Files
bchen-ui/dist/tokens.css
Brendan Chen 6b06d00115 feat: add @bchen/ui v0.1.0 — dark-mode token palette and 16px base rule
- dist/tokens.css: canonical light + @media dark semantic-token palette
  extracted from inventory (cross-checked against authd and buchinese).
  Covers --fg, --fg-muted, --bg, --bg-elevated, --surface, --accent*,
  --danger*, --border*, --input-*, --warning, primitive --gray-* scale.
- dist/base.css: `input, textarea, select { font-size: 16px; }` prevents
  iOS Safari auto-zoom on focus.
- tests/tokens.test.ts: vitest — token presence in both light and dark
  blocks; WCAG AA contrast (>=4.5:1 body, >=3.0:1 UI) via inline
  hex-to-luminance math. All 10 tests green.
- tests/base.test.ts: vitest — asserts 16px rule covers all three selectors.
- .gitea/workflows/release.yml: tag-triggered CI — npm ci + npm test,
  CHANGELOG version gate, dist/scripts security grep, Gitea release
  artifact upload.
- README.md: four-step consumer integration guide with copy-pasteable
  snippets (package.json dep, Dockerfile cp, HTML link tags, app CSS).
- CHANGELOG.md: v0.1.0 entry.

npm audit --omit=dev: 0 vulnerabilities

Closes #1
2026-05-13 17:56:08 -07:00

71 lines
1.9 KiB
CSS

/* @bchen/ui v0.1.0 — semantic token palette
* Canonical light + dark values extracted from the bchen.dev fleet.
* Source of truth: inventory (cross-checked against authd, buchinese). */
:root {
/* Primitive palette */
--black: #000;
--white: #fff;
--gray-50: #fafafa;
--gray-100: #f0f0f0;
--gray-200: #e0e0e0;
--gray-400: #999;
--gray-600: #555;
--red: #c00;
/* Typography */
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
--font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
/* Layout */
--radius: 0;
--header-height: 48px;
/* Border tokens */
--border-color: var(--gray-200);
--border-strong: var(--black);
--border: 1px solid var(--border-strong);
/* Semantic color tokens */
--fg: var(--black);
--fg-muted: var(--gray-600);
--bg: var(--white);
--bg-elevated: var(--gray-50);
--surface: var(--white);
--accent: var(--black);
--accent-fg: var(--white);
--accent-hover: var(--gray-600);
--danger: var(--red);
--danger-fg: var(--white);
--danger-bg: #fff5f5;
--warning: var(--gray-600);
/* Input tokens */
--input-bg: var(--white);
--input-fg: var(--black);
--input-border: var(--black);
--input-bg-focus: var(--gray-50);
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #0f1115;
--bg-elevated: #1a1d23;
--surface: #0f1115;
--fg: #e5e7eb;
--fg-muted: #9ca3af;
--border-color: #374151;
--border-strong: #6b7280;
--accent: #e5e7eb;
--accent-fg: #0f1115;
--accent-hover: #cbd5e1;
--danger: #f87171;
--danger-fg: #0f1115;
--danger-bg: rgba(248, 113, 113, 0.12);
--input-bg: #1a1d23;
--input-fg: #e5e7eb;
--input-border: #6b7280;
--input-bg-focus: #0f1115;
}
}