@@ -2,18 +2,36 @@ import {
2
2
IconFileStack ,
3
3
IconGlobe ,
4
4
IconHome ,
5
- IconMenu ,
6
5
IconNetwork ,
7
6
IconPalette ,
8
7
IconRuler ,
9
8
IconSettings ,
10
9
} from '@tabler/icons-solidjs'
11
- import type { ParentComponent } from 'solid-js'
10
+ import type { JSX , ParentComponent } from 'solid-js'
12
11
import { LogoText } from '~/components'
13
12
import { ROUTES , themes } from '~/constants'
14
13
import { useI18n } from '~/i18n'
15
14
import { setCurTheme } from '~/signals'
16
15
16
+ interface NavItem {
17
+ href : string
18
+ name : string
19
+ icon : JSX . Element
20
+ }
21
+
22
+ const useNavItems = ( ) => {
23
+ const [ t ] = useI18n ( )
24
+
25
+ return [
26
+ { href : ROUTES . Overview , name : t ( 'overview' ) , icon : < IconHome /> } ,
27
+ { href : ROUTES . Proxies , name : t ( 'proxies' ) , icon : < IconGlobe /> } ,
28
+ { href : ROUTES . Rules , name : t ( 'rules' ) , icon : < IconRuler /> } ,
29
+ { href : ROUTES . Conns , name : t ( 'connections' ) , icon : < IconNetwork /> } ,
30
+ { href : ROUTES . Log , name : t ( 'logs' ) , icon : < IconFileStack /> } ,
31
+ { href : ROUTES . Config , name : t ( 'config' ) , icon : < IconSettings /> } ,
32
+ ] as NavItem [ ]
33
+ }
34
+
17
35
const Nav : ParentComponent < { href : string ; tooltip : string } > = ( {
18
36
href,
19
37
tooltip,
@@ -59,102 +77,90 @@ const ThemeSwitcher = () => (
59
77
</ div >
60
78
)
61
79
62
- export const Header = ( ) => {
63
- const [ t ] = useI18n ( )
64
- const navs = ( ) => [
65
- {
66
- href : ROUTES . Overview ,
67
- name : t ( 'overview' ) ,
68
- icon : < IconHome /> ,
69
- } ,
70
- {
71
- href : ROUTES . Proxies ,
72
- name : t ( 'proxies' ) ,
73
- icon : < IconGlobe /> ,
74
- } ,
75
- {
76
- href : ROUTES . Rules ,
77
- name : t ( 'rules' ) ,
78
- icon : < IconRuler /> ,
79
- } ,
80
- {
81
- href : ROUTES . Conns ,
82
- name : t ( 'connections' ) ,
83
- icon : < IconNetwork /> ,
84
- } ,
85
- {
86
- href : ROUTES . Log ,
87
- name : t ( 'logs' ) ,
88
- icon : < IconFileStack /> ,
89
- } ,
90
- {
91
- href : ROUTES . Config ,
92
- name : t ( 'config' ) ,
93
- icon : < IconSettings /> ,
94
- } ,
95
- ]
96
-
80
+ const MobileBottomNav = ( ) => {
81
+ const navs = useNavItems ( )
97
82
const location = useLocation ( )
98
83
99
- const [ openedDrawer , setOpenedDrawer ] = createSignal ( false )
84
+ createEffect ( ( ) => {
85
+ const shouldShow = location . pathname !== ROUTES . Setup
86
+ document . body . style . paddingBottom =
87
+ shouldShow && window . innerWidth < 1024 ? '4rem' : '0'
88
+ } )
89
+
90
+ onCleanup ( ( ) => {
91
+ document . body . style . paddingBottom = '0'
92
+ } )
93
+
94
+ return (
95
+ < Show when = { location . pathname !== ROUTES . Setup } >
96
+ < nav class = "fixed inset-x-0 bottom-0 z-50 border-t border-base-content/10 bg-base-300/95 backdrop-blur-sm lg:hidden" >
97
+ < div class = "grid h-16 grid-cols-6" >
98
+ < For each = { navs } >
99
+ { ( { href, name, icon } ) => {
100
+ const isActive = ( ) => location . pathname === href
101
+
102
+ return (
103
+ < A
104
+ href = { href }
105
+ class = "relative flex flex-col items-center justify-center gap-1 transition-all duration-200 hover:bg-base-200/50"
106
+ >
107
+ < Show when = { isActive ( ) } >
108
+ < div class = "absolute top-0 left-1/2 h-1 w-8 -translate-x-1/2 transform rounded-b-full bg-primary" />
109
+ </ Show >
110
+ < div
111
+ class = "text-xl transition-all duration-200"
112
+ classList = { {
113
+ 'text-primary scale-110' : isActive ( ) ,
114
+ 'text-base-content/70' : ! isActive ( ) ,
115
+ } }
116
+ >
117
+ { icon }
118
+ </ div >
119
+ < Show when = { isActive ( ) } >
120
+ < span class = "animate-in fade-in slide-in-from-bottom-1 text-xs font-medium text-primary duration-200" >
121
+ { name }
122
+ </ span >
123
+ </ Show >
124
+ </ A >
125
+ )
126
+ } }
127
+ </ For >
128
+ </ div >
129
+ </ nav >
130
+ </ Show >
131
+ )
132
+ }
133
+
134
+ export const Header = ( ) => {
135
+ const navs = useNavItems ( )
136
+ const location = useLocation ( )
100
137
101
138
return (
102
- < ul class = "z-50 navbar flex w-auto items-center justify-center bg-base-300 px-4 shadow-lg" >
103
- < div class = "navbar-start gap-4" >
104
- < div class = "drawer w-auto lg:hidden" >
105
- < input
106
- id = "navs"
107
- type = "checkbox"
108
- class = "drawer-toggle"
109
- onChange = { ( e ) => setOpenedDrawer ( e . target . checked ) }
110
- checked = { openedDrawer ( ) }
111
- />
112
-
113
- < div class = "drawer-content flex w-6 items-center" >
114
- < label for = "navs" class = "drawer-button btn btn-circle btn-sm" >
115
- < IconMenu />
116
- </ label >
117
- </ div >
118
-
119
- < div class = "drawer-side" >
120
- < label for = "navs" class = "drawer-overlay" />
121
-
122
- < ul class = "menu min-h-full min-w-2/5 gap-2 rounded-r-box bg-base-300 pt-20" >
123
- < For each = { navs ( ) } >
139
+ < >
140
+ < header class = "z-50 navbar flex w-auto items-center justify-center bg-base-300 px-4 shadow-lg" >
141
+ < div class = "navbar-start" >
142
+ < LogoText />
143
+ </ div >
144
+
145
+ < Show when = { location . pathname !== ROUTES . Setup } >
146
+ < nav class = "navbar-center hidden lg:flex" >
147
+ < ul class = "menu menu-horizontal gap-2 menu-lg p-0" >
148
+ < For each = { navs } >
124
149
{ ( { href, name, icon } ) => (
125
- < li onClick = { ( ) => setOpenedDrawer ( false ) } >
126
- < A href = { href } activeClass = "menu-active" >
127
- { icon } { name }
128
- </ A >
129
- </ li >
150
+ < Nav href = { href } tooltip = { name } >
151
+ { icon }
152
+ </ Nav >
130
153
) }
131
154
</ For >
132
155
</ ul >
133
- </ div >
134
- </ div >
135
-
136
- < LogoText />
137
- </ div >
138
-
139
- < Show when = { location . pathname !== ROUTES . Setup } >
140
- < div class = "navbar-center hidden lg:flex" >
141
- < ul class = "menu menu-horizontal gap-2 menu-lg p-0" >
142
- < For each = { navs ( ) } >
143
- { ( { href, name, icon } ) => (
144
- < Nav href = { href } tooltip = { name } >
145
- { icon }
146
- </ Nav >
147
- ) }
148
- </ For >
149
- </ ul >
150
- </ div >
151
- </ Show >
156
+ </ nav >
157
+ </ Show >
152
158
153
- < div class = "navbar-end" >
154
- < div class = "flex items-center gap-2" >
159
+ < div class = "navbar-end" >
155
160
< ThemeSwitcher />
156
161
</ div >
157
- </ div >
158
- </ ul >
162
+ </ header >
163
+ < MobileBottomNav />
164
+ </ >
159
165
)
160
166
}
0 commit comments