Skip to content

Commit 1649a37

Browse files
committed
feat: dark mode
1 parent cbac4de commit 1649a37

18 files changed

Lines changed: 243 additions & 46 deletions

frontend/public/arch.png

31.8 KB
Loading

frontend/src/App.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,27 @@ import { useI18n } from 'vue-i18n'
77
import { useRouter } from 'vue-router'
88
import AppSidebar from '@/components/AppSidebar.vue'
99
import LoginForm from '@/components/LoginForm.vue'
10+
import ThemeToggle from '@/components/ThemeToggle.vue'
1011
import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar'
1112
import { Toaster } from '@/components/ui/sonner'
1213
import { useAuth } from '@/composables/auth'
14+
import { useThemeStore } from '@/stores/theme'
1315
import ActionHandler from '@/views/ActionHandler.vue'
1416
import 'vue-sonner/style.css'
1517
1618
const { t } = useI18n()
1719
const { checkAuth, isLoggedIn } = useAuth()
1820
const { replace, currentRoute } = useRouter()
21+
const themeStore = useThemeStore()
1922
2023
const authState = ref<AuthState | null>(null)
2124
const isCheckingAuth = ref(true)
2225
2326
onMounted(async () => {
27+
// Initialize theme
28+
themeStore.initTheme()
29+
themeStore.setupSystemThemeListener()
30+
2431
authState.value = await checkAuth()
2532
isCheckingAuth.value = false
2633
setTimeout(() => replace(currentRoute.value.path), 100)
@@ -59,6 +66,7 @@ onMounted(async () => {
5966
</h1>
6067
</div>
6168
</div>
69+
<ThemeToggle />
6270
</div>
6371
</div>
6472
<RouterView />

frontend/src/components/AppDetailDialog.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function formatDate(dateString: string) {
6060
</h3>
6161
</div>
6262

63-
<p class="text-gray-600 text-sm">
63+
<p class="text-muted-foreground text-sm">
6464
{{ app.description || t('appDetailDialog.noDescription') }}
6565
</p>
6666
</div>

frontend/src/components/AppSidebar.vue

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script setup lang="ts">
22
import { AlertTriangle, BarChart3, Brain, Grid3X3, InfoIcon, Settings, Zap } from 'lucide-vue-next'
33
import { useI18n } from 'vue-i18n'
4+
import ThemeToggle from '@/components/ThemeToggle.vue'
45
import {
56
HoverCard,
67
HoverCardContent,
@@ -124,22 +125,25 @@ const { serverConnected, serviceUrl } = useService()
124125
</div>
125126
</div>
126127

127-
<HoverCard :open-delay="400">
128-
<HoverCardTrigger>
129-
<div class="h-8 flex items-center gap-1 text-xs text-sidebar-foreground/70">
130-
<div
131-
class="mx-1 h-2 w-2 rounded-full mb-[2px]"
132-
:class="serverConnected ? 'bg-green-500' : 'bg-red-500'"
133-
/>
134-
<span class="text-sm select-none">{{ serverConnected ? t('service.connected') : t('service.disconnected') }}</span>
135-
</div>
136-
</HoverCardTrigger>
137-
<HoverCardContent v-if="serverConnected" :side-offset="0" class="pt-2 py-1">
138-
<div class="font-mono text-sm text-center mt-1 ">
139-
{{ serviceUrl }}
140-
</div>
141-
</HoverCardContent>
142-
</HoverCard>
128+
<div class="flex items-center justify-between">
129+
<HoverCard :open-delay="400">
130+
<HoverCardTrigger>
131+
<div class="h-8 flex items-center gap-1 text-xs text-sidebar-foreground/70">
132+
<div
133+
class="mx-1 h-2 w-2 rounded-full mb-[2px]"
134+
:class="serverConnected ? 'bg-green-500' : 'bg-red-500'"
135+
/>
136+
<span class="text-sm select-none">{{ serverConnected ? t('service.connected') : t('service.disconnected') }}</span>
137+
</div>
138+
</HoverCardTrigger>
139+
<HoverCardContent v-if="serverConnected" :side-offset="0" class="pt-2 py-1">
140+
<div class="font-mono text-sm text-center mt-1 ">
141+
{{ serviceUrl }}
142+
</div>
143+
</HoverCardContent>
144+
</HoverCard>
145+
<ThemeToggle />
146+
</div>
143147
</div>
144148
</SidebarFooter>
145149
</Sidebar>

frontend/src/components/ManualConfigCard.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ async function handleManualConfigSave(config: ManualConfig) {
4343
</CardHeader>
4444

4545
<CardContent class="flex-grow">
46-
<div class="text-sm text-gray-600">
46+
<div class="text-sm text-muted-foreground">
4747
<p>{{ t('providers.manualConfigDescription') }}</p>
4848
</div>
4949
</CardContent>

frontend/src/components/ManualConfigDialog.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ watch(open, (newValue) => {
5454

5555
<template>
5656
<Dialog v-model:open="open">
57-
<DialogContent class="sm:max-w-lg" autocomplete="off">
57+
<DialogContent class="sm:max-w-lg">
5858
<DialogHeader>
5959
<DialogTitle>{{ t('manualConfigDialog.title') }}</DialogTitle>
6060
<DialogDescription>
6161
{{ t('manualConfigDialog.description') }}
6262
</DialogDescription>
6363
</DialogHeader>
6464

65-
<div class="mt-6 space-y-4" autocomplete="off">
65+
<div class="mt-6 space-y-4">
6666
<div class="space-y-2">
6767
<label class="text-sm font-medium">{{ t('manualConfigDialog.providerName') }}</label>
6868
<Input

frontend/src/components/ProviderSelector.vue

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ watchEffect(() => {
2727
</script>
2828

2929
<template>
30-
<div class="space-y-1">
31-
<div class="text-sm font-medium text-gray-700">
30+
<div class="space-y-2">
31+
<div class="text-sm font-medium">
3232
{{ t('providers.selectProvider') }}:
3333
</div>
34-
<div v-if="providersStore.loading" class="text-sm text-gray-500">
34+
<div v-if="providersStore.loading" class="text-sm text-muted-foreground">
3535
{{ t('providers.loadingProviders') }}
3636
</div>
37-
<div v-else-if="providersStore.providers.length === 0" class="text-sm text-gray-500">
37+
<div v-else-if="providersStore.providers.length === 0" class="text-sm text-muted-foreground">
3838
<span class="text-red-500">
3939
{{ t('providers.noProvidersAvailable') }}
4040
</span>
@@ -48,10 +48,10 @@ watchEffect(() => {
4848
v-for="provider in providersStore.providers"
4949
:key="provider.id"
5050
:variant="selectedProviderId === provider.id ? 'default' : 'secondary'"
51-
class="cursor-pointer transition-colors hover:bg-gray-300"
51+
class="cursor-pointer transition-colors"
5252
:class="{
53-
'bg-blue-500 hover:bg-blue-600 text-white': selectedProviderId === provider.id,
54-
'bg-gray-200 hover:bg-gray-300': selectedProviderId !== provider.id,
53+
'bg-blue-500 hover:bg-blue-600 dark:bg-blue-800 dark:hover:bg-blue-600 text-white': selectedProviderId === provider.id,
54+
'bg-muted hover:bg-muted-foreground': selectedProviderId !== provider.id,
5555
}"
5656
@click="selectedProviderId = provider.id"
5757
>
@@ -60,9 +60,8 @@ watchEffect(() => {
6060

6161
<!-- Add new provider button -->
6262
<Badge
63-
key="new"
6463
variant="secondary"
65-
class="text-xs cursor-pointer transition-colors hover:bg-gray-300 h-6"
64+
class="text-xs cursor-pointer transition-colors bg-muted hover:bg-muted-foreground h-6"
6665
@click="openAddProviderDialog = true"
6766
>
6867
<Plus class="inline h-4 w-4" />

frontend/src/components/ProvidersSection.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,23 +69,23 @@ onMounted(() => {
6969
</CardTitle>
7070
<div v-show="!siliconFlowStore.isLoading" class="flex items-center gap-2">
7171
<span
72-
class="inline-flex items-center rounded-full px-2 py-1 text-xs font-medium text-gray-800"
72+
class="inline-flex items-center rounded-full px-2 py-1 text-xs font-medium text-accent-foreground"
7373
:class="{
74-
'bg-emerald-200': siliconFlowStore.isLoggedIn,
75-
'bg-gray-200': !siliconFlowStore.isLoggedIn,
74+
'bg-emerald-200 dark:bg-green-500/60': siliconFlowStore.isLoggedIn,
75+
'bg-accent': !siliconFlowStore.isLoggedIn,
7676
}"
7777
>
78-
{{ siliconFlowStore.isLoggedIn ? t('providers.loggedIn') : t('providers.notLoggedIn') }}
78+
{{ siliconFlowStore.isLoggedIn ? t('providers.loggedIn') : t('providers.loggedOut') }}
7979
</span>
8080
</div>
8181
</div>
8282
</CardHeader>
8383

8484
<CardContent>
85-
<div class="text-sm text-gray-600">
85+
<div class="text-sm text-muted-foreground">
8686
<p>
8787
{{ t('providers.siliconFlowDescription1') }}
88-
<a href="https://www.siliconflow.cn" target="_blank" class="text-blue-900 hover:underline">
88+
<a href="https://www.siliconflow.cn" target="_blank" class="text-blue-900 dark:text-blue-200 hover:underline">
8989
{{ t('providers.siliconFlow') }}
9090
</a>
9191
{{ t('providers.siliconFlowDescription2') }}

frontend/src/components/SiliconFlowCard.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ async function handleCreateKey() {
6767
{{ t('providers.siliconFlow') }}
6868
</div>
6969

70-
<div class="h-2 w-2 bg-green-500 rounded-full" />
71-
<div class="text-green-700 text-base">
70+
<div class="h-2 w-2 bg-green-500 dark:bg-green-400 rounded-full" />
71+
<div class="text-green-700 dark:text-green-500 text-base">
7272
{{ t('siliconFlow.loggedIn') }}
7373
</div>
7474

frontend/src/components/SiliconFlowPaymentDialog.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
Dialog,
66
DialogClose,
77
DialogContent,
8+
DialogDescription,
89
DialogHeader,
910
DialogTitle,
1011
} from '@/components/ui/dialog'
@@ -28,6 +29,9 @@ function handleOpenChange(open: boolean) {
2829
<DialogContent class="max-w-sm">
2930
<DialogHeader>
3031
<DialogTitle>{{ t('siliconFlow.accountRecharge') }}</DialogTitle>
32+
<DialogDescription>
33+
{{ t('siliconFlow.accountRechargeDescription') }}
34+
</DialogDescription>
3135
<DialogClose />
3236
</DialogHeader>
3337
<div class="space-y-4">

0 commit comments

Comments
 (0)