Files
yaak/src-web/lib/theme/window.ts
Gregory Schier 317ca24dcf Fix small view
2023-03-07 22:55:51 -08:00

102 lines
2.8 KiB
TypeScript

import type { AppTheme } from './theme';
import { generateCSS, toTailwindVariable } from './theme';
export type Appearance = 'dark' | 'light';
const darkTheme: AppTheme = {
name: 'Default Dark',
appearance: 'dark',
layers: {
root: {
blackPoint: 0.1,
whitePoint: 0.95,
colors: {
gray: '#656196',
red: '#ee3b3b',
orange: '#ff9411',
yellow: '#dcdc3b',
green: '#44cb44',
blue: '#2e91ff',
pink: '#f670f6',
violet: '#ae70ff',
},
},
},
};
const lightTheme: AppTheme = {
name: 'Default Light',
appearance: 'light',
layers: {
root: {
blackPoint: 0.1,
whitePoint: 1,
colors: {
gray: '#7f8fb0',
red: '#e13939',
orange: '#da881f',
yellow: '#cb9f2a',
green: '#37c237',
blue: '#1365ff',
pink: '#e861e8',
violet: '#8d47ff',
},
},
},
};
export function getAppearance(): Appearance {
const docAppearance = document.documentElement.getAttribute('data-appearance');
if (docAppearance === 'dark' || docAppearance === 'light') {
return docAppearance;
}
return getPreferredAppearance();
}
export function toggleAppearance(): Appearance {
const currentTheme =
document.documentElement.getAttribute('data-appearance') ?? getPreferredAppearance();
const newAppearance = currentTheme === 'dark' ? 'light' : 'dark';
setAppearance(newAppearance);
return newAppearance;
}
export function setAppearance(a?: Appearance) {
const appearance = a ?? getPreferredAppearance();
const theme = appearance === 'dark' ? darkTheme : lightTheme;
document.documentElement.setAttribute('data-appearance', appearance);
document.documentElement.setAttribute('data-theme', theme.name);
let existingStyleEl = document.head.querySelector(`style[data-theme-definition]`);
if (!existingStyleEl) {
const styleEl = document.createElement('style');
document.head.appendChild(styleEl);
existingStyleEl = styleEl;
}
existingStyleEl.textContent = [
`/* ${darkTheme.name} */`,
`[data-appearance="dark"] {`,
...generateCSS(darkTheme).map(toTailwindVariable),
'}',
`/* ${lightTheme.name} */`,
`[data-appearance="light"] {`,
...generateCSS(lightTheme).map(toTailwindVariable),
'}',
].join('\n');
existingStyleEl.setAttribute('data-theme-definition', '');
}
export function getPreferredAppearance(): Appearance {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
export function subscribeToPreferredAppearanceChange(
cb: (appearance: Appearance) => void,
): () => void {
const listener = (e: MediaQueryListEvent) => cb(e.matches ? 'dark' : 'light');
const m = window.matchMedia('(prefers-color-scheme: dark)');
m.addEventListener('change', listener);
return () => m.removeEventListener('change', listener);
}