mirror of
https://github.com/sysadminsmedia/homebox.git
synced 2025-12-21 13:23:14 +01:00
feat: move theme picker to its own component and improve contrast on login screen
This commit is contained in:
45
frontend/components/App/ThemePicker.vue
Normal file
45
frontend/components/App/ThemePicker.vue
Normal 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>
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
];
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user