Add theme selection, dark/light mode selection

This commit is contained in:
2026-01-15 02:01:41 +05:00
parent 3cfaad10cf
commit c0524494e9
94 changed files with 8035 additions and 72 deletions

View File

@ -1,11 +1,20 @@
<script setup lang="ts">
import { Search } from 'lucide-vue-next';
import ModeToggle from './ModeToggle.vue';
import ThemeSelector from './ThemeSelector.vue';
const colorMode = useColorMode()
const logoPath = computed(() => {
return colorMode.value === 'dark' ? 'logo-dark.png' : 'logo.png'
})
</script>
<template>
<div class="flex items-center justify-center w-full p-4 gap-8 border-b">
<div>
<NuxtImg src="logo.jpg" width="48" height="48" />
<ClientOnly>
<NuxtImg :src="logoPath" width="48" height="48" />
</ClientOnly>
</div>
<div>
<Button variant="ghost">
@ -18,13 +27,15 @@ import { Search } from 'lucide-vue-next';
Forum
</Button>
</div>
<div>
<div class="flex gap-4">
<InputGroup>
<InputGroupInput placeholder="Search..." />
<InputGroupAddon>
<Search />
</InputGroupAddon>
</InputGroup>
<ModeToggle />
<ThemeSelector />
</div>
</div>
</template>

View File

@ -0,0 +1,62 @@
<template>
<div class="flex flex-col items-center gap-4 mt-32">
<h1 class="scroll-m-20 text-center text-4xl font-extrabold tracking-tight text-balance">
The next-generation anime platform
</h1>
<h3 class="scroll-m-20 text-2xl font-semibold tracking-tight text-center max-w-2/5">
Track, share, and discover your favorite anime and manga with Anyame
</h3>
</div>
<div class="flex items-center justify-center">
<div class="grid grid-cols-2 gap-16">
<div class="flex max-w-96 gap-8">
<NuxtImg src="discover-icon.svg" width="96" height="96" />
<div>
<h4 class="scroll-m-20 text-xl font-semibold tracking-tight">
Discover your obsessions
</h4>
<p class="font-semibold text-sm text-muted-foreground">
What are your highest rated genres or most watched voice actors?
Follow your watching habits over time with in-depth statistics.
</p>
</div>
</div>
<div class="flex max-w-96 gap-8">
<NuxtImg src="anywhere-icon.svg" width="96" height="96" />
<div>
<h4 class="scroll-m-20 text-xl font-semibold tracking-tight">
Bring Anyame anywhere
</h4>
<p class="font-semibold text-sm text-muted-foreground">
Keep track of your progress on-the-go with one of many Anyame apps across iOS, Android,
macOS, and Windows.
</p>
</div>
</div>
<div class="flex max-w-96 gap-8">
<NuxtImg src="conversation-icon.svg" width="96" height="96" />
<div>
<h4 class="scroll-m-20 text-xl font-semibold tracking-tight">
Join the conversation
</h4>
<p class="font-semibold text-sm text-muted-foreground">
Share your thoughts with our thriving community, make friends, socialize, and receive
recommendations.
</p>
</div>
</div>
<div class="flex max-w-96 gap-8">
<NuxtImg src="tweak-icon.svg" width="96" height="96" />
<div>
<h4 class="scroll-m-20 text-xl font-semibold tracking-tight">
Tweak it to your liking
</h4>
<p class="font-semibold text-sm text-muted-foreground">
Customize your scoring system, title format, color scheme, and much more! Also, we have a
dark mode.
</p>
</div>
</div>
</div>
</div>
</template>

View File

@ -0,0 +1,22 @@
<script setup lang="ts">
import { Button } from '@/components/ui/button';
import { Moon, Sun } from 'lucide-vue-next';
const colorMode = useColorMode()
function toggleMode() {
if (colorMode.preference === 'system' || colorMode.preference === 'light') {
colorMode.preference = 'dark'
} else {
colorMode.preference = 'light'
}
}
</script>
<template>
<Button variant="outline" @click="toggleMode">
<Moon class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Sun class="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span class="sr-only">Toggle theme</span>
</Button>
</template>

View 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>