78 lines
2.0 KiB
TypeScript
78 lines
2.0 KiB
TypeScript
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
|
|
}
|