|
5 | 5 | <v-app-bar :elevation="0"> |
6 | 6 | <v-app-bar-nav-icon |
7 | 7 | variant="text" color="default" class="mr-1" size="small" density="comfortable" |
8 | | - @click.stop="drawer = !drawer" |
| 8 | + @click.stop="!mdAndUp ? drawer = !drawer : rail = !rail" |
9 | 9 | /> |
10 | 10 |
|
11 | 11 | <v-app-bar-title class="mx-1"> |
12 | 12 | <router-link v-if="featureFlags.dashboard" to="/dashboard"> |
13 | | - <v-img v-if="theme.global.current.value.dark" src="@/assets/logo-dark.svg" width="172" alt="Storj Logo" /> |
| 13 | + <v-img v-if="themeStore.globalTheme?.dark" src="@/assets/logo-dark.svg" width="172" alt="Storj Logo" /> |
14 | 14 | <v-img v-else src="@/assets/logo.svg" width="172" alt="Storj Logo" /> |
15 | 15 | </router-link> |
16 | 16 | <div v-else> |
17 | | - <v-img v-if="theme.global.current.value.dark" src="@/assets/logo-dark.svg" width="172" alt="Storj Logo" /> |
| 17 | + <v-img v-if="themeStore.globalTheme?.dark" src="@/assets/logo-dark.svg" width="172" alt="Storj Logo" /> |
18 | 18 | <v-img v-else src="@/assets/logo.svg" width="172" alt="Storj Logo" /> |
19 | 19 | </div> |
20 | 20 | </v-app-bar-title> |
21 | 21 |
|
22 | 22 | <template #append> |
23 | | - <!-- Theme Toggle Light/Dark Mode --> |
24 | | - <v-btn-toggle v-model="activeTheme" mandatory border inset rounded="lg" density="compact"> |
25 | | - <v-tooltip text="Light Theme" location="bottom"> |
26 | | - <template #activator="{ props }"> |
27 | | - <v-btn |
28 | | - v-bind="props" :icon="Sun" size="x-small" class="px-4" aria-label="Toggle Light Theme" |
29 | | - @click="toggleTheme('light')" |
30 | | - /> |
31 | | - </template> |
32 | | - </v-tooltip> |
33 | | - |
34 | | - <v-tooltip text="Dark Theme" location="bottom"> |
35 | | - <template #activator="{ props }"> |
36 | | - <v-btn |
37 | | - v-bind="props" :icon="MoonStar" size="x-small" class="px-4" aria-label="Toggle Dark Theme" |
38 | | - @click="toggleTheme('dark')" |
39 | | - /> |
40 | | - </template> |
41 | | - </v-tooltip> |
42 | | - </v-btn-toggle> |
| 23 | + <v-menu offset-y width="200" class="rounded-xl"> |
| 24 | + <template #activator="{ props: activatorProps }"> |
| 25 | + <v-btn |
| 26 | + class="mr-2" |
| 27 | + v-bind="activatorProps" |
| 28 | + variant="outlined" |
| 29 | + color="default" |
| 30 | + rounded="lg" |
| 31 | + :icon="activeThemeIcon" |
| 32 | + /> |
| 33 | + </template> |
| 34 | + |
| 35 | + <v-list class="px-2 rounded-lg"> |
| 36 | + <v-list-item :active="activeTheme === 0" class="px-2" @click="themeStore.setTheme('light')"> |
| 37 | + <v-list-item-title class="text-body-2"> |
| 38 | + <v-btn |
| 39 | + class="mr-2" |
| 40 | + variant="outlined" |
| 41 | + color="default" |
| 42 | + size="x-small" |
| 43 | + rounded="lg" |
| 44 | + :icon="Sun" |
| 45 | + /> |
| 46 | + Light |
| 47 | + </v-list-item-title> |
| 48 | + </v-list-item> |
| 49 | + |
| 50 | + <v-list-item :active="activeTheme === 1" class="px-2" @click="themeStore.setTheme('dark')"> |
| 51 | + <v-list-item-title class="text-body-2"> |
| 52 | + <v-btn |
| 53 | + class="mr-2" |
| 54 | + variant="outlined" |
| 55 | + color="default" |
| 56 | + size="x-small" |
| 57 | + rounded="lg" |
| 58 | + :icon="MoonStar" |
| 59 | + /> |
| 60 | + Dark |
| 61 | + </v-list-item-title> |
| 62 | + </v-list-item> |
| 63 | + |
| 64 | + <v-list-item :active="activeTheme === 2" class="px-2" @click="themeStore.setTheme('auto')"> |
| 65 | + <v-list-item-title class="text-body-2"> |
| 66 | + <v-btn |
| 67 | + class="mr-2" |
| 68 | + variant="outlined" |
| 69 | + color="default" |
| 70 | + size="x-small" |
| 71 | + rounded="lg" |
| 72 | + :icon="smAndDown ? Smartphone : Monitor" |
| 73 | + /> |
| 74 | + System |
| 75 | + </v-list-item-title> |
| 76 | + </v-list-item> |
| 77 | + </v-list> |
| 78 | + </v-menu> |
43 | 79 |
|
44 | 80 | <v-menu offset-y class="rounded-xl"> |
45 | 81 | <template v-if="featureFlags.switchSatellite && featureFlags.operator &&featureFlags.signOut" #activator="{ props }"> |
|
86 | 122 | </template> |
87 | 123 | </v-app-bar> |
88 | 124 |
|
89 | | - <v-navigation-drawer v-model="drawer" color="surface"> |
| 125 | + <v-navigation-drawer v-model="drawer" :rail="mdAndUp && rail" :permanent="mdAndUp" color="surface"> |
90 | 126 | <v-sheet> |
91 | | - <v-list class="px-2" variant="flat"> |
| 127 | + <v-list density="compact" nav> |
92 | 128 | <v-list-item v-if="featureFlags.switchSatellite" link class="pa-4 rounded-lg"> |
93 | 129 | <v-menu activator="parent" location="end" transition="scale-transition"> |
94 | 130 | <v-list class="pa-2"> |
|
166 | 202 | <!-- This view is temporary until we implement list with search --> |
167 | 203 | <v-list-item v-if="featureFlags.account.search" link router-link to="/account-search" class="my-1" rounded="lg"> |
168 | 204 | <template #prepend> |
169 | | - <img src="@/assets/icon-team.svg" alt="Accounts"> |
| 205 | + <v-icon :icon="UserRoundSearch" /> |
170 | 206 | </template> |
171 | 207 | <v-list-item-title class="text-body-2 ml-3"> |
172 | 208 | Search account |
|
187 | 223 | </template> |
188 | 224 |
|
189 | 225 | <script setup lang="ts"> |
190 | | -import { ref, watch } from 'vue'; |
| 226 | +import { computed, ref } from 'vue'; |
191 | 227 | import { |
192 | 228 | VAppBar, |
193 | 229 | VAppBarNavIcon, |
194 | 230 | VAppBarTitle, |
195 | | - VImg, |
196 | | - VMenu, |
197 | | - VBtnToggle, |
198 | 231 | VBtn, |
199 | | - VTooltip, |
| 232 | + VDivider, |
200 | 233 | VIcon, |
| 234 | + VImg, |
201 | 235 | VList, |
202 | 236 | VListItem, |
203 | | - VListItemTitle, |
204 | 237 | VListItemSubtitle, |
205 | | - VDivider, |
| 238 | + VListItemTitle, |
| 239 | + VMenu, |
206 | 240 | VNavigationDrawer, |
207 | 241 | VSheet, |
208 | 242 | } from 'vuetify/components'; |
209 | | -import { useTheme } from 'vuetify'; |
210 | | -import { MoonStar, Sun } from 'lucide-vue-next'; |
| 243 | +import { useDisplay } from 'vuetify'; |
| 244 | +import { Monitor, MoonStar, Smartphone, Sun, UserRoundSearch } from 'lucide-vue-next'; |
211 | 245 |
|
212 | 246 | import { FeatureFlags } from '@/api/client.gen'; |
213 | 247 | import { useAppStore } from '@/store/app'; |
| 248 | +import { useThemeStore } from '@/store/theme'; |
| 249 | +
|
| 250 | +const appStore = useAppStore(); |
| 251 | +const themeStore = useThemeStore(); |
| 252 | +const { mdAndUp, smAndDown } = useDisplay(); |
214 | 253 |
|
215 | | -const theme = useTheme(); |
216 | 254 | const drawer = ref<boolean>(true); |
217 | | -const activeTheme = ref<number>(0); |
218 | | -const featureFlags = useAppStore().state.settings.admin.features as FeatureFlags; |
| 255 | +const rail = ref<boolean>(true); |
219 | 256 |
|
220 | | -function toggleTheme(newTheme: string) { |
221 | | - if ((newTheme === 'dark' && theme.global.current.value.dark) || (newTheme === 'light' && !theme.global.current.value.dark)) { |
222 | | - return; |
| 257 | +const activeTheme = computed<number>(() => { |
| 258 | + switch (themeStore.state.name) { |
| 259 | + case 'light': |
| 260 | + return 0; |
| 261 | + case 'dark': |
| 262 | + return 1; |
| 263 | + default: |
| 264 | + return 2; |
223 | 265 | } |
224 | | - theme.global.name.value = newTheme; |
225 | | - localStorage.setItem('theme', newTheme); // Store the selected theme in localStorage |
226 | | -} |
| 266 | +}); |
227 | 267 |
|
228 | | -watch(() => theme.global.current.value.dark, newVal => { |
229 | | - activeTheme.value = newVal ? 1 : 0; |
| 268 | +const activeThemeIcon = computed(() => { |
| 269 | + switch (themeStore.state.name) { |
| 270 | + case 'light': |
| 271 | + return Sun; |
| 272 | + case 'dark': |
| 273 | + return MoonStar; |
| 274 | + default: |
| 275 | + return themeStore.globalTheme?.dark ? MoonStar : Sun; |
| 276 | + } |
230 | 277 | }); |
231 | 278 |
|
232 | | -// Check for stored theme in localStorage. If none, default to 'light' |
233 | | -toggleTheme(localStorage.getItem('theme') || 'light'); |
234 | | -activeTheme.value = theme.global.current.value.dark ? 1 : 0; |
| 279 | +const featureFlags = computed(() => appStore.state.settings.admin.features as FeatureFlags); |
235 | 280 | </script> |
0 commit comments