initial commit

This commit is contained in:
michael
2026-03-03 17:59:56 -08:00
commit 1c8d5855e6
56 changed files with 11767 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
{
"name": "@dangerousthings/tokens",
"version": "0.1.0",
"description": "Canonical design tokens for the Dangerous Things design system",
"license": "MIT",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
},
"./brands/*": {
"types": "./dist/brands/*.d.ts",
"import": "./dist/brands/*.js"
},
"./css/*": "./dist/css/*"
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"publishConfig": {
"access": "public"
},
"files": [
"dist"
],
"scripts": {
"build": "tsc && node dist/scripts/generate-css.js",
"clean": "rm -rf dist",
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@types/node": "^25.3.3",
"typescript": "^5.7.0"
}
}

View File

@@ -0,0 +1,66 @@
import type { BrandTokens } from "../types.js";
export const classic: BrandTokens = {
id: "classic",
name: "Classic Cyberpunk",
description: "Original dark navy aesthetic with magenta accents",
dark: {
bg: "#0a0e1a",
surface: "#121827",
surfaceHover: "#1a2332",
border: "#1e293b",
textPrimary: "#e2e8f0",
textSecondary: "#94a3b8",
textMuted: "#64748b",
primary: "#00ffff",
primaryDim: "#0891b2",
secondary: "#ff00ff",
accent: "#00ff88",
other: "#ff00ff",
success: "#00ff88",
warning: "#ffaa00",
error: "#ff0055",
info: "#00ffff",
},
light: {
bg: "#ffffff",
surface: "#f8fafc",
surfaceHover: "#f1f5f9",
border: "#e2e8f0",
textPrimary: "#0f172a",
textSecondary: "#475569",
textMuted: "#94a3b8",
primary: "#0891b2",
primaryDim: "#0e7490",
secondary: "#c026d3",
accent: "#00ff88",
other: "#c026d3",
success: "#16a34a",
warning: "#d97706",
error: "#dc2626",
info: "#0891b2",
},
typography: {
heading: "var(--font-sans)",
body: "var(--font-sans)",
mono: "'SF Mono', Monaco, 'Cascadia Code', monospace",
},
shape: {
bevelSm: "0px",
bevelMd: "0px",
bevelLg: "0px",
radiusSm: "0.25rem",
radius: "0.5rem",
radiusLg: "0.75rem",
},
};

View File

@@ -0,0 +1,66 @@
import type { BrandTokens } from "../types.js";
export const dt: BrandTokens = {
id: "dt",
name: "Dangerous Things",
description: "Official DT brand — Tektur font, neon cyberpunk, beveled corners",
dark: {
bg: "#000000",
surface: "#0a0a0a",
surfaceHover: "#141414",
border: "#00ffff",
textPrimary: "#ffffff",
textSecondary: "#e2e8f0",
textMuted: "#94a3b8",
primary: "#00ffff",
primaryDim: "#0891b2",
secondary: "#ffff00",
accent: "#00ff00",
other: "#ff00ff",
success: "#00ff00",
warning: "#ffff00",
error: "#ff0000",
info: "#00ffff",
},
light: {
bg: "#ffffff",
surface: "#f8fafc",
surfaceHover: "#f1f5f9",
border: "#000000",
textPrimary: "#000000",
textSecondary: "#475569",
textMuted: "#94a3b8",
primary: "#0891b2",
primaryDim: "#0e7490",
secondary: "#a16207",
accent: "#15803d",
other: "#ff00ff",
success: "#15803d",
warning: "#a16207",
error: "#dc2626",
info: "#0891b2",
},
typography: {
heading: "'Tektur', var(--font-sans)",
body: "'Tektur', var(--font-sans)",
mono: "'SF Mono', Monaco, 'Cascadia Code', monospace",
},
shape: {
bevelSm: "1rem",
bevelMd: "2rem",
bevelLg: "2.5rem",
radiusSm: "0",
radius: "0",
radiusLg: "0",
},
};

View File

@@ -0,0 +1,66 @@
import type { BrandTokens } from "../types.js";
export const supra: BrandTokens = {
id: "supra",
name: "VivoKey Supra",
description: "Material Design 3 with VivoKey blue, rounded corners, elevation shadows",
dark: {
bg: "#000000",
surface: "#28292E",
surfaceHover: "#303136",
border: "#42667E",
textPrimary: "#ffffff",
textSecondary: "#e2e8f0",
textMuted: "#94a3b8",
primary: "#42667E",
primaryDim: "#385872",
secondary: "#8BAEC7",
accent: "#8BAEC7",
other: "#F67448",
success: "#8BB174",
warning: "#F67448",
error: "#ED4337",
info: "#42667E",
},
light: {
bg: "#ffffff",
surface: "#AFB8C2",
surfaceHover: "#C5CCD4",
border: "#000000",
textPrimary: "#000000",
textSecondary: "#374151",
textMuted: "#6b7280",
primary: "#000000",
primaryDim: "#1f2937",
secondary: "#F67448",
accent: "#FDFE1B",
other: "#F67448",
success: "#8BB174",
warning: "#F67448",
error: "#ED4337",
info: "#42667E",
},
typography: {
heading: "var(--font-sans)",
body: "var(--font-sans)",
mono: "'SF Mono', Monaco, 'Cascadia Code', monospace",
},
shape: {
bevelSm: "0px",
bevelMd: "0px",
bevelLg: "0px",
radiusSm: "0.5rem",
radius: "0.625rem",
radiusLg: "0.75rem",
},
};

View File

@@ -0,0 +1,46 @@
export type {
ThemeBrand,
ThemeMode,
ThemeDefinition,
ColorTokens,
TypographyTokens,
ShapeTokens,
BrandTokens,
} from "./types.js";
export { dt } from "./brands/dt.js";
export { classic } from "./brands/classic.js";
export { supra } from "./brands/supra.js";
import { dt } from "./brands/dt.js";
import { classic } from "./brands/classic.js";
import { supra } from "./brands/supra.js";
import type { BrandTokens, ThemeDefinition } from "./types.js";
/** All brand tokens keyed by id */
export const brands: Record<string, BrandTokens> = { dt, classic, supra };
/** Theme registry for UI selectors */
export const themes: ThemeDefinition[] = [
{
id: "dt",
name: dt.name,
description: dt.description,
supportsModes: ["dark", "light", "auto"],
defaultMode: "dark",
},
{
id: "classic",
name: classic.name,
description: classic.description,
supportsModes: ["dark", "light", "auto"],
defaultMode: "dark",
},
{
id: "supra",
name: supra.name,
description: supra.description,
supportsModes: ["dark", "light", "auto"],
defaultMode: "dark",
},
];

View File

@@ -0,0 +1,129 @@
/**
* Generates CSS custom property files from canonical TypeScript token definitions.
* Run via: node dist/scripts/generate-css.js
* Output: dist/css/{brand}.css
*/
import { writeFileSync, mkdirSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import type { BrandTokens, ColorTokens } from "../types.js";
import { dt } from "../brands/dt.js";
import { classic } from "../brands/classic.js";
import { supra } from "../brands/supra.js";
const __dirname = dirname(fileURLToPath(import.meta.url));
const outDir = join(__dirname, "..", "css");
/** Convert hex #rrggbb to "r, g, b" triplet for rgba() usage */
function hexToRgb(hex: string): string {
const h = hex.replace("#", "");
const r = parseInt(h.substring(0, 2), 16);
const g = parseInt(h.substring(2, 4), 16);
const b = parseInt(h.substring(4, 6), 16);
return `${r}, ${g}, ${b}`;
}
/** Generate CSS custom properties from color tokens */
function colorVars(colors: ColorTokens): string {
return ` /* Backgrounds */
--color-bg: ${colors.bg};
--color-bg-rgb: ${hexToRgb(colors.bg)};
--color-surface: ${colors.surface};
--color-surface-rgb: ${hexToRgb(colors.surface)};
--color-surface-hover: ${colors.surfaceHover};
--color-border: ${colors.border};
/* Text */
--color-text-primary: ${colors.textPrimary};
--color-text-secondary: ${colors.textSecondary};
--color-text-muted: ${colors.textMuted};
/* Brand Palette */
--color-primary: ${colors.primary};
--color-primary-rgb: ${hexToRgb(colors.primary)};
--color-primary-dim: ${colors.primaryDim};
--color-secondary: ${colors.secondary};
--color-secondary-rgb: ${hexToRgb(colors.secondary)};
--color-accent: ${colors.accent};
--color-accent-rgb: ${hexToRgb(colors.accent)};
--color-other: ${colors.other};
--color-other-rgb: ${hexToRgb(colors.other)};
/* Status */
--color-success: ${colors.success};
--color-success-rgb: ${hexToRgb(colors.success)};
--color-warning: ${colors.warning};
--color-warning-rgb: ${hexToRgb(colors.warning)};
--color-error: ${colors.error};
--color-error-rgb: ${hexToRgb(colors.error)};
--color-info: ${colors.info};
--color-info-rgb: ${hexToRgb(colors.info)};`;
}
/** Generate a full brand CSS file */
function generateBrandCSS(brand: BrandTokens): string {
const id = brand.id;
// DT is also the default (when no data-brand is set)
const darkSelector =
id === "dt"
? `:root[data-brand="${id}"],\n:root:not([data-brand])`
: `:root[data-brand="${id}"]`;
let css = `/* @dangerousthings/tokens — Generated CSS for "${brand.name}" */\n/* DO NOT EDIT — regenerate with: npm run build -w packages/tokens */\n\n`;
// Dark mode (default)
css += `/* ${brand.name} — Dark Mode (Default) */\n`;
css += `${darkSelector} {\n`;
css += colorVars(brand.dark) + "\n\n";
css += ` /* Typography */\n`;
css += ` --font-heading: ${brand.typography.heading};\n`;
css += ` --font-body: ${brand.typography.body};\n\n`;
css += ` /* Shape */\n`;
css += ` --bevel-sm: ${brand.shape.bevelSm};\n`;
css += ` --bevel-md: ${brand.shape.bevelMd};\n`;
css += ` --bevel-lg: ${brand.shape.bevelLg};\n`;
css += ` --radius-sm: ${brand.shape.radiusSm};\n`;
css += ` --radius: ${brand.shape.radius};\n`;
css += ` --radius-lg: ${brand.shape.radiusLg};\n\n`;
css += ` color-scheme: dark;\n`;
css += `}\n\n`;
// Light mode (explicit)
css += `/* ${brand.name} — Light Mode */\n`;
css += `:root[data-brand="${id}"][data-theme="light"] {\n`;
css += colorVars(brand.light) + "\n\n";
css += ` color-scheme: light;\n`;
css += `}\n\n`;
// Auto mode (prefers-color-scheme)
css += `/* ${brand.name} — Auto Mode (follows system preference) */\n`;
css += `@media (prefers-color-scheme: light) {\n`;
css += ` :root[data-brand="${id}"][data-theme="auto"] {\n`;
css += colorVars(brand.light).replace(/^/gm, " ") + "\n\n";
css += ` color-scheme: light;\n`;
css += ` }\n`;
css += `}\n`;
// DT gets explicit dark override
if (id === "dt") {
css += `\n/* Force dark explicitly */\n`;
css += `:root[data-brand="${id}"][data-theme="dark"] {\n`;
css += ` color-scheme: dark;\n`;
css += `}\n`;
}
return css;
}
// --- Main ---
mkdirSync(outDir, { recursive: true });
for (const brand of [dt, classic, supra]) {
const css = generateBrandCSS(brand);
const path = join(outDir, `${brand.id}.css`);
writeFileSync(path, css, "utf-8");
console.log(` tokens: generated ${path}`);
}
console.log(" tokens: CSS generation complete");

View File

@@ -0,0 +1,65 @@
/** Brand identifiers */
export type ThemeBrand = "dt" | "classic" | "supra";
/** Color mode */
export type ThemeMode = "dark" | "light" | "auto";
/** Theme metadata for UI selectors */
export interface ThemeDefinition {
id: ThemeBrand;
name: string;
description: string;
supportsModes: ThemeMode[];
defaultMode: ThemeMode;
}
/** Color tokens for a single mode */
export interface ColorTokens {
bg: string;
surface: string;
surfaceHover: string;
border: string;
textPrimary: string;
textSecondary: string;
textMuted: string;
primary: string;
primaryDim: string;
secondary: string;
accent: string;
other: string;
success: string;
warning: string;
error: string;
info: string;
}
/** Typography tokens */
export interface TypographyTokens {
heading: string;
body: string;
mono: string;
}
/** Shape tokens */
export interface ShapeTokens {
bevelSm: string;
bevelMd: string;
bevelLg: string;
radiusSm: string;
radius: string;
radiusLg: string;
}
/** Complete brand definition */
export interface BrandTokens {
id: ThemeBrand;
name: string;
description: string;
dark: ColorTokens;
light: ColorTokens;
typography: TypographyTokens;
shape: ShapeTokens;
}

View File

@@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}