Add theme selection, dark/light mode selection
This commit is contained in:
149
app/components/ui/internal/ThemeSelector.vue
Normal file
149
app/components/ui/internal/ThemeSelector.vue
Normal file
@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<Select v-model="selectedPreset" @update:model-value="handleThemeChange">
|
||||
<SelectTrigger class="w-[180px]">
|
||||
<SelectValue placeholder="Select theme..." />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>Themes</SelectLabel>
|
||||
|
||||
<!-- Theme Categories -->
|
||||
<SelectLabel class="pl-8 text-xs font-normal text-muted-foreground">
|
||||
Classic
|
||||
</SelectLabel>
|
||||
<SelectItem v-for="theme in classicThemes" :key="theme" :value="theme">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="h-3 w-3 rounded-full" :class="themeColor(theme)" />
|
||||
<span>{{ formatThemeName(theme) }}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
|
||||
<SelectLabel class="pl-8 text-xs font-normal text-muted-foreground mt-2">
|
||||
Vibrant
|
||||
</SelectLabel>
|
||||
<SelectItem v-for="theme in vibrantThemes" :key="theme" :value="theme">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="h-3 w-3 rounded-full" :class="themeColor(theme)" />
|
||||
<span>{{ formatThemeName(theme) }}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
|
||||
<SelectLabel class="pl-8 text-xs font-normal text-muted-foreground mt-2">
|
||||
Special
|
||||
</SelectLabel>
|
||||
<SelectItem v-for="theme in specialThemes" :key="theme" :value="theme">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="h-3 w-3 rounded-full" :class="themeColor(theme)" />
|
||||
<span>{{ formatThemeName(theme) }}</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@/components/ui/select'
|
||||
import type { ThemePreset } from '@/composables/useTheme'
|
||||
import type { AcceptableValue } from 'reka-ui'
|
||||
|
||||
const { themePreset, setThemePreset } = useTheme()
|
||||
|
||||
const selectedPreset = ref<ThemePreset>(themePreset.value)
|
||||
|
||||
const classicThemes: ThemePreset[] = [
|
||||
'default', 'modern', 'nature', 'mocha', 'graphite',
|
||||
'notebook', 'ocean', 'pastel', 'retro', 'sage',
|
||||
'vintage', 'mono'
|
||||
]
|
||||
|
||||
const vibrantThemes: ThemePreset[] = [
|
||||
'cyberpunk', 'claymorphism', 'bold-tech', 'bubblegum',
|
||||
'candyland', 'neo', 'quantum', 'softpop', 'solardusk',
|
||||
'starry', 'sunset', 'tangerine', 'violet', 'amber',
|
||||
'amethyst'
|
||||
]
|
||||
|
||||
const specialThemes: ThemePreset[] = [
|
||||
'darkmatter', 'cleanslate', 'eleganyluxury', 'kodama',
|
||||
'midnight', 'catpuccin', 'claude', 'cosmicnight', 'doom64',
|
||||
'caffeine', 'northern', 'perpetuity', 'supabase', 't3chat',
|
||||
'twitter', 'vercel'
|
||||
]
|
||||
|
||||
const handleThemeChange = (value: AcceptableValue) => {
|
||||
console.log(value);
|
||||
setThemePreset(value as ThemePreset)
|
||||
}
|
||||
|
||||
watch(() => themePreset.value, (newPreset) => {
|
||||
selectedPreset.value = newPreset
|
||||
})
|
||||
|
||||
const formatThemeName = (theme: string) => {
|
||||
return theme
|
||||
.replace(/-/g, ' ')
|
||||
.replace(/\b\w/g, l => l.toUpperCase())
|
||||
}
|
||||
|
||||
const themeColor = (theme: ThemePreset) => {
|
||||
const colors: Record<string, string> = {
|
||||
'default': 'bg-blue-500',
|
||||
'modern': 'bg-slate-600',
|
||||
'mono': 'bg-zinc-600',
|
||||
'cleanslate': 'bg-slate-300',
|
||||
'notebook': 'bg-amber-100 border border-amber-300',
|
||||
'vintage': 'bg-amber-800',
|
||||
'graphite': 'bg-gray-700',
|
||||
|
||||
'darkmatter': 'bg-gray-900',
|
||||
'midnight': 'bg-blue-900',
|
||||
'cosmicnight': 'bg-indigo-950',
|
||||
'doom64': 'bg-purple-900',
|
||||
|
||||
'cyberpunk': 'bg-pink-500',
|
||||
'bold-tech': 'bg-rose-600',
|
||||
'neo': 'bg-emerald-400',
|
||||
'quantum': 'bg-teal-500',
|
||||
|
||||
'nature': 'bg-green-600',
|
||||
'sage': 'bg-emerald-600',
|
||||
'northern': 'bg-sky-700',
|
||||
'ocean': 'bg-cyan-500',
|
||||
|
||||
'claymorphism': 'bg-orange-300',
|
||||
'softpop': 'bg-fuchsia-300',
|
||||
|
||||
'eleganyluxury': 'bg-amber-900',
|
||||
'amethyst': 'bg-purple-700',
|
||||
'claude': 'bg-violet-800',
|
||||
|
||||
'kodama': 'bg-lime-400',
|
||||
'catpuccin': 'bg-mauve-500',
|
||||
'bubblegum': 'bg-pink-300',
|
||||
|
||||
'mocha': 'bg-amber-800',
|
||||
'caffeine': 'bg-brown-700',
|
||||
'tangerine': 'bg-orange-500',
|
||||
'candyland': 'bg-rose-400',
|
||||
|
||||
'sunset': 'bg-orange-500',
|
||||
'solardusk': 'bg-red-700',
|
||||
'starry': 'bg-indigo-700',
|
||||
'perpetuity': 'bg-cyan-700',
|
||||
|
||||
'pastel': 'bg-pink-200',
|
||||
'retro': 'bg-yellow-400',
|
||||
|
||||
'supabase': 'bg-green-400',
|
||||
'twitter': 'bg-sky-500',
|
||||
'vercel': 'bg-black',
|
||||
't3chat': 'bg-blue-600',
|
||||
|
||||
'amber': 'bg-amber-500',
|
||||
'violet': 'bg-violet-600',
|
||||
}
|
||||
|
||||
return colors[theme] || 'bg-gray-400'
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user