Skip to content

Commit 8d4b2b4

Browse files
committed
feat(ui): redesign settings screen with card layout and visual improvements
1 parent ba99070 commit 8d4b2b4

File tree

10 files changed

+193
-139
lines changed

10 files changed

+193
-139
lines changed

src/renderer/components/preferences/API.vue

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,29 @@ watch(apiPort, (value) => {
1313
</script>
1414

1515
<template>
16-
<div class="space-y-5">
17-
<UiMenuFormItem :label="i18n.t('preferences:api.port.label')">
18-
<UiInput
19-
v-model="apiPort"
20-
type="number"
21-
min="1024"
22-
max="65535"
23-
size="sm"
24-
class="w-32"
25-
/>
26-
<template #description>
27-
{{ i18n.t("preferences:api.port.description") }}
28-
</template>
29-
<template #actions>
30-
<Button
31-
variant="outline"
32-
@click="ipc.invoke('system:reload', null)"
33-
>
34-
{{ i18n.t("action.reload.app") }}
35-
</Button>
36-
</template>
37-
</UiMenuFormItem>
16+
<div>
17+
<UiMenuFormSection :label="i18n.t('preferences:api.label')">
18+
<UiMenuFormItem :label="i18n.t('preferences:api.port.label')">
19+
<UiInput
20+
v-model="apiPort"
21+
type="number"
22+
min="1024"
23+
max="65535"
24+
size="sm"
25+
class="w-32"
26+
/>
27+
<template #description>
28+
{{ i18n.t("preferences:api.port.description") }}
29+
</template>
30+
<template #actions>
31+
<Button
32+
variant="outline"
33+
@click="ipc.invoke('system:reload', null)"
34+
>
35+
{{ i18n.t("action.reload.app") }}
36+
</Button>
37+
</template>
38+
</UiMenuFormItem>
39+
</UiMenuFormSection>
3840
</div>
3941
</template>

src/renderer/components/preferences/Appearance.vue

Lines changed: 70 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -46,83 +46,85 @@ void loadCustomThemes()
4646
</script>
4747

4848
<template>
49-
<div class="space-y-5">
50-
<UiMenuFormItem :label="i18n.t('preferences:appearance.theme.label')">
51-
<Select.Select
52-
:model-value="currentThemeId"
53-
@update:model-value="onThemeChange"
54-
>
55-
<Select.SelectTrigger class="w-64">
56-
<Select.SelectValue />
57-
</Select.SelectTrigger>
58-
<Select.SelectContent>
59-
<Select.SelectGroup>
60-
<Select.SelectLabel>
61-
{{ i18n.t("preferences:appearance.theme.builtIn") }}
62-
</Select.SelectLabel>
63-
<Select.SelectItem
64-
v-for="theme in builtInThemes"
65-
:key="theme.id"
66-
:value="theme.id"
67-
>
68-
{{ theme.label }}
69-
</Select.SelectItem>
70-
</Select.SelectGroup>
71-
72-
<template v-if="customThemes.length">
73-
<Select.SelectSeparator />
74-
75-
<Select.SelectGroup v-if="customDarkThemes.length">
49+
<div>
50+
<UiMenuFormSection :label="i18n.t('preferences:appearance.label')">
51+
<UiMenuFormItem :label="i18n.t('preferences:appearance.theme.label')">
52+
<Select.Select
53+
:model-value="currentThemeId"
54+
@update:model-value="onThemeChange"
55+
>
56+
<Select.SelectTrigger class="w-64">
57+
<Select.SelectValue />
58+
</Select.SelectTrigger>
59+
<Select.SelectContent>
60+
<Select.SelectGroup>
7661
<Select.SelectLabel>
77-
{{
78-
`${i18n.t("preferences:appearance.theme.custom")} · ${i18n.t("preferences:appearance.theme.dark")}`
79-
}}
62+
{{ i18n.t("preferences:appearance.theme.builtIn") }}
8063
</Select.SelectLabel>
8164
<Select.SelectItem
82-
v-for="theme in customDarkThemes"
65+
v-for="theme in builtInThemes"
8366
:key="theme.id"
8467
:value="theme.id"
8568
>
86-
{{ theme.name }}
69+
{{ theme.label }}
8770
</Select.SelectItem>
8871
</Select.SelectGroup>
8972

90-
<Select.SelectGroup v-if="customLightThemes.length">
91-
<Select.SelectLabel>
92-
{{
93-
`${i18n.t("preferences:appearance.theme.custom")} · ${i18n.t("preferences:appearance.theme.light")}`
94-
}}
95-
</Select.SelectLabel>
96-
<Select.SelectItem
97-
v-for="theme in customLightThemes"
98-
:key="theme.id"
99-
:value="theme.id"
100-
>
101-
{{ theme.name }}
102-
</Select.SelectItem>
103-
</Select.SelectGroup>
104-
</template>
105-
</Select.SelectContent>
106-
</Select.Select>
107-
</UiMenuFormItem>
73+
<template v-if="customThemes.length">
74+
<Select.SelectSeparator />
10875

109-
<UiMenuFormItem :label="i18n.t('preferences:appearance.theme.themesDir')">
110-
<template #description>
111-
{{ i18n.t("preferences:appearance.theme.dirDescription") }}
112-
</template>
113-
<template #actions>
114-
<div class="flex gap-2">
115-
<Button
116-
variant="outline"
117-
@click="openThemesDir"
118-
>
119-
{{ i18n.t("preferences:appearance.theme.openDir") }}
120-
</Button>
121-
<Button @click="createThemeTemplate">
122-
{{ i18n.t("preferences:appearance.theme.createTemplate") }}
123-
</Button>
124-
</div>
125-
</template>
126-
</UiMenuFormItem>
76+
<Select.SelectGroup v-if="customDarkThemes.length">
77+
<Select.SelectLabel>
78+
{{
79+
`${i18n.t("preferences:appearance.theme.custom")} · ${i18n.t("preferences:appearance.theme.dark")}`
80+
}}
81+
</Select.SelectLabel>
82+
<Select.SelectItem
83+
v-for="theme in customDarkThemes"
84+
:key="theme.id"
85+
:value="theme.id"
86+
>
87+
{{ theme.name }}
88+
</Select.SelectItem>
89+
</Select.SelectGroup>
90+
91+
<Select.SelectGroup v-if="customLightThemes.length">
92+
<Select.SelectLabel>
93+
{{
94+
`${i18n.t("preferences:appearance.theme.custom")} · ${i18n.t("preferences:appearance.theme.light")}`
95+
}}
96+
</Select.SelectLabel>
97+
<Select.SelectItem
98+
v-for="theme in customLightThemes"
99+
:key="theme.id"
100+
:value="theme.id"
101+
>
102+
{{ theme.name }}
103+
</Select.SelectItem>
104+
</Select.SelectGroup>
105+
</template>
106+
</Select.SelectContent>
107+
</Select.Select>
108+
</UiMenuFormItem>
109+
110+
<UiMenuFormItem :label="i18n.t('preferences:appearance.theme.themesDir')">
111+
<template #description>
112+
{{ i18n.t("preferences:appearance.theme.dirDescription") }}
113+
</template>
114+
<template #actions>
115+
<div class="flex gap-2">
116+
<Button
117+
variant="outline"
118+
@click="openThemesDir"
119+
>
120+
{{ i18n.t("preferences:appearance.theme.openDir") }}
121+
</Button>
122+
<Button @click="createThemeTemplate">
123+
{{ i18n.t("preferences:appearance.theme.createTemplate") }}
124+
</Button>
125+
</div>
126+
</template>
127+
</UiMenuFormItem>
128+
</UiMenuFormSection>
127129
</div>
128130
</template>

src/renderer/components/preferences/Editor.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ watch(
2323
</script>
2424

2525
<template>
26-
<div>
26+
<div class="space-y-4">
2727
<UiMenuFormSection :label="i18n.t('preferences:editor.label')">
2828
<UiMenuFormItem :label="i18n.t('preferences:editor.fontSize')">
2929
<UiInput

src/renderer/components/preferences/Language.vue

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,35 @@ watch(selectedLanguage, (value) => {
1717
</script>
1818

1919
<template>
20-
<div class="space-y-5">
21-
<UiMenuFormItem :label="i18n.t('preferences:language.label')">
22-
<template #description>
23-
{{ i18n.t("messages:description.language") }}
24-
</template>
25-
<Select.Select v-model="selectedLanguage">
26-
<Select.SelectTrigger class="w-64">
27-
<Select.SelectValue placeholder="Select a language" />
28-
</Select.SelectTrigger>
29-
<Select.SelectContent>
30-
<Select.SelectItem
31-
v-for="i in languageOptions"
32-
:key="i.value"
33-
:value="i.value"
20+
<div>
21+
<UiMenuFormSection :label="i18n.t('preferences:language.label')">
22+
<UiMenuFormItem :label="i18n.t('preferences:language.label')">
23+
<template #description>
24+
{{ i18n.t("messages:description.language") }}
25+
</template>
26+
<Select.Select v-model="selectedLanguage">
27+
<Select.SelectTrigger class="w-64">
28+
<Select.SelectValue placeholder="Select a language" />
29+
</Select.SelectTrigger>
30+
<Select.SelectContent>
31+
<Select.SelectItem
32+
v-for="i in languageOptions"
33+
:key="i.value"
34+
:value="i.value"
35+
>
36+
{{ i.label }}
37+
</Select.SelectItem>
38+
</Select.SelectContent>
39+
</Select.Select>
40+
<template #actions>
41+
<Button
42+
variant="outline"
43+
@click="ipc.invoke('system:reload', null)"
3444
>
35-
{{ i.label }}
36-
</Select.SelectItem>
37-
</Select.SelectContent>
38-
</Select.Select>
39-
<template #actions>
40-
<Button
41-
variant="outline"
42-
@click="ipc.invoke('system:reload', null)"
43-
>
44-
{{ i18n.t("action.reload.app") }}
45-
</Button>
46-
</template>
47-
</UiMenuFormItem>
45+
{{ i18n.t("action.reload.app") }}
46+
</Button>
47+
</template>
48+
</UiMenuFormItem>
49+
</UiMenuFormSection>
4850
</div>
4951
</template>

src/renderer/components/preferences/Storage.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ watch(
479479
</script>
480480

481481
<template>
482-
<div class="space-y-5">
482+
<div class="space-y-4">
483483
<!-- Section 1: Main -->
484484
<UiMenuFormSection :label="i18n.t('preferences:storage.section.main')">
485485
<UiMenuFormItem :label="i18n.t('preferences:storage.engine.label')">
@@ -632,6 +632,7 @@ watch(
632632
<UiMenuFormSection
633633
v-if="isSqliteEngine"
634634
:label="i18n.t('preferences:storage.section.dangerZone')"
635+
variant="danger"
635636
>
636637
<UiMenuFormItem :label="i18n.t('preferences:storage.clearDatabase')">
637638
<Button

src/renderer/components/ui/input/variants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { VariantProps } from 'class-variance-authority'
22
import { cva } from 'class-variance-authority'
33

44
export const variants = cva(
5-
'w-full rounded-md focus:outline-none placeholder:text-muted-foreground py-0.5 px-2 border dark:bg-black/10 bg-black/3 [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
5+
'w-full rounded-md focus:outline-none placeholder:text-muted-foreground py-0.5 px-2 border bg-background dark:bg-black/20 [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none',
66
{
77
variants: {
88
variant: {

src/renderer/components/ui/menu/FormItem.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ const props = defineProps<Props>()
1010
</script>
1111

1212
<template>
13-
<div :class="cn('grid max-w-3xl grid-cols-[200px_1fr] gap-2', props.class)">
14-
<div>
13+
<div :class="cn('grid grid-cols-[200px_1fr] gap-2', props.class)">
14+
<div class="flex min-h-9 items-start text-sm font-medium">
1515
{{ label }}
1616
</div>
1717
<div class="space-y-2">
Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,48 @@
11
<script setup lang="ts">
2+
import { cn } from '@/utils'
3+
24
interface Props {
35
label: string
6+
description?: string
7+
variant?: 'default' | 'danger'
48
}
59
6-
defineProps<Props>()
10+
const props = withDefaults(defineProps<Props>(), {
11+
description: undefined,
12+
variant: 'default',
13+
})
714
</script>
815

916
<template>
10-
<div class="[&:not(:first-child)]:mt-5">
11-
<UiText
12-
as="div"
13-
variant="xs"
14-
weight="bold"
15-
uppercase
16-
class="pb-2"
17+
<div>
18+
<div class="mb-2 px-1">
19+
<h3
20+
class="text-muted-foreground text-xs font-semibold tracking-wide uppercase"
21+
>
22+
{{ label }}
23+
</h3>
24+
<p
25+
v-if="description"
26+
class="text-muted-foreground mt-0.5 text-xs"
27+
>
28+
{{ description }}
29+
</p>
30+
</div>
31+
<div
32+
:class="
33+
cn(
34+
'rounded-lg border p-5',
35+
props.variant === 'danger'
36+
? 'border-destructive/20 bg-destructive/5'
37+
: 'border-border bg-card',
38+
)
39+
"
1740
>
18-
{{ label }}
19-
</UiText>
20-
<div class="space-y-5">
21-
<slot />
41+
<div
42+
class="divide-border/40 divide-y [&>*]:py-4 [&>*:first-child]:pt-0 [&>*:last-child]:pb-0"
43+
>
44+
<slot />
45+
</div>
2246
</div>
2347
</div>
2448
</template>

src/renderer/components/ui/menu/Item.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,21 @@ defineProps<Props>()
99

1010
<template>
1111
<div
12-
class="flex items-center rounded-md"
12+
class="flex items-center gap-2 rounded-md px-2 py-1"
1313
:class="
1414
isActive ? 'bg-accent text-accent-foreground' : 'hover:bg-accent-hover'
1515
"
1616
>
17-
<div class="ml-5.5 truncate select-none">
17+
<div
18+
v-if="$slots.icon"
19+
class="text-muted-foreground flex h-4 w-4 shrink-0 items-center justify-center"
20+
>
21+
<slot name="icon" />
22+
</div>
23+
<div
24+
class="truncate select-none"
25+
:class="!$slots.icon && 'ml-3.5'"
26+
>
1827
{{ label }}
1928
</div>
2029
</div>

0 commit comments

Comments
 (0)