understanding

This commit is contained in:
2026-02-06 16:29:09 -05:00
parent bfea6816ef
commit 1cee931913
13 changed files with 161 additions and 398 deletions

View File

@@ -3,46 +3,54 @@
* Handles dynamic theme switching by updating CSS custom properties
*/
import { RGBA, type TerminalColors } from "@opentui/core"
import type { ThemeColors } from "../types/settings"
import type { ColorValue, ThemeJson } from "../types/theme-schema"
import { THEME_JSON } from "../constants/themes"
import { getCustomThemes } from "./custom-themes"
import { resolveTheme as resolveThemeJson } from "./theme-resolver"
import { generateSystemTheme } from "./system-theme"
import { RGBA, type TerminalColors } from "@opentui/core";
import type { ThemeColors } from "../types/settings";
import type { ColorValue, ThemeJson } from "../types/theme-schema";
import { THEME_JSON } from "../constants/themes";
import { getCustomThemes } from "./custom-themes";
import { resolveTheme as resolveThemeJson } from "./theme-resolver";
import { generateSystemTheme } from "./system-theme";
const toCss = (value: ColorValue | RGBA) => {
if (value instanceof RGBA) {
const r = Math.round(value.r * 255)
const g = Math.round(value.g * 255)
const b = Math.round(value.b * 255)
return `rgba(${r}, ${g}, ${b}, ${value.a})`
const r = Math.round(value.r * 255);
const g = Math.round(value.g * 255);
const b = Math.round(value.b * 255);
return `rgba(${r}, ${g}, ${b}, ${value.a})`;
}
if (typeof value === "number") return `var(--ansi-${value})`
if (typeof value === "string") return value
return value.dark
}
if (typeof value === "number") return `var(--ansi-${value})`;
if (typeof value === "string") return value;
return value.dark;
};
export function applyTheme(theme: ThemeColors | Record<string, RGBA>) {
if (typeof document === "undefined") return
const root = document.documentElement
root.style.setProperty("--color-background", toCss(theme.background as ColorValue))
root.style.setProperty("--color-surface", toCss(theme.surface as ColorValue))
root.style.setProperty("--color-primary", toCss(theme.primary as ColorValue))
root.style.setProperty("--color-secondary", toCss(theme.secondary as ColorValue))
root.style.setProperty("--color-accent", toCss(theme.accent as ColorValue))
root.style.setProperty("--color-text", toCss(theme.text as ColorValue))
root.style.setProperty("--color-muted", toCss(theme.muted as ColorValue))
root.style.setProperty("--color-warning", toCss(theme.warning as ColorValue))
root.style.setProperty("--color-error", toCss(theme.error as ColorValue))
root.style.setProperty("--color-success", toCss(theme.success as ColorValue))
if (typeof document === "undefined") return;
const root = document.documentElement;
root.style.setProperty(
"--color-background",
toCss(theme.background as ColorValue),
);
root.style.setProperty("--color-surface", toCss(theme.surface as ColorValue));
root.style.setProperty("--color-primary", toCss(theme.primary as ColorValue));
root.style.setProperty(
"--color-secondary",
toCss(theme.secondary as ColorValue),
);
root.style.setProperty("--color-accent", toCss(theme.accent as ColorValue));
root.style.setProperty("--color-text", toCss(theme.text as ColorValue));
root.style.setProperty("--color-muted", toCss(theme.muted as ColorValue));
root.style.setProperty("--color-warning", toCss(theme.warning as ColorValue));
root.style.setProperty("--color-error", toCss(theme.error as ColorValue));
root.style.setProperty("--color-success", toCss(theme.success as ColorValue));
const layers = theme.layerBackgrounds as Record<string, ColorValue> | undefined
const layers = theme.layerBackgrounds as
| Record<string, ColorValue>
| undefined;
if (layers) {
root.style.setProperty("--color-layer0", toCss(layers.layer0))
root.style.setProperty("--color-layer1", toCss(layers.layer1))
root.style.setProperty("--color-layer2", toCss(layers.layer2))
root.style.setProperty("--color-layer3", toCss(layers.layer3))
root.style.setProperty("--color-layer0", toCss(layers.layer0));
root.style.setProperty("--color-layer1", toCss(layers.layer1));
root.style.setProperty("--color-layer2", toCss(layers.layer2));
root.style.setProperty("--color-layer3", toCss(layers.layer3));
}
}
@@ -50,46 +58,46 @@ export function applyTheme(theme: ThemeColors | Record<string, RGBA>) {
* Get theme mode from system preference
*/
export function getSystemThemeMode(): "dark" | "light" {
if (typeof window === "undefined") return "dark"
if (typeof window === "undefined") return "dark";
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches
return prefersDark ? "dark" : "light"
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
return prefersDark ? "dark" : "light";
}
/**
* Apply CSS variable data-theme attribute
*/
export function setThemeAttribute(themeName: string) {
if (typeof document === "undefined") return
const root = document.documentElement
root.setAttribute("data-theme", themeName)
if (typeof document === "undefined") return;
const root = document.documentElement;
root.setAttribute("data-theme", themeName);
}
export async function loadThemes() {
return await getCustomThemes()
return await getCustomThemes();
}
export async function loadTheme(name: string) {
const themes = await loadThemes()
return themes[name]
const themes = await loadThemes();
return themes[name];
}
export function resolveTheme(theme: ThemeJson, mode: "dark" | "light") {
return resolveThemeJson(theme, mode)
return resolveThemeJson(theme, mode);
}
export function resolveTerminalTheme(
themes: Record<string, ThemeJson>,
name: string,
mode: "dark" | "light",
system?: TerminalColors
system?: TerminalColors,
) {
if (name === "system" && system) {
return resolveThemeJson(generateSystemTheme(system, mode), mode)
return resolveThemeJson(generateSystemTheme(system, mode), mode);
}
const theme = themes[name] ?? themes.opencode
const theme = themes[name] ?? themes.catppuccin;
if (!theme) {
return resolveThemeJson(THEME_JSON.opencode, mode)
return resolveThemeJson(THEME_JSON.catppuccin, mode);
}
return resolveThemeJson(theme, mode)
return resolveThemeJson(theme, mode);
}