import type { ThemeScheme } from "./internal/themes" export type Brightness = "dim" | "normal" | "bright" export type MotionMode = "system" | "reduce" | "full" export type ResolvedMotionMode = Exclude 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, brightness: Brightness, scheme: ThemeScheme ): Record { 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 }