Files
simple-react-app-kit/packages/appearance/src/theme.ts
T

81 lines
1.9 KiB
TypeScript

import {
themes,
type AccentColor,
type BaseColor,
type ThemeColorConfig,
type ThemeScheme,
} from "./internal/themes"
import {
getColorVisionCssVariables,
type ColorVisionMode,
} from "./color-vision"
import { applyBrightnessToTheme, type Brightness } from "./display"
export {
accentColors,
baseColors,
themes,
type AccentColor,
type BaseColor,
type Theme,
type ThemeColorConfig,
type ThemeScheme,
} from "./internal/themes"
export const THEME_STYLE_ELEMENT_ID = "ui-theme-variables"
export const getTheme = (name: BaseColor | AccentColor) =>
themes.find((theme) => theme.name === name)
export function getThemeCssVariables(
scheme: ThemeScheme,
config: ThemeColorConfig
) {
const base = getTheme(config.baseColor) ?? getTheme("neutral")!
const accent = getTheme(config.accentColor) ?? getTheme("blue")!
return {
...base.cssVars[scheme],
...accent.cssVars[scheme],
}
}
function serializeThemeVariables(theme: Record<string, string>): string {
return Object.entries(theme)
.map(([key, value]) => `--${key}:${value}`)
.join(";")
}
export function buildThemeStyleSheet(
config: ThemeColorConfig,
colorVisionMode: ColorVisionMode = "standard",
brightness: Brightness = "normal"
) {
const light = serializeThemeVariables(
applyBrightnessToTheme(
{
...getThemeCssVariables("light", config),
...getColorVisionCssVariables(colorVisionMode, "light"),
},
brightness,
"light"
)
)
const dark = serializeThemeVariables(
applyBrightnessToTheme(
{
...getThemeCssVariables("dark", config),
...getColorVisionCssVariables(colorVisionMode, "dark"),
},
brightness,
"dark"
)
)
return [
`:root,.ui\\:light{${light}}`,
`.ui\\:dark{${dark}}`,
`@media (prefers-color-scheme:dark){:root:not(.ui\\:light):not(.ui\\:dark){${dark}}}`,
].join("")
}