Skip to content

Commit 04b7093

Browse files
committed
feat: theme editor
1 parent 6afbd57 commit 04b7093

File tree

8 files changed

+318
-19
lines changed

8 files changed

+318
-19
lines changed

frontend/app/api/generated.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1856,7 +1856,7 @@ export type AdminProjectEditPageQueryVariables = Exact<{
18561856
}>;
18571857

18581858

1859-
export type AdminProjectEditPageQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, name: string, description: string, startDate: any, endDate: any, archivedAt?: boolean | null, branding: { __typename?: 'Branding', logo?: string | null, rounding: number, colors: { __typename?: 'Colors', light: { __typename?: 'ColorSet', accent: string }, dark: { __typename?: 'ColorSet', accent: string } } } } };
1859+
export type AdminProjectEditPageQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, name: string, description: string, startDate: any, endDate: any, archivedAt?: boolean | null, branding: { __typename?: 'Branding', logo?: string | null, rounding: number, colors: { __typename?: 'Colors', light: { __typename?: 'ColorSet', accent: string, accentContrast: string, onAccent: string, backgroundDefault: string, backgroundRaised: string, backgroundIndent: string, textDefault: string, textMuted: string, textHint: string, shadowDefault: string, shadowBlank: string, borderDefault: string }, dark: { __typename?: 'ColorSet', accent: string, accentContrast: string, onAccent: string, backgroundDefault: string, backgroundRaised: string, backgroundIndent: string, textDefault: string, textMuted: string, textHint: string, shadowDefault: string, shadowBlank: string, borderDefault: string } } } } };
18601860

18611861
export type AdminProjectEventPageQueryVariables = Exact<{
18621862
eventId: Scalars['ID']['input'];
@@ -2579,9 +2579,31 @@ export const AdminProjectEditPageDocument = gql`
25792579
colors {
25802580
light {
25812581
accent
2582+
accentContrast
2583+
onAccent
2584+
backgroundDefault
2585+
backgroundRaised
2586+
backgroundIndent
2587+
textDefault
2588+
textMuted
2589+
textHint
2590+
shadowDefault
2591+
shadowBlank
2592+
borderDefault
25822593
}
25832594
dark {
25842595
accent
2596+
accentContrast
2597+
onAccent
2598+
backgroundDefault
2599+
backgroundRaised
2600+
backgroundIndent
2601+
textDefault
2602+
textMuted
2603+
textHint
2604+
shadowDefault
2605+
shadowBlank
2606+
borderDefault
25852607
}
25862608
}
25872609
}

frontend/app/components/PageLayout.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const hasScrolled = computed(() => y.value > 25)
2828
>
2929
<h1
3030
:class="[
31-
'absolute transition-all duration-300 ease-out',
31+
'text-text-default absolute transition-all duration-300 ease-out',
3232
{
3333
'text-heading bottom-3 left-6 translate-x-0 translate-y-0':
3434
!hasScrolled,
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<script setup lang="ts">
2+
const modelValue = defineModel<Colors>({ required: true })
3+
4+
const colorFields = [
5+
{ key: 'accent', label: 'Accent' },
6+
{ key: 'accentContrast', label: 'Accent Contrast' },
7+
{ key: 'onAccent', label: 'On Accent' },
8+
{ key: 'backgroundDefault', label: 'Background Default' },
9+
{ key: 'backgroundRaised', label: 'Background Raised' },
10+
{ key: 'backgroundIndent', label: 'Background Indent' },
11+
{ key: 'textDefault', label: 'Text Default' },
12+
{ key: 'textMuted', label: 'Text Muted' },
13+
{ key: 'textHint', label: 'Text Hint' },
14+
{ key: 'shadowDefault', label: 'Shadow Default' },
15+
{ key: 'shadowBlank', label: 'Shadow Blank' },
16+
{ key: 'borderDefault', label: 'Border Default' },
17+
] as const
18+
19+
type ColorKey = (typeof colorFields)[number]['key']
20+
21+
const lightStyles = computed(() => {
22+
return {
23+
'--color-accent': modelValue.value.light.accent,
24+
'--color-accent-contrast': modelValue.value.light.accentContrast,
25+
'--color-on-accent': modelValue.value.light.onAccent,
26+
'--color-background-default': modelValue.value.light.backgroundDefault,
27+
'--color-background-raised': modelValue.value.light.backgroundRaised,
28+
'--color-background-indent': modelValue.value.light.backgroundIndent,
29+
'--color-text-default': modelValue.value.light.textDefault,
30+
'--color-text-muted': modelValue.value.light.textMuted,
31+
'--color-text-hint': modelValue.value.light.textHint,
32+
'--color-shadow-default': modelValue.value.light.shadowDefault,
33+
'--color-shadow-blank': modelValue.value.light.shadowBlank,
34+
'--color-border-default': modelValue.value.light.borderDefault,
35+
}
36+
})
37+
38+
const darkStyles = computed(() => {
39+
return {
40+
'--color-accent': modelValue.value.dark.accent,
41+
'--color-accent-contrast': modelValue.value.dark.accentContrast,
42+
'--color-on-accent': modelValue.value.dark.onAccent,
43+
'--color-background-default': modelValue.value.dark.backgroundDefault,
44+
'--color-background-raised': modelValue.value.dark.backgroundRaised,
45+
'--color-background-indent': modelValue.value.dark.backgroundIndent,
46+
'--color-text-default': modelValue.value.dark.textDefault,
47+
'--color-text-muted': modelValue.value.dark.textMuted,
48+
'--color-text-hint': modelValue.value.dark.textHint,
49+
'--color-shadow-default': modelValue.value.dark.shadowDefault,
50+
'--color-shadow-blank': modelValue.value.dark.shadowBlank,
51+
'--color-border-default': modelValue.value.dark.borderDefault,
52+
}
53+
})
54+
55+
function updateLightColor(key: ColorKey, value: string) {
56+
modelValue.value = {
57+
...modelValue.value,
58+
light: {
59+
...modelValue.value.light,
60+
[key]: value,
61+
},
62+
}
63+
}
64+
65+
function updateDarkColor(key: ColorKey, value: string) {
66+
modelValue.value = {
67+
...modelValue.value,
68+
dark: {
69+
...modelValue.value.dark,
70+
[key]: value,
71+
},
72+
}
73+
}
74+
</script>
75+
76+
<template>
77+
<UModal title="Theme Editor" fullscreen>
78+
<UButton variant="soft" block>Open theme editor</UButton>
79+
80+
<template #body>
81+
<div class="flex gap-8">
82+
<div class="grid flex-1 grid-cols-2 gap-6">
83+
<div>
84+
<h3 class="mb-4 text-lg font-semibold">Light Mode</h3>
85+
<div class="space-y-3">
86+
<UFormField
87+
v-for="field in colorFields"
88+
:key="field.key"
89+
:label="field.label"
90+
>
91+
<ColorPickerInput
92+
:model-value="modelValue.light[field.key]"
93+
@update:model-value="updateLightColor(field.key, $event)"
94+
/>
95+
</UFormField>
96+
</div>
97+
</div>
98+
<div>
99+
<h3 class="mb-4 text-lg font-semibold">Dark Mode</h3>
100+
<div class="space-y-3">
101+
<UFormField
102+
v-for="field in colorFields"
103+
:key="field.key"
104+
:label="field.label"
105+
>
106+
<ColorPickerInput
107+
:model-value="modelValue.dark[field.key]"
108+
@update:model-value="updateDarkColor(field.key, $event)"
109+
/>
110+
</UFormField>
111+
</div>
112+
</div>
113+
</div>
114+
<div class="flex shrink-0 gap-4">
115+
<div class="text-center">
116+
<p class="text-muted mb-2 text-sm">Light</p>
117+
<AdminProjectThemePreview :style="lightStyles" />
118+
</div>
119+
<div class="text-center">
120+
<p class="text-muted mb-2 text-sm">Dark</p>
121+
<AdminProjectThemePreview :style="darkStyles" />
122+
</div>
123+
</div>
124+
</div>
125+
</template>
126+
</UModal>
127+
</template>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<script setup lang="ts">
2+
const leaderboard: LeaderboardEntry[] = [
3+
{
4+
id: '1',
5+
name: 'Name Nameson',
6+
score: 100,
7+
rank: 1,
8+
description: 'Local Church',
9+
tags: [LeaderboardEntryTag.TeamLead],
10+
},
11+
{
12+
id: '2',
13+
name: 'Jane Doe',
14+
score: 90,
15+
rank: 2,
16+
description: 'Global Church',
17+
tags: [],
18+
},
19+
{
20+
id: '3',
21+
name: 'Bob Smith',
22+
score: 80,
23+
rank: 3,
24+
description: 'Local Church',
25+
tags: [LeaderboardEntryTag.Me],
26+
},
27+
{
28+
id: '4',
29+
name: 'John Doe',
30+
score: 70,
31+
rank: 4,
32+
description: 'Global Church',
33+
tags: [],
34+
},
35+
]
36+
</script>
37+
38+
<template>
39+
<div
40+
class="border-default bg-background-default aspect-1/2 w-[400px] overflow-clip rounded-xl border text-start"
41+
>
42+
<PageLayout title="Preview">
43+
<div class="gap-list-section-gap flex flex-col">
44+
<DesignButton>Primary Button</DesignButton>
45+
<DesignButton variant="secondary">Secondary Button</DesignButton>
46+
<LeaderboardList
47+
:leaderboard
48+
:badge="
49+
(entry) =>
50+
entry.tags.includes(LeaderboardEntryTag.TeamLead)
51+
? $t('unit.unitLeader')
52+
: undefined
53+
"
54+
class="mt-medium"
55+
/>
56+
<div
57+
class="bg-background-indent rounded-list p-default mt-medium flex flex-col gap-1"
58+
>
59+
<p class="text-label text-text-default">Default text color</p>
60+
<p class="text-label text-text-muted">Muted text color</p>
61+
<p class="text-label text-text-hint">Hint text color</p>
62+
<p class="text-label text-accent-contrast">Accent contrast color</p>
63+
<p class="text-label text-on-accent bg-accent">On accent color</p>
64+
</div>
65+
</div>
66+
</PageLayout>
67+
</div>
68+
</template>

frontend/app/components/design/DesignButton.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const classes = cva(
1818
variants: {
1919
variant: {
2020
primary: 'bg-accent text-on-accent gradient-border',
21-
secondary: 'bg-border-default text-default gradient-border',
21+
secondary: 'bg-border-default text-text-default gradient-border',
2222
tertiary: 'text-default',
2323
},
2424
size: {

frontend/app/components/leaderboard/LeaderboardItem.vue

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ defineProps<{
77
}>()
88
99
const colorClasses = [
10-
{ light: 'text-[#F2BC28]', dark: 'text-[#864802]' },
11-
{ light: 'text-[#D4D4D4]', dark: 'text-[#525252]' },
12-
{ light: 'text-[#C47E49]', dark: 'text-[#512012]' },
10+
{ light: 'text-[#F2BC28]!', dark: 'text-[#864802]!' },
11+
{ light: 'text-[#D4D4D4]!', dark: 'text-[#525252]!' },
12+
{ light: 'text-[#C47E49]!', dark: 'text-[#512012]!' },
1313
]
1414
1515
const getColorClasses = (rank: number | undefined, mode: 'dark' | 'light') => {
@@ -29,11 +29,11 @@ const getColorClasses = (rank: number | undefined, mode: 'dark' | 'light') => {
2929
>
3030
<div
3131
:class="[
32-
'grid aspect-square size-10 place-items-center rounded-full',
32+
'text-text-default grid aspect-square size-10 place-items-center rounded-full',
3333
{
3434
'border-border-default border':
3535
hideMedal || (item.rank && item.rank > 3),
36-
'text-accent-contrast': isMe && hideMedal,
36+
'text-accent-contrast!': isMe && hideMedal,
3737
},
3838
!hideMedal && getColorClasses(item.rank, 'dark'),
3939
]"
@@ -47,7 +47,12 @@ const getColorClasses = (rank: number | undefined, mode: 'dark' | 'light') => {
4747
</div>
4848
<div class="grow">
4949
<div class="flex gap-2">
50-
<p :class="['text-label', { 'text-accent-contrast': isMe }]">
50+
<p
51+
:class="[
52+
'text-label',
53+
{ 'text-accent-contrast': isMe, 'text-text-default': !isMe },
54+
]"
55+
>
5156
{{ item.name }}
5257
</p>
5358
<span

0 commit comments

Comments
 (0)