feat: move theme picker to its own component and improve contrast on login screen

This commit is contained in:
tonyaellie
2025-08-23 18:05:00 +00:00
parent 377c6c6e0d
commit 6fcd10d796
6 changed files with 89 additions and 59 deletions

View File

@@ -0,0 +1,45 @@
<script setup lang="ts">
import { themes } from "~~/lib/data/themes";
import { useTheme } from "~/composables/use-theme";
const { setTheme } = useTheme();
</script>
<template>
<div class="homebox grid grid-cols-1 gap-4 font-sans sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5">
<div
v-for="theme in themes"
:key="theme.value"
:class="'theme-' + theme.value"
class="overflow-hidden rounded-lg border outline-2 outline-offset-2"
:data-theme="theme.value"
:data-set-theme="theme.value"
data-act-class="outline"
@click="setTheme(theme.value)"
>
<div :data-theme="theme.value" class="w-full cursor-pointer bg-background-accent text-foreground">
<div class="grid grid-cols-5 grid-rows-3">
<div class="col-start-1 row-start-1 bg-background"></div>
<div class="col-start-1 row-start-2 bg-sidebar"></div>
<div class="col-start-1 row-start-3 bg-background-accent"></div>
<div class="col-span-4 col-start-2 row-span-3 row-start-1 flex flex-col gap-1 bg-background p-2">
<div class="font-bold">{{ theme.label }}</div>
<div class="flex flex-wrap gap-1">
<div class="flex size-5 items-center justify-center rounded bg-primary lg:size-6">
<div class="text-sm font-bold text-primary-foreground">A</div>
</div>
<div class="flex size-5 items-center justify-center rounded bg-secondary lg:size-6">
<div class="text-sm font-bold text-secondary-foreground">A</div>
</div>
<div class="flex size-5 items-center justify-center rounded bg-accent lg:size-6">
<div class="text-sm font-bold text-accent-foreground">A</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped></style>

View File

@@ -15,6 +15,7 @@
import "@vuepic/vue-datepicker/dist/main.css";
import * as datelib from "~/lib/datelib/datelib";
import { Label } from "@/components/ui/label";
import { darkThemes } from "~/lib/data/themes";
const emit = defineEmits(["update:modelValue", "update:text"]);
@@ -34,7 +35,7 @@
},
});
const isDark = useIsDark();
const isDark = useIsThemeInList(darkThemes);
const formatDate = (date: Date | string | number) => fmtDate(date, "human", "date");

View File

@@ -1,5 +1,5 @@
import type { ComputedRef } from "vue";
import type { DaisyTheme } from "~~/lib/data/themes";
import { type DaisyTheme } from "~~/lib/data/themes";
export interface UseTheme {
theme: ComputedRef<DaisyTheme>;
@@ -42,27 +42,11 @@ export function useTheme(): UseTheme {
return { theme, setTheme };
}
export function useIsDark() {
export function useIsThemeInList(list: DaisyTheme[]) {
const theme = useTheme();
const darkthemes = [
"synthwave",
"retro",
"cyberpunk",
"valentine",
"halloween",
"forest",
"aqua",
"black",
"luxury",
"dracula",
"business",
"night",
"coffee",
];
return computed(() => {
return darkthemes.includes(theme.theme.value);
return list.includes(theme.theme.value);
});
}

View File

@@ -153,3 +153,19 @@ export const themes: ThemeOption[] = [
value: "winter",
},
];
export const darkThemes: DaisyTheme[] = [
"synthwave",
"retro",
"cyberpunk",
"valentine",
"halloween",
"forest",
"aqua",
"black",
"luxury",
"dracula",
"business",
"night",
"coffee",
];

View File

@@ -54,6 +54,20 @@
}
});
const isEvilAccentTheme = useIsThemeInList([
"bumblebee",
"corporate",
"forest",
"pastel",
"wireframe",
"black",
"dracula",
"autumn",
"acid",
]);
const isEvilForegroundTheme = useIsThemeInList(["light", "aqua", "fantasy", "autumn", "night"]);
const isLofiTheme = useIsThemeInList(["lofi"]);
const route = useRoute();
const router = useRouter();
@@ -166,14 +180,19 @@
</svg>
</div>
<div>
<header class="mx-auto p-4 text-accent sm:flex sm:items-end sm:p-6 lg:p-14">
<header
class="mx-auto p-4 sm:flex sm:items-end sm:p-6 lg:p-14"
:class="{ 'text-accent': !isEvilAccentTheme, 'text-white': isLofiTheme }"
>
<div class="z-10">
<h2 class="mt-1 flex text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl">
HomeB
<AppLogo class="-mb-4 w-12" />
x
</h2>
<p class="ml-1 text-lg text-foreground">{{ $t("index.tagline") }}</p>
<p class="ml-1 text-lg" :class="{ 'text-foreground': !isEvilForegroundTheme, 'text-white': isLofiTheme }">
{{ $t("index.tagline") }}
</p>
</div>
<TooltipProvider :delay-duration="0">
<div class="z-10 ml-auto mt-6 flex items-center gap-4 sm:mt-0">

View File

@@ -2,7 +2,6 @@
import { useI18n } from "vue-i18n";
import { toast } from "@/components/ui/sonner";
import type { Detail } from "~~/components/global/DetailsSection/types";
import { themes } from "~~/lib/data/themes";
import type { CurrenciesCurrency, NotifierCreate, NotifierOut } from "~~/lib/api/types/data-contracts";
import MdiLoading from "~icons/mdi/loading";
import MdiAccount from "~icons/mdi/account";
@@ -21,6 +20,7 @@
import LanguageSelector from "~/components/App/LanguageSelector.vue";
import { Tooltip, TooltipContent, TooltipTrigger, TooltipProvider } from "@/components/ui/tooltip";
import { DialogID } from "~/components/ui/dialog-provider/utils";
import ThemePicker from "~/components/App/ThemePicker.vue";
const { t } = useI18n();
@@ -105,8 +105,6 @@
toast.success(t("profile.toast.group_updated"));
}
const { setTheme } = useTheme();
const auth = useAuthContext();
const details = computed(() => {
@@ -516,40 +514,7 @@
{{ $t("profile.display_legacy_header", { currentValue: preferences.displayLegacyHeader }) }}
</Button>
</div>
<div class="homebox grid grid-cols-1 gap-4 font-sans sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5">
<div
v-for="theme in themes"
:key="theme.value"
:class="'theme-' + theme.value"
class="overflow-hidden rounded-lg border outline-2 outline-offset-2"
:data-theme="theme.value"
:data-set-theme="theme.value"
data-act-class="outline"
@click="setTheme(theme.value)"
>
<div :data-theme="theme.value" class="w-full cursor-pointer bg-background-accent text-foreground">
<div class="grid grid-cols-5 grid-rows-3">
<div class="col-start-1 row-start-1 bg-background"></div>
<div class="col-start-1 row-start-2 bg-sidebar"></div>
<div class="col-start-1 row-start-3 bg-background-accent"></div>
<div class="col-span-4 col-start-2 row-span-3 row-start-1 flex flex-col gap-1 bg-background p-2">
<div class="font-bold">{{ theme.label }}</div>
<div class="flex flex-wrap gap-1">
<div class="flex size-5 items-center justify-center rounded bg-primary lg:size-6">
<div class="text-sm font-bold text-primary-foreground">A</div>
</div>
<div class="flex size-5 items-center justify-center rounded bg-secondary lg:size-6">
<div class="text-sm font-bold text-secondary-foreground">A</div>
</div>
<div class="flex size-5 items-center justify-center rounded bg-accent lg:size-6">
<div class="text-sm font-bold text-accent-foreground">A</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<ThemePicker />
</div>
</BaseCard>