diff --git a/apps/dashboard/src/app.html b/apps/dashboard/src/app.html index 6a2bb582..02ecd330 100644 --- a/apps/dashboard/src/app.html +++ b/apps/dashboard/src/app.html @@ -4,6 +4,33 @@ + + %sveltekit.head%
diff --git a/apps/dashboard/src/lib/components/dialogs/user-settings-dialog.svelte b/apps/dashboard/src/lib/components/dialogs/user-settings-dialog.svelte index 918a9e1c..6ab1f0b7 100644 --- a/apps/dashboard/src/lib/components/dialogs/user-settings-dialog.svelte +++ b/apps/dashboard/src/lib/components/dialogs/user-settings-dialog.svelte @@ -22,12 +22,15 @@ listSshKeys } from '#lib/remote/ssh-keys.remote.js'; import { disableTwoFactorWithVerification } from '#lib/remote/two-factor.remote.js'; + import { type ContrastPreference, contrast } from '#lib/state/contrast.svelte.js'; import type { UserSettingsTab } from '#lib/state/user-settings.svelte.js'; import { getErrorMessage } from '#lib/utils.js'; import { goto, invalidate } from '$app/navigation'; import { resolve } from '$app/paths'; import { page } from '$app/state'; import Check from '~icons/lucide/check'; + import Circle from '~icons/lucide/circle'; + import Contrast from '~icons/lucide/contrast'; import Loader2 from '~icons/lucide/loader-2'; import Minus from '~icons/lucide/minus'; import Plus from '~icons/lucide/plus'; @@ -59,6 +62,12 @@ { value: 'system', label: 'Auto', icon: Monitor } ]; + const contrastOptions: { value: ContrastPreference; label: string; icon: typeof Sun }[] = [ + { value: 'off', label: 'Off', icon: Circle }, + { value: 'on', label: 'On', icon: Contrast }, + { value: 'auto', label: 'Auto', icon: Monitor } + ]; + interface Props { activeTab?: UserSettingsTab; open?: boolean; @@ -1063,6 +1072,34 @@ Auto follows your system's light/dark setting. + diff --git a/apps/dashboard/src/lib/components/ui/button/button.svelte b/apps/dashboard/src/lib/components/ui/button/button.svelte index c2ae9171..08d62b3e 100644 --- a/apps/dashboard/src/lib/components/ui/button/button.svelte +++ b/apps/dashboard/src/lib/components/ui/button/button.svelte @@ -7,16 +7,17 @@ base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 active:not-aria-[haspopup]:translate-y-px aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-all outline-none select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", variants: { variant: { - default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80', + default: + 'bg-primary text-primary-foreground [a]:hover:bg-primary/80 high-contrast:border-primary high-contrast:hover:border-foreground high-contrast:hover:bg-foreground high-contrast:hover:text-background high-contrast:hover:[&_svg]:text-current', outline: - 'border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground', + 'border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground high-contrast:border-border high-contrast:bg-background high-contrast:hover:border-foreground high-contrast:hover:bg-foreground high-contrast:hover:text-background high-contrast:hover:[&_svg]:text-current', secondary: - 'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground', + 'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground high-contrast:border-border high-contrast:hover:border-foreground high-contrast:hover:bg-foreground high-contrast:hover:text-background high-contrast:hover:[&_svg]:text-current', ghost: - 'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground', + 'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground high-contrast:hover:border-foreground high-contrast:hover:bg-foreground high-contrast:hover:text-background high-contrast:hover:[&_svg]:text-current', destructive: - 'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30', - link: 'text-primary underline-offset-4 hover:underline' + 'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30 high-contrast:border-destructive high-contrast:hover:border-destructive high-contrast:hover:bg-destructive high-contrast:hover:text-destructive-foreground high-contrast:hover:[&_svg]:text-current', + link: 'text-primary underline-offset-4 hover:underline high-contrast:underline' }, size: { default: diff --git a/apps/dashboard/src/lib/components/ui/input-group/input-group.svelte b/apps/dashboard/src/lib/components/ui/input-group/input-group.svelte index aeda9184..d818c0b4 100644 --- a/apps/dashboard/src/lib/components/ui/input-group/input-group.svelte +++ b/apps/dashboard/src/lib/components/ui/input-group/input-group.svelte @@ -15,7 +15,7 @@ data-slot="input-group" role="group" class={cn( - 'group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5', + 'group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border border-input transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:bg-input/50 has-disabled:opacity-50 high-contrast:has-disabled:opacity-100 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto dark:bg-input/30 dark:has-disabled:bg-input/80 high-contrast:bg-background high-contrast:has-disabled:bg-background high-contrast:has-disabled:border-dashed dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5', className )} {...props} diff --git a/apps/dashboard/src/lib/components/ui/input/input.svelte b/apps/dashboard/src/lib/components/ui/input/input.svelte index 0b63e568..5f23cf93 100644 --- a/apps/dashboard/src/lib/components/ui/input/input.svelte +++ b/apps/dashboard/src/lib/components/ui/input/input.svelte @@ -25,7 +25,7 @@ bind:this={ref} data-slot={dataSlot} class={cn( - 'h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40', + 'h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 high-contrast:bg-background high-contrast:disabled:bg-background high-contrast:disabled:border-dashed high-contrast:disabled:text-muted-foreground high-contrast:disabled:opacity-100', className )} type="file" @@ -38,7 +38,7 @@ bind:this={ref} data-slot={dataSlot} class={cn( - 'h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40', + 'h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 high-contrast:bg-background high-contrast:disabled:bg-background high-contrast:disabled:border-dashed high-contrast:disabled:text-muted-foreground high-contrast:disabled:opacity-100', className )} {type} diff --git a/apps/dashboard/src/lib/components/ui/switch/switch.svelte b/apps/dashboard/src/lib/components/ui/switch/switch.svelte index 52243042..9a678da9 100644 --- a/apps/dashboard/src/lib/components/ui/switch/switch.svelte +++ b/apps/dashboard/src/lib/components/ui/switch/switch.svelte @@ -19,13 +19,13 @@ data-slot="switch" data-size={size} class={cn( - 'peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50', + 'peer group/switch relative inline-flex shrink-0 items-center rounded-full border border-transparent transition-all outline-none after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:bg-primary data-unchecked:bg-input dark:data-unchecked:bg-input/80 data-disabled:cursor-not-allowed data-disabled:opacity-50 high-contrast:border-input high-contrast:data-unchecked:bg-background', className )} {...restProps} >