Skip to content

Commit 0ead8d6

Browse files
committed
refactor(app): consolidate theme and sidebar settings into appSettings
- Replace useCustomize with useAppSettings for unified configuration management - Add AppSettings type definition and move sidebar config under appSettings - Update components to use new appSettings structure - Add .nvmrc and .npmrc for consistent environment setup
1 parent 8ea98f3 commit 0ead8d6

File tree

13 files changed

+101
-97
lines changed

13 files changed

+101
-97
lines changed

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
shamefully-hoist=true

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
22.20.0

README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,30 @@
1010
## Quick Start
1111

1212
```bash [Terminal]
13-
npx degit dianprata/nuxt-shadcn-dashboard my-dashboard-app
13+
npx nuxi@latest init -t github:dianprata/nuxt-shadcn-dashboard my-dashboard-app
1414
cd my-dashboard-app
1515
pnpm i # If you don't have pnpm installed, run: npm install -g pnpm
1616
```
1717

18+
## App Settings
19+
You can change the app settings in `app.config.ts` file.
20+
If you want to change app settings, you have to clear cookie 'app_settings' first.
21+
```json [app.config.ts]
22+
export default defineAppConfig({
23+
appSettings: {
24+
sidebar: {
25+
collapsible: 'offcanvas', // 'offcanvas' | 'icon' | 'none'
26+
side: 'left', // 'left' | 'right'
27+
variant: 'inset', // 'sidebar' | 'floating' | 'inset'
28+
},
29+
theme: {
30+
color: 'default', // 'default' | 'blue' | 'green' | 'orange' | 'purple' | 'red' | 'teal' | 'yellow' | 'rose'
31+
type: 'scaled', // 'default' | 'mono' | 'scaled'
32+
}
33+
},
34+
})
35+
```
36+
1837
## Contributing
1938

2039
1. Clone this repository.

app/app.config.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ export default defineAppConfig({
33
size: '', // default <Icon> size applied
44
class: '', // default <Icon> class applied
55
},
6-
sidebar: {
7-
collapsible: 'offcanvas', // 'offcanvas' | 'icon' | 'none'
8-
side: 'left', // 'left' | 'right'
9-
variant: 'sidebar', // 'sidebar' | 'floating' | 'inset'
6+
appSettings: {
7+
sidebar: {
8+
collapsible: 'offcanvas', // 'offcanvas' | 'icon' | 'none'
9+
side: 'left', // 'left' | 'right'
10+
variant: 'inset', // 'sidebar' | 'floating' | 'inset'
11+
}
1012
},
1113
})

app/app.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import 'vue-sonner/style.css'
55
66
const colorMode = useColorMode()
77
const color = computed(() => colorMode.value === 'dark' ? '#09090b' : '#ffffff')
8-
const { color: activeColor, type } = useCustomize()
8+
const { theme } = useAppSettings()
99
1010
useHead({
1111
meta: [
@@ -20,7 +20,7 @@ useHead({
2020
lang: 'en',
2121
},
2222
bodyAttrs: {
23-
class: computed(() => `color-${activeColor.value} theme-${type.value}`),
23+
class: computed(() => `color-${theme.value?.color || 'default'} theme-${theme.value?.type || 'default'}`),
2424
},
2525
})
2626

app/components/AppSettings.vue

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ const isDesktop = useMediaQuery('(min-width: 768px)')
44
55
const isOpen = ref(false)
66
7-
const { sidebar } = useAppSettings()
7+
const { sidebar, updateAppSettings } = useAppSettings()
88
99
const direction = useTextDirection()
1010
1111
function handleChangeDirection(dir: 'ltr' | 'rtl') {
1212
direction.value = dir
13-
sidebar.value.side = dir === 'rtl' ? 'right' : 'left'
13+
updateAppSettings({ sidebar: { side: dir === 'rtl' ? 'right' : 'left' } })
1414
}
1515
</script>
1616

@@ -24,22 +24,22 @@ function handleChangeDirection(dir: 'ltr' | 'rtl') {
2424
<div class="grid grid-cols-3 gap-2">
2525
<Button
2626
variant="outline"
27-
:class="{ '!border-primary border-2 !bg-primary/10': sidebar.variant === 'sidebar' }"
28-
@click="sidebar.variant = 'sidebar'"
27+
:class="{ '!border-primary border-2 !bg-primary/10': sidebar?.variant === 'sidebar' }"
28+
@click="updateAppSettings({ sidebar: { variant: 'sidebar' } })"
2929
>
3030
Sidebar
3131
</Button>
3232
<Button
3333
variant="outline"
34-
:class="{ '!border-primary border-2 !bg-primary/10': sidebar.variant === 'floating' }"
35-
@click="sidebar.variant = 'floating'"
34+
:class="{ '!border-primary border-2 !bg-primary/10': sidebar?.variant === 'floating' }"
35+
@click="updateAppSettings({ sidebar: { variant: 'floating' } })"
3636
>
3737
Floating
3838
</Button>
3939
<Button
4040
variant="outline"
41-
:class="{ '!border-primary border-2 !bg-primary/10': sidebar.variant === 'inset' }"
42-
@click="sidebar.variant = 'inset'"
41+
:class="{ '!border-primary border-2 !bg-primary/10': sidebar?.variant === 'inset' }"
42+
@click="updateAppSettings({ sidebar: { variant: 'inset' } })"
4343
>
4444
Inset
4545
</Button>

app/components/ThemeCustomize.vue

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,31 @@
22
import type { ThemeColor, ThemeType } from '@/constants/themes'
33
import { THEME_COLORS, THEME_TYPE } from '@/constants/themes'
44
5-
const { color, setColor, type, setThemeType } = useCustomize()
5+
const { theme, updateAppSettings } = useAppSettings()
66
77
const allColors: ThemeColor[] = THEME_COLORS.map(color => color.name)
88
const allTypes: ThemeType[] = THEME_TYPE
99
10-
watch(color, () => {
10+
watch(() => theme.value?.color, () => {
1111
setClassColor()
1212
})
1313
1414
function setClassColor() {
1515
document.body.classList.remove(
1616
...allColors.map(color => `color-${color}`),
1717
)
18-
document.body.classList.add(`color-${color.value}`)
18+
document.body.classList.add(`color-${theme.value?.color || 'default'}`)
1919
}
2020
21-
watch(type, () => {
21+
watch(() => theme.value?.type, () => {
2222
setClassType()
2323
})
2424
2525
function setClassType() {
2626
document.body.classList.remove(
2727
...allTypes.map(type => `theme-${type}`),
2828
)
29-
document.body.classList.add(`theme-${type.value}`)
29+
document.body.classList.add(`theme-${theme.value?.type || 'default'}`)
3030
}
3131
3232
function backgroundColor(color: ThemeColor) {
@@ -46,11 +46,11 @@ const colorMode = useColorMode()
4646
<Button
4747
class="justify-start gap-2"
4848
variant="outline"
49-
:class="{ '!border-primary border-2 !bg-primary/10': color === col }"
50-
@click="setColor(col)"
49+
:class="{ '!border-primary border-2 !bg-primary/10': theme?.color === col }"
50+
@click="updateAppSettings({ theme: { color: col } })"
5151
>
5252
<span class="h-5 w-5 flex items-center justify-center rounded-full border border-white" :style="{ backgroundColor: backgroundColor(col) }">
53-
<Icon v-if="col === color" name="i-radix-icons-check" size="16" class="text-white" />
53+
<Icon v-if="col === theme?.color" name="i-radix-icons-check" size="16" class="text-white" />
5454
</span>
5555
<span class="text-xs capitalize">{{ col }}</span>
5656
</Button>
@@ -64,8 +64,8 @@ const colorMode = useColorMode()
6464
<Button
6565
class="justify-center gap-2"
6666
variant="outline"
67-
:class="{ '!border-primary border-2 !bg-primary/10': themeType === type }"
68-
@click="setThemeType(themeType)"
67+
:class="{ '!border-primary border-2 !bg-primary/10': theme?.type === themeType }"
68+
@click="updateAppSettings({ theme: { type: themeType } })"
6969
>
7070
<span class="text-xs capitalize">{{ themeType }}</span>
7171
</Button>

app/components/layout/AppSidebar.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const { sidebar } = useAppSettings()
4545
</script>
4646

4747
<template>
48-
<Sidebar :collapsible="sidebar.collapsible" :side="sidebar.side" :variant="sidebar.variant">
48+
<Sidebar :collapsible="sidebar?.collapsible" :side="sidebar?.side" :variant="sidebar?.variant">
4949
<SidebarHeader>
5050
<LayoutSidebarNavHeader :teams="teams" />
5151
<Search />

app/composables/useAppSettings.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,42 @@
1-
import type { AppConfigInput } from 'nuxt/schema'
1+
import type { AppSettings } from '~/types/appSettings'
2+
3+
import { createDefu } from 'defu';
4+
5+
const customDefu = createDefu((obj, key, value) => {
6+
if (Array.isArray(value) && value.every((x: any) => typeof x === 'string')) {
7+
obj[key] = value;
8+
return true;
9+
}
10+
});
11+
12+
const defaultAppSettings: AppSettings = {
13+
sidebar: {
14+
collapsible: 'offcanvas',
15+
side: 'left',
16+
variant: 'sidebar',
17+
},
18+
theme: {
19+
color: 'default',
20+
type: 'default',
21+
}
22+
}
223

324
export function useAppSettings() {
4-
const { sidebar: _sidebar } = useAppConfig()
5-
6-
const sidebar = useCookie('app-settings', {
7-
default: () => ({
8-
collapsible: _sidebar.collapsible,
9-
side: _sidebar.side,
10-
variant: _sidebar.variant,
11-
}) as AppConfigInput['sidebar'],
25+
const { appSettings } = useAppConfig()
26+
27+
const processedConfig = customDefu(appSettings, defaultAppSettings);
28+
29+
const cookieAppSettings = useCookie<AppSettings>('app_settings', {
30+
default: () => processedConfig,
1231
})
1332

33+
const updateAppSettings = (settings: AppSettings) => {
34+
cookieAppSettings.value = customDefu(settings, cookieAppSettings.value)
35+
}
36+
1437
return {
15-
sidebar,
38+
updateAppSettings,
39+
sidebar: computed(() => cookieAppSettings.value.sidebar),
40+
theme: computed(() => cookieAppSettings.value.theme),
1641
}
1742
}

app/composables/useCustomize.ts

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)