@jflamb/ledger
v0.1.0
Published
Ledger — design tokens for jflamb.com, assistant.jflamb.com, and retirement.jflamb.com. Ink on warm paper, viridian brand, semantic tokens underneath.
Maintainers
Readme
Ledger
Ledger is the shared CSS foundation for jflamb.com, Assistant Workbench, and the Retirement Dashboard. It gives the three products one visual identity: ink on warm paper, a viridian brand, serif prose, mono figures, and rules instead of decorative shadows.
The package is intentionally small. It provides versioned design tokens, themes, accessibility defaults, and a stable contract for site-local components. It does not force the three products into one component library.
Install
npm install @jflamb/ledgerUntil the first npm release is published, projects can install the package directly from this public repository:
npm install github:jflamb/ledgerImport the stylesheet from application CSS:
@import "@jflamb/ledger/ledger.css";Or import it from JavaScript when the bundler handles CSS:
import "@jflamb/ledger/ledger.css";For a site without npm tooling, use a version-pinned CDN URL or vendor the file into the site repository:
<link rel="stylesheet" href="https://unpkg.com/@jflamb/[email protected]/ledger.css">Pin the version in production. Do not load an unversioned latest URL.
Use semantic tokens
Site components should use semantic roles rather than palette values:
.panel {
color: var(--color-text-primary);
background: var(--color-surface-panel);
border: 1px solid var(--color-border);
border-radius: var(--radius-static);
padding: var(--space-4);
}
.primary-action {
min-block-size: var(--control-min-block-size);
color: var(--color-text-on-action);
background: var(--color-action);
border-radius: var(--radius-control);
}
.primary-action:focus-visible {
outline: var(--focus-ring);
outline-offset: var(--focus-ring-offset);
}Palette primitives such as --viridian and --paper are implementation details. Keeping components on semantic tokens lets Ledger improve contrast or rebalance themes without requiring component rewrites.
Rules of consumption
- Components consume only layer-2 semantic tokens (
--color-*,--font-*,--text-*,--space-*,--radius-*,--control-*,--focus-*,--shadow-*). Layer-1 primitives (--paper,--ink,--viridian, …) are private toledger.cssand are the only values that change per theme. - Color never carries meaning alone. Every status has a text label; selection changes border weight and adds a check, not just a fill.
- Square is static, round is interactive.
--radius-staticfor panels and tables;--radius-control/--radius-selectablemark what can be operated. - Shadows are for overlays only (
--shadow-overlay): menus, tooltips, dialogs. Static grouping uses rules and the one-step paper raise. - Type roles:
--font-prose(serif) for display and explanatory text,--font-ui(system sans) for controls/navigation/dense labels,--font-monofor figures, dates, codes, and short statuses (withfont-variant-numeric: tabular-nums). - Site-local tokens (e.g. the dashboard's
--chart-*) may alias down to Ledger tokens; they may not redefine shared names.
Token families
--color-*: text, surfaces, borders, actions, focus, and statuses--font-*: prose, interface, and numeric roles--text-*: type scale--space-*: 4px spacing scale--radius-*: static, tag, control, selectable, and pill shapes--control-*: interaction sizing--focus-*: keyboard focus treatment--shadow-*: overlays only
The full token list and values live in ledger.css.
Theming
ledger.css defines light (default), dark (prefers-color-scheme and :root[data-theme="dark"], so a manual toggle beats the system), high contrast (prefers-contrast: more), and print. The theme preference is shared across subdomains via a first-party cookie — localStorage is origin-scoped and serves only as a same-origin fallback:
// set on toggle — readable by every *.jflamb.com origin
document.cookie =
"jflamb-theme=dark; Domain=.jflamb.com; Path=/; Max-Age=31536000; SameSite=Lax; Secure";
// no-flash bootstrap (inline in <head>): cookie → localStorage → system
const t = document.cookie.match(/(?:^|; )jflamb-theme=(dark|light)/)?.[1]
?? localStorage.getItem("jflamb-theme");
if (t) document.documentElement.dataset.theme = t;Use data-theme="light" or data-theme="dark" for a manual override. Without an override, Ledger follows prefers-color-scheme. The stylesheet also includes prefers-contrast: more and print values.
CI
npm test runs the contrast gate: it parses ledger.css itself and verifies every text-role/surface pair at ≥ 4.5:1 and every interactive-border/focus pair at ≥ 3:1, across light, dark, and high-contrast, and confirms the two dark blocks never diverge. A palette change that regresses accessibility fails the build.
Run the local checks before committing:
npm test
npm run check:packagenpm run sync:site -- /path/to/jflamb.com vendors the canonical stylesheet into a zero-tooling site. npm run check:drift -- /path/to/jflamb.com verifies that copy byte-for-byte.
Versioning
Semver. Renaming or removing a primitive or semantic token is major; adding or re-pointing a semantic alias is minor; value tweaks that pass the gate are patch.
Publishing
- Update
versioninpackage.jsonand add a dated entry toCHANGELOG.md. - Merge the change to
main. - Create a GitHub release whose tag exactly matches
v<package version>. - The
publishworkflow validates the tag, reruns the accessibility and package checks, and publishes the public package to npm with provenance.
The repository needs an npm automation token stored as the NPM_TOKEN Actions secret. Publishing is intentionally tied to a GitHub release; ordinary pushes and pull requests cannot publish packages.
