add theme patterns
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
// Theme helpers — derive subtle pattern shades from a user's chosen color
|
||||
// swatch. Patterns in theme-patterns.css read --c1..--c4; we override them
|
||||
// with hsl variations of the user's hue so the background stays subtle.
|
||||
|
||||
export function hexToHsl(hex: string): { h: number; s: number; l: number } {
|
||||
const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());
|
||||
if (!m) return { h: 243, s: 75, l: 66 }; // indigo fallback
|
||||
const n = parseInt(m[1], 16);
|
||||
const r = ((n >> 16) & 255) / 255;
|
||||
const g = ((n >> 8) & 255) / 255;
|
||||
const b = (n & 255) / 255;
|
||||
const max = Math.max(r, g, b);
|
||||
const min = Math.min(r, g, b);
|
||||
const l = (max + min) / 2;
|
||||
if (max === min) return { h: 0, s: 0, l: Math.round(l * 100) };
|
||||
const d = max - min;
|
||||
const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||
let h = 0;
|
||||
if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
|
||||
else if (max === g) h = ((b - r) / d + 2) / 6;
|
||||
else h = ((r - g) / d + 4) / 6;
|
||||
return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) };
|
||||
}
|
||||
|
||||
// Four subtle shades built on the swatch's hue — pastel tints distinct
|
||||
// enough that the pattern motif reads against the near-white app shell,
|
||||
// but soft enough to stay a background wash rather than a loud print.
|
||||
// `alpha` (0..1) fades the whole motif toward the shell background — the
|
||||
// app-shell keeps `background: whitesmoke` underneath, so lowering it
|
||||
// blends the pattern out.
|
||||
export function themeShades(
|
||||
hex: string,
|
||||
alpha = 1
|
||||
): { c1: string; c2: string; c3: string; c4: string } {
|
||||
const { h } = hexToHsl(hex);
|
||||
return {
|
||||
c1: `hsl(${h} 45% 93% / ${alpha})`,
|
||||
c2: `hsl(${h} 50% 85% / ${alpha})`,
|
||||
c3: `hsl(${h} 55% 74% / ${alpha})`,
|
||||
c4: `hsl(${(h + 40) % 360} 50% 87% / ${alpha})`
|
||||
};
|
||||
}
|
||||
|
||||
// Pattern ids: 'p1'..'p60', '' = none. Currently showing the first 19;
|
||||
// bump this to include more (the CSS file still ships all 60).
|
||||
export const PATTERN_COUNT = 19;
|
||||
export function patternId(n: number): string {
|
||||
return `p${n}`;
|
||||
}
|
||||
|
||||
// Pattern size slider — the value is the pattern's `--s` in vw units, so the
|
||||
// motif scales with the viewport. E.g. 7 at a 1400px screen ≈ 98px tiles.
|
||||
export const THEME_SIZE_MIN = 2;
|
||||
export const THEME_SIZE_MAX = 16;
|
||||
export const THEME_SIZE_DEFAULT = 7;
|
||||
|
||||
// Pattern opacity slider — 1 = current full visibility, down to a faint hint.
|
||||
export const THEME_OPACITY_MIN = 0.05;
|
||||
export const THEME_OPACITY_MAX = 1;
|
||||
export const THEME_OPACITY_STEP = 0.05;
|
||||
export const THEME_OPACITY_DEFAULT = 1;
|
||||
Reference in New Issue
Block a user