A political conference and discussion platform, in Rust and Dioxus
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143#!/usr/bin/env -S deno run --allow-net --allow-read --allow-env// Generate the app's Material Design 3 colour scheme from brand seed colours,// using Google's material-color-utilities (the same engine as the Material// Theme Builder). Emits canonical `--md-sys-color-*` tokens for light + dark.//// The scheme is fully REPLACEABLE: change the two seeds below (or pass them as// args) and re-run to re-skin the entire app — every component reads the// generated tokens (directly or via the `--md-*` aliases in style.css).//// deno run scripts/gen-theme.ts # default Radikale seeds// deno run scripts/gen-theme.ts "#02944F" "#D2307E" # primary, accent// deno run scripts/gen-theme.ts > assets/m3-theme.css # regenerate in place//// Radikale Venstre 2025 brand: grøn #02944F + magenta #D2307E — "de to farver// bør altid optræde sammen". Green leads as the M3 primary; magenta is the// tertiary accent.import { argbFromHex, hexFromArgb, themeFromSourceColor,} from "npm:@material/material-color-utilities@0.3.0";
const PRIMARY = Deno.args[0] ?? "#02944F"; // Radikale grøn → M3 primaryconst TERTIARY = Deno.args[1] ?? "#D2307E"; // Radikale magenta → M3 tertiary accentconst LABEL = Deno.args[2] ?? "green-primary (Radikale)";
const theme = themeFromSourceColor(argbFromHex(PRIMARY), [ { name: "accent", value: argbFromHex(TERTIARY), blend: false },]);
const H = (n: number) => hexFromArgb(n);
// M3 surface-container tones read off the neutral tonal palette (spec values).const SURF_LIGHT: Record<string, number> = { "surface-dim": 87, "surface-bright": 98, "surface-container-lowest": 100, "surface-container-low": 96, "surface-container": 94, "surface-container-high": 92, "surface-container-highest": 90,};const SURF_DARK: Record<string, number> = { "surface-dim": 6, "surface-bright": 24, "surface-container-lowest": 4, "surface-container-low": 10, "surface-container": 12, "surface-container-high": 17, "surface-container-highest": 22,};
type Accent = { color: number; onColor: number; colorContainer: number; onColorContainer: number;};
function tokens( scheme: Record<string, number>, accent: Accent, isDark: boolean,): Record<string, string> { const S = (k: string) => H(scheme[k]); const N = (t: number) => H(theme.palettes.neutral.tone(t)); const surf = isDark ? SURF_DARK : SURF_LIGHT; return { primary: S("primary"), "on-primary": S("onPrimary"), "primary-container": S("primaryContainer"), "on-primary-container": S("onPrimaryContainer"), secondary: S("secondary"), "on-secondary": S("onSecondary"), "secondary-container": S("secondaryContainer"), "on-secondary-container": S("onSecondaryContainer"), // Tertiary = the accent brand colour, tonally correct for this mode. tertiary: H(accent.color), "on-tertiary": H(accent.onColor), "tertiary-container": H(accent.colorContainer), "on-tertiary-container": H(accent.onColorContainer), error: S("error"), "on-error": S("onError"), "error-container": S("errorContainer"), "on-error-container": S("onErrorContainer"), background: S("background"), "on-background": S("onBackground"), surface: S("surface"), "on-surface": S("onSurface"), "surface-variant": S("surfaceVariant"), "on-surface-variant": S("onSurfaceVariant"), "surface-dim": N(surf["surface-dim"]), "surface-bright": N(surf["surface-bright"]), "surface-container-lowest": N(surf["surface-container-lowest"]), "surface-container-low": N(surf["surface-container-low"]), "surface-container": N(surf["surface-container"]), "surface-container-high": N(surf["surface-container-high"]), "surface-container-highest": N(surf["surface-container-highest"]), outline: S("outline"), "outline-variant": S("outlineVariant"), shadow: S("shadow"), scrim: S("scrim"), "inverse-surface": S("inverseSurface"), "inverse-on-surface": S("inverseOnSurface"), "inverse-primary": S("inversePrimary"), "surface-tint": S("primary"), };}
function block(selector: string, toks: Record<string, string>): string { const lines = Object.entries(toks).map( ([k, v]) => ` --md-sys-color-${k}: ${v};`, ); return `${selector} {\n${lines.join("\n")}\n}`;}
// deno-lint-ignore no-explicit-anyconst anyTheme = theme as any;const light = tokens( anyTheme.schemes.light, theme.customColors[0].light, false,);const dark = tokens(anyTheme.schemes.dark, theme.customColors[0].dark, true);
const header = `/* Material Design 3 colour scheme — GENERATED by scripts/gen-theme.ts. * DO NOT EDIT BY HAND — re-run the generator to change it. * * Variant: ${LABEL} * --md-sys-color-primary seeded from ${PRIMARY} * --md-sys-color-tertiary seeded from ${TERTIARY} * * These are the canonical M3 system-colour roles. The app's shorthand --md-* * tokens (assets/style.css) alias them, so every component re-skins when this * file is regenerated from new seeds. */`;
console.log(header);console.log();console.log(block(':root,\nhtml[data-theme="light"]', light));console.log();console.log(block('html[data-theme="dark"]', dark));