1
- import Search from '@/components/Search' ;
2
- import { Sidebar } from '@/components/Sidebar' ;
3
1
import { NavLink } from '@remix-run/react' ;
4
- import { atom , useAtom } from 'jotai' ;
5
- import { useEffect , useRef , useState } from 'react' ;
2
+ import { useEffect , useState } from 'react' ;
6
3
4
+ import Search from '~/components/Search' ;
5
+ import { Sidebar } from '~/components/Sidebar' ;
7
6
import { useDocumentScroll } from '~/hooks' ;
8
7
9
8
const NavHeight = 68 ;
@@ -12,24 +11,57 @@ const MaxPaddingBottom = 36;
12
11
const SearchHeight = NavHeight ;
13
12
14
13
export const useHero = ( ) => {
14
+ const [ isClient , setIsClient ] = useState ( false ) ;
15
+
16
+ useEffect ( ( ) => {
17
+ setIsClient ( true ) ;
18
+ } , [ ] ) ;
19
+
15
20
const { y } = useDocumentScroll ( ) ;
16
21
17
22
const paddingTop = y <= MaxPaddingTop ? MaxPaddingTop - y : 0 ;
18
23
19
- const paddingBottom = Math . max ( y > MaxPaddingTop ? MaxPaddingBottom - ( y - MaxPaddingTop ) : MaxPaddingBottom , 0 ) ;
24
+ const paddingBottom = Math . max (
25
+ y > MaxPaddingTop ? MaxPaddingBottom - ( y - MaxPaddingTop ) : MaxPaddingBottom ,
26
+ 0
27
+ ) ;
20
28
21
29
const height = paddingTop + SearchHeight + paddingBottom ;
22
30
23
- return { height, paddingTop, paddingBottom } ;
31
+ return {
32
+ height,
33
+ paddingTop,
34
+ paddingBottom,
35
+ injectScript : `requestAnimationFrame(() => {
36
+ const y = document.documentElement.scrollTop;
37
+ const paddingTop = y <= ${ MaxPaddingTop } ? ${ MaxPaddingTop } - y : 0;
38
+ const paddingBottom = Math.max(
39
+ y > ${ MaxPaddingTop } ? ${ MaxPaddingBottom } - (y - ${ MaxPaddingTop } ) : ${ MaxPaddingBottom } ,
40
+ 0
41
+ );
42
+ const height = paddingTop + ${ SearchHeight } + paddingBottom;
43
+
44
+ const hero = document.querySelector('.hero');
45
+ if (hero) hero.style.height = height + 'px';
46
+ const top = document.querySelector('.hero-top');
47
+ if (top) top.style.top = (paddingTop - ${ MaxPaddingTop } ) + 'px';
48
+ const search = document.querySelector('.hero-search');
49
+ if (search) search.style.top = paddingTop + 'px';
50
+ const bottom = document.querySelector('.hero-bottom');
51
+ if (bottom) { bottom.style.top = (paddingTop + ${ SearchHeight } ) + 'px'; bottom.style.height = paddingBottom + 'px'; }
52
+ });`
53
+ } ;
24
54
} ;
25
55
26
56
export default function Layout ( props : { children ?: React . ReactNode } ) {
27
- const { height, paddingTop, paddingBottom } = useHero ( ) ;
28
-
29
57
return (
30
58
< div className = "w-full" style = { { '--nav-height' : `${ NavHeight } px` } } >
31
- < Hero height = { height } paddingTop = { paddingTop } paddingBottom = { paddingBottom } > </ Hero >
32
- < div className = "flex" style = { { paddingTop : `${ MaxPaddingTop + NavHeight + MaxPaddingBottom } px` } } >
59
+ < Hero > </ Hero >
60
+ < div
61
+ className = "flex"
62
+ style = { { paddingTop : `${ MaxPaddingTop + NavHeight + MaxPaddingBottom } px` } }
63
+ > </ div >
64
+ < div className = "w-full flex" >
33
65
< Sidebar > </ Sidebar >
34
66
< div className = "flex-auto flex items-center" >
35
67
< div className = "main" > { props . children } </ div >
@@ -39,39 +71,78 @@ export default function Layout(props: { children?: React.ReactNode }) {
39
71
) ;
40
72
}
41
73
42
- function Hero ( props : { height : number , paddingTop : number ; paddingBottom : number } ) {
43
- const { height, paddingTop, paddingBottom } = props ;
74
+ function Hero ( ) {
75
+ const { height, paddingTop, paddingBottom, injectScript } = useHero ( ) ;
44
76
45
77
return (
46
- < div className = "w-full fixed bg-[#fef8f7]" style = { { height : `${ height } px` } } >
78
+ < div className = "w-full" >
79
+ < div
80
+ className = "hero z-1 w-full fixed bg-[#fef8f7] border-b border-b-gray-200"
81
+ suppressHydrationWarning = { true }
82
+ style = { { height : `${ height } px` } }
83
+ > </ div >
47
84
< Header > </ Header >
48
- < div className = "hero-top w-full pt-4rem pb-3rem text-4xl font-quicksand font-bold text-center select-none outline-none absolute pointer-events-none" style = { { top : `${ paddingTop - MaxPaddingTop } px` } } >
49
- < NavLink to = "/" className = "pointer-events-auto cursor-pointer" > 🌸 Anime Garden</ NavLink >
85
+ < div
86
+ className = "hero-top z-10 fixed w-full pt-4rem pb-3rem text-4xl font-quicksand font-bold text-center select-none outline-none pointer-events-none"
87
+ suppressHydrationWarning = { true }
88
+ style = { { top : `${ paddingTop - MaxPaddingTop } px` } }
89
+ >
90
+ < NavLink to = "/" className = "pointer-events-auto cursor-pointer" >
91
+ 🌸 Anime Garden
92
+ </ NavLink >
50
93
</ div >
51
- < div className = "w-full flex justify-center absolute z-10" style = { { top : `${ paddingTop } px` , paddingTop : '8px' , paddingBottom : '8px' } } >
94
+ < div
95
+ className = "hero-search w-full flex justify-center fixed z-10"
96
+ suppressHydrationWarning = { true }
97
+ style = { { top : `${ paddingTop } px` , paddingTop : '8px' , paddingBottom : '8px' } }
98
+ >
52
99
< div className = "h-[52px]" >
53
100
< Search > </ Search >
54
101
</ div >
55
102
</ div >
56
- < div className = "hero-bottom w-full absolute" style = { { top : `${ paddingTop + SearchHeight } px` , height : `${ paddingBottom } px` } } > </ div >
103
+ < div
104
+ className = "hero-bottom z-10 fixed w-full"
105
+ suppressHydrationWarning = { true }
106
+ style = { { top : `${ paddingTop + SearchHeight } px` , height : `${ paddingBottom } px` } }
107
+ > </ div >
108
+ { injectScript && (
109
+ < script
110
+ dangerouslySetInnerHTML = { {
111
+ __html : injectScript
112
+ } }
113
+ />
114
+ ) }
57
115
</ div >
58
116
) ;
59
117
}
60
118
61
119
function Header ( ) {
62
- return < nav className = "px-8 h-$nav-height flex gap-4 z-1 [&>div]:leading-$nav-height" >
63
- < div className = "text-2xl font-quicksand font-bold" > < NavLink to = "/" > 🌸</ NavLink > </ div >
64
- < div > < NavLink to = "/" className = "rounded-md p-2 hover:(bg-neutral-200)" > 动画</ NavLink > </ div >
65
- < div > < NavLink to = "/resources" className = "rounded-md p-2 hover:(bg-neutral-200)" > 资源</ NavLink > </ div >
66
- < div className = 'flex-auto' > </ div >
67
- < div >
68
- < a
69
- href = { '' }
70
- target = "_blank"
71
- className = "inline cursor-pointer rounded-md p-2 text-[#ee802f] hover:(!text-[#ff7800] !border-b-[#ff7800] bg-neutral-200)"
72
- >
73
- < span className = "i-carbon-rss mr1" /> < span > RSS</ span >
74
- </ a >
75
- </ div >
76
- </ nav >
77
- }
120
+ return (
121
+ < nav className = "z-11 fixed w-full px-8 h-$nav-height flex gap-4 [&>div]:leading-$nav-height" >
122
+ < div className = "text-2xl font-quicksand font-bold" >
123
+ < NavLink to = "/" > 🌸</ NavLink >
124
+ </ div >
125
+ < div >
126
+ < NavLink to = "/" className = "rounded-md p-2 hover:(bg-neutral-200)" >
127
+ 动画
128
+ </ NavLink >
129
+ </ div >
130
+ < div >
131
+ < NavLink to = "/resources" className = "rounded-md p-2 hover:(bg-neutral-200)" >
132
+ 资源
133
+ </ NavLink >
134
+ </ div >
135
+ < div className = "flex-auto" > </ div >
136
+ < div >
137
+ < a
138
+ href = { '' }
139
+ target = "_blank"
140
+ className = "inline cursor-pointer rounded-md p-2 text-[#ee802f] hover:(!text-[#ff7800] !border-b-[#ff7800] bg-neutral-200)"
141
+ >
142
+ < span className = "i-carbon-rss mr1" />
143
+ < span > RSS</ span >
144
+ </ a >
145
+ </ div >
146
+ </ nav >
147
+ ) ;
148
+ }
0 commit comments