feat(appearance): add display preference models
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import type { ThemeScheme } from "./themes"
|
||||
|
||||
export type Brightness = "dim" | "normal" | "bright"
|
||||
export type MotionMode = "system" | "reduce" | "full"
|
||||
export type ResolvedMotionMode = Exclude<MotionMode, "system">
|
||||
export type TextScale = "100" | "125" | "150" | "200"
|
||||
|
||||
export const brightnessModes = [
|
||||
"dim",
|
||||
"normal",
|
||||
"bright",
|
||||
] as const satisfies readonly Brightness[]
|
||||
export const motionModes = [
|
||||
"system",
|
||||
"reduce",
|
||||
"full",
|
||||
] as const satisfies readonly MotionMode[]
|
||||
export const textScales = [
|
||||
"100",
|
||||
"125",
|
||||
"150",
|
||||
"200",
|
||||
] as const satisfies readonly TextScale[]
|
||||
|
||||
export const BRIGHTNESS_ATTRIBUTE = "data-ui-brightness"
|
||||
export const MOTION_ATTRIBUTE = "data-ui-motion"
|
||||
export const TEXT_SCALE_ATTRIBUTE = "data-ui-text-scale"
|
||||
|
||||
const surfaceVariableNames = [
|
||||
"background",
|
||||
"card",
|
||||
"popover",
|
||||
"secondary",
|
||||
"muted",
|
||||
"highlight",
|
||||
"sidebar",
|
||||
] as const
|
||||
|
||||
export function isBrightness(value: unknown): value is Brightness {
|
||||
return brightnessModes.some((mode) => mode === value)
|
||||
}
|
||||
|
||||
export function isMotionMode(value: unknown): value is MotionMode {
|
||||
return motionModes.some((mode) => mode === value)
|
||||
}
|
||||
|
||||
export function isTextScale(value: unknown): value is TextScale {
|
||||
return textScales.some((scale) => scale === value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts interface surfaces without filtering media, illustrations, or brand
|
||||
* colors. Foreground colors are preserved so dimming does not reduce contrast.
|
||||
*/
|
||||
export function applyBrightnessToTheme(
|
||||
variables: Record<string, string>,
|
||||
brightness: Brightness,
|
||||
scheme: ThemeScheme
|
||||
): Record<string, string> {
|
||||
if (brightness === "normal") return variables
|
||||
|
||||
const target = brightness === "dim" ? "black" : "white"
|
||||
const amount = {
|
||||
bright: scheme === "light" ? 12 : 8,
|
||||
dim: scheme === "light" ? 5 : 12,
|
||||
}[brightness]
|
||||
const adjusted = { ...variables }
|
||||
|
||||
for (const name of surfaceVariableNames) {
|
||||
const value = variables[name]
|
||||
if (value) {
|
||||
adjusted[name] = `color-mix(in oklch,${value},${target} ${amount}%)`
|
||||
}
|
||||
}
|
||||
|
||||
return adjusted
|
||||
}
|
||||
Reference in New Issue
Block a user