feat: add style switcher
This commit is contained in:
parent
22e548f452
commit
b37ba515dd
20
apps/www/.vitepress/theme/components/ComponentLoader.vue
Normal file
20
apps/www/.vitepress/theme/components/ComponentLoader.vue
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<script setup lang="ts">
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import Spinner from './Spinner.vue'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
}>()
|
||||
const { style } = useConfigStore()
|
||||
|
||||
const Component = defineAsyncComponent({
|
||||
loadingComponent: Spinner,
|
||||
loader: () => import(`../../../src/lib/registry/${style.value}/example/${props.name}.vue`),
|
||||
timeout: 5000,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Component :is="Component" />
|
||||
</template>
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import Spinner from './Spinner.vue'
|
||||
import StyleSwitcher from './StyleSwitcher.vue'
|
||||
import ComponentLoader from './ComponentLoader.vue'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/lib/registry/default/ui/tabs'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
|
|
@ -11,11 +12,7 @@ const props = withDefaults(defineProps<{
|
|||
sfcTsHtml?: string
|
||||
}>(), { align: 'center' })
|
||||
|
||||
const Component = defineAsyncComponent({
|
||||
loadingComponent: Spinner,
|
||||
loader: () => import(`../../../src/lib/registry/default/example/${props.name}.vue`),
|
||||
timeout: 5000,
|
||||
})
|
||||
const { style } = useConfigStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -40,6 +37,9 @@ const Component = defineAsyncComponent({
|
|||
</TabsList>
|
||||
</div>
|
||||
<TabsContent value="preview" class="relative rounded-md border">
|
||||
<div className="flex items-center justify-between p-4">
|
||||
<StyleSwitcher />
|
||||
</div>
|
||||
<div
|
||||
:class="cn('preview flex min-h-[350px] w-full justify-center p-10', {
|
||||
'items-center': align === 'center',
|
||||
|
|
@ -47,7 +47,7 @@ const Component = defineAsyncComponent({
|
|||
'items-end': align === 'end',
|
||||
})"
|
||||
>
|
||||
<Component :is="Component" />
|
||||
<ComponentLoader :key="style" :name="name" />
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="code">
|
||||
|
|
|
|||
33
apps/www/.vitepress/theme/components/StyleSwitcher.vue
Normal file
33
apps/www/.vitepress/theme/components/StyleSwitcher.vue
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<script setup lang="ts">
|
||||
import { type SelectTriggerProps } from 'radix-vue'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/lib/registry/new-york/ui/select'
|
||||
import { styles } from '@/lib/registry/styles'
|
||||
|
||||
const props = defineProps<SelectTriggerProps & { class?: string }>()
|
||||
const { config } = useConfigStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Select v-model="config.style">
|
||||
<SelectTrigger :class="cn('h-7 w-[145px] text-xs [&_svg]:h-4 [&_svg]:w-4', props.class)">
|
||||
<span class="text-muted-foreground">Style: </span>
|
||||
<SelectValue placeholder="Select style">
|
||||
{{ styles.find(s => s.name === config.style)?.label }}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="style in styles" :key="style.name" :value="style.name" class="text-xs">
|
||||
{{ style.label }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</template>
|
||||
4
apps/www/.vitepress/theme/composables/style.ts
Normal file
4
apps/www/.vitepress/theme/composables/style.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import { useStorage } from '@vueuse/core'
|
||||
import { styles } from '../../../src/lib/registry/styles'
|
||||
|
||||
export const useStyle = () => useStorage('selected-style', styles[0].name)
|
||||
|
|
@ -3,10 +3,10 @@ export const styles = [
|
|||
name: 'default',
|
||||
label: 'Default',
|
||||
},
|
||||
// {
|
||||
// name: 'new-york',
|
||||
// label: 'New York',
|
||||
// },
|
||||
{
|
||||
name: 'new-york',
|
||||
label: 'New York',
|
||||
},
|
||||
] as const
|
||||
|
||||
export type Style = (typeof styles)[number]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { computed } from 'vue'
|
||||
import { useSessionStorage } from '@vueuse/core'
|
||||
import type { Theme } from './../lib/registry/themes'
|
||||
import { styles } from '@/lib/registry/styles'
|
||||
|
||||
interface Config {
|
||||
theme: Theme['name']
|
||||
radius: number
|
||||
style: string
|
||||
}
|
||||
|
||||
export const RADII = [0, 0.25, 0.5, 0.75, 1]
|
||||
|
|
@ -13,13 +15,14 @@ export function useConfigStore() {
|
|||
const config = useSessionStorage<Config>('config', {
|
||||
theme: 'zinc',
|
||||
radius: 0.5,
|
||||
style: styles[0].name,
|
||||
})
|
||||
|
||||
const themeClass = computed(() => `theme-${config.value.theme}`)
|
||||
|
||||
const theme = computed(() => config.value.theme)
|
||||
|
||||
const radius = computed(() => config.value.radius)
|
||||
const style = computed(() => config.value.style)
|
||||
|
||||
function setTheme(themeName: Theme['name']) {
|
||||
config.value.theme = themeName
|
||||
|
|
@ -29,5 +32,5 @@ export function useConfigStore() {
|
|||
config.value.radius = newRadius
|
||||
}
|
||||
|
||||
return { config, theme, setTheme, radius, setRadius, themeClass }
|
||||
return { config, theme, setTheme, radius, setRadius, themeClass, style }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user