Skip to content

Ponchia/bronto-ui

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

166 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@ponchia/ui

npm npm provenance runtime deps default CSS CI OpenSSF Scorecard license: MIT

A CSS-first identity layer for services, tools, and reports that need provenance. It works in plain HTML, modern frameworks, and print/PDF, with no component runtime to adopt and zero runtime dependencies.

The sharpest lane is report and tooling UI: static/PDF reports, evidence, provenance, system state, dense workbenches, and explanatory figures. The default CSS bundle stays the shared service identity, not the whole package: app shells, navigation, forms, tables, feedback, overlays, prose, motion, and the token system that lets apps feel related without sharing a component runtime.

The look is deliberately restrained: a mostly neutral canvas, one core accent for emphasis, dot-matrix display type, and hairline borders. Status colors, display-expression tokens, and data-viz colors are separate governed tiers, not extra brand accents. Opt-in skins re-point the root accent; Mermaid, D2, and Vega bridges use resolved renderer theme data instead of live CSS variables.

Start here

The demo is the kitchen sink — every component, light/dark, RTL, live theming. The service shell shows the shared app identity; the static report shows the same system under a no-build, no-JS, Chromium-PDF-ready constraint.

A research report built with the @ponchia/ui report layer The same report grammar printed to PDF


What it is

@ponchia/ui ships its design as CSS, not components. You drop in one stylesheet and style with semantic ui-* classes; an optional thin layer of typed class-name recipes and SSR-safe vanilla behaviors sits on top for the few things that genuinely need JS (theme persistence, dialogs, toasts, disclosure).

The guiding principle is that colour is rationed and structure carries meaning — layout, type weight, and the hairline do the work before a hue does, and the accent is a spotlight, not a paint bucket. Because framework rules live in @layer bronto, ordinary un-layered consumer CSS overrides them without a specificity fight. Print and reduced-motion rules still use !important deliberately where the framework must neutralize animation or layout at a media boundary.

It ships a complete, accessible standard component set because that is the identity layer every service consumes. Its sharper edge is the opt-in tooling, analytical, and communication layer sketched above. The line that holds it together: each primitive owns only its visual grammar and pure geometry — no chart engine, no domain state, no hit-testing. See docs/frontier-primitives.md for the thesis.

Install

npm i @ponchia/ui

Or drop it in with no build step, straight from a CDN:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ponchia/ui@0.6.11/dist/bronto.css">

Quick start

1. Load the CSS. One flattened, minified default CSS bundle — the standard component set, one request (~89 kB raw / ~15 kB gzip) — that is dist/bronto.css, not the whole package tarball:

@import '@ponchia/ui';            /* via a bundler */
<!-- or a plain <link>, no bundler -->
<link rel="stylesheet" href="/node_modules/@ponchia/ui/dist/bronto.css">

Prefer source leaves through a bundler? Use @import '@ponchia/ui/css' (a thin @import fan-out) instead. Both resolve the Doto @font-face with relative URLs, so there's no /fonts path assumption.

The size above is only dist/bronto.css. The opt-in analytical and report layers — report.css, dataviz.css, figure.css, annotations.css, legend.css, interval.css, clamp.css, highlights.css, and the rest — are not in the default CSS bundle; link each one you need from dist/css/. For LLM-authored static reports see docs/reporting.md.

2. Write markup with ui-* classes (primary is the default button; modifiers are opt-in):

<button class="ui-button">Save</button>
<button class="ui-button ui-button--ghost">Cancel</button>
<div class="ui-card">
  <span class="ui-eyebrow">Status</span>
  <span class="ui-badge ui-badge--success">Online</span>
</div>

3. (Optional) typed recipes — build class strings in JS/TS:

import { ui, cx } from '@ponchia/ui/classes';

ui.button({ variant: 'ghost' });   // → "ui-button ui-button--ghost"
ui.meter({ tone: 'warning' });      // → "ui-meter ui-meter--warning"

4. (Optional) behaviors — SSR-safe vanilla JS, each returns a cleanup function:

import { initThemeToggle, initDialog, toast } from '@ponchia/ui/behaviors';

initThemeToggle();   // wires [data-bronto-theme-toggle] + localStorage
initDialog();        // native <dialog> glue: [data-bronto-open] / [data-bronto-close]
toast('Saved', { tone: 'success' });   // body-anchored stack, no markup needed

Behaviors cover theme persistence, disclosure, dropdown menus, native-<dialog> modals/drawers, tabs, combobox, form validation, table sort, carousel, source backrefs and toasts — wired by data-bronto-* attributes.

5. (Optional) display glyphs — a 71-glyph dot-matrix icon set:

import { renderGlyph } from '@ponchia/ui/glyphs';

el.innerHTML = renderGlyph('search', { label: 'Search' });  // role="img"
// or drop a placeholder and expand it: <span data-bronto-glyph="check"></span>
// import { initDotGlyph } from '@ponchia/ui/behaviors'; initDotGlyph();

Arrows, chevrons, check/close/plus/minus, search/menu/gear, info/warning/bell/lock, home/user/heart/star/spark and circle-family marks are rendered on the same .ui-dotmatrix primitive and re-skinned by the --field-dot* tokens. Default dot look is for display sizes; pass { solid: true } to fuse the cells into a crisp pixel glyph that works as an inline icon down to ~16px. For dense lists/tables, renderGlyph(name, { render: 'mask' }) emits one .ui-icon element backed by an internal CSS mask.

What's in the box

  • Primitives — buttons, cards, chips, badges, links, key/value, ui-num, avatars.
  • Forms — inputs, select, textarea, search, switch, checkbox, ui-input-icon, ui-input-group.
  • Feedback — alert/callout, toast, tooltip, ui-progress (task) and ui-meter (measured value).
  • Overlay — modal + drawer on native <dialog>, dropdown menu, ui-carousel + ui-lightbox (gallery, user-driven — not an auto-slider).
  • Disclosure & nav — tabs, accordion, segmented, breadcrumb, pagination, ui-steps, ui-timeline, ui-pagehead, ui-kbd.
  • Shells — a service/app shell (ui-app-*) and a content/marketing site shell (ui-site*, ui-container).
  • Prose.ui-prose styles raw, unclassed semantic HTML (Markdown / CMS / LLM output) with zero classes.
  • Analytical & communication primitives (opt-in)@ponchia/ui/css/analytical.css: figure stages, SVG annotations (subject/connector/note), standalone legends/data-keys, text/evidence marks, leader-line connectors (+ a pure @ponchia/ui/connectors geometry kernel), a guided-focus spotlight, a crosshair/readout, a cross-cutting selection vocabulary, and CSS Custom Highlight API highlights. Each owns its visual grammar + pure geometry and refuses scales/state/hit-testing — figures that explain themselves, not a chart engine. The richer annotation engine lives in @ponchia/annotations; this package keeps only the dependency-free Bronto helper surface. Plus standalone source/provenance (trust), interval, clamp, and lifecycle state leaves.
  • Reports (opt-in)@ponchia/ui/css/report-kit.css for a complete static/PDF report vocabulary, or @ponchia/ui/css/report.css plus only the leaves a narrow report uses. Covers, decisions, claims, sections, severity-labelled findings, evidence packets, evidence ledgers, action registers, source-card bindings, ui-figure composition, intervals, bounded excerpts, chart wrappers and print utilities.
  • Motion & dots — the dot-matrix motif kit: dot grid, status dots, dot loaders, the orbital spinner, matrix reveal — all reduced-motion aware.
  • Glyphs@ponchia/ui/glyphs, a 71-glyph dot-matrix icon set on the .ui-dotmatrix primitive (display marks + crisp solid inline icons + one-node .ui-icon mask rendering).
  • Colorways (opt-in)data-bronto-skin="amber-crt | phosphor-green | e-ink": a root-level recolour of the one accent (OKLCH, per-theme, contrast-gated), never in the default bundle.
  • Data-viz (opt-in) — a colourblind-safe chart palette (--chart-* + dot-matrix pattern fills, resolved hex in charts.json), gated under simulated protan/deutan/tritan vision. Charts only, never UI chrome.

Full generated catalog of every class: docs/reference.md. The decision guide (which primitive when): docs/usage.md.

Theming: one knob

Core DOM accent surfaces derive from a single --accent variable via color-mix(). Re-brand the entire app — both light and dark — with root-level, per-theme overrides:

:root   { --accent: #2f6df6; }   /* whole app blue   */

Scoped --accent overrides recolor direct accent uses in that subtree, but the derived family (--accent-text, --accent-soft, focus/dot/ramp tokens) is a root-level skin contract. Use the full per-theme recipe in docs/theming.md for production rebrands.

Buttons, focus rings, dot motifs, accent borders and soft fills follow the root accent automatically. Light/dark is data-theme="light" / "dark" on <html> (defaults to prefers-color-scheme); data-density and data-contrast give density and contrast presets. A full re-skin (radius, display face, dot density, surfaces) is a handful more token overrides, while status colours and data-viz colours remain their own governed tiers — the default monochrome look is one skin, not the architecture.

One system, many skins. That the knob is real isn't a claim — it ships: drop in @ponchia/ui/css/skins.css and set data-bronto-skin="amber-crt | phosphor-green | e-ink" on <html> for a complete, contrast-gated recolour (the derived accent family, focus ring, dot-matrix and glyphs all follow). Colour is governed in tiers — neutral canvas · one accent · locked status · display expression · opt-in data-viz — so it always earns its place; the full constitution is ADR-0001.

When you change --accent, contrast becomes yours: verify your hue in the theme playground (it shows the derived family and computed WCAG ratios). Mermaid, D2, and Vega helpers emit resolved theme data for those renderers; they do not live-reskin from a later CSS --accent override. Full contract: docs/theming.md.

Accessibility

Not an afterthought — a gate. Every contractual token pairing has a declared WCAG 2.1 conformance level the build fails below (docs/contrast.md, regenerated + CI-checked), and the shipped colorways are held to the same floors. The data-viz palette is gated for distinctness under simulated protanopia/deuteranopia/tritanopia, and never relies on colour alone (dot-matrix pattern fills). APCA Lc is published advisory alongside WCAG. Components ship ARIA-correct markup and SSR-safe keyboard behaviors; prefers-reduced-motion, prefers-contrast and forced-colors are all honored.

Works with anything

The CSS is the framework, so it works with React, Svelte/SvelteKit, Astro, Vue, Solid, Qwik or plain HTML — there's no component runtime to adopt. The optional classes and behaviors entrypoints pull in no UI framework and are SSR-safe. For React, Solid and Qwik there are also optional thin bindings@ponchia/ui/react, @ponchia/ui/solid and @ponchia/ui/qwik wrap the behaviors as hooks (useDialog, useToast, …); react/solid-js/@builder.io/qwik are optional peer deps. Svelte and Vue get dependency-free lifecycle adapters too: @ponchia/ui/svelte exports actions, and @ponchia/ui/vue exports directives/plugin helpers over the same behavior layer.

Per-framework getting-started guides + runnable example apps live in the repo:

Stack Guide Example
Vanilla / Vite / plain HTML vanilla.md examples/vanilla-vite
Astro astro.md examples/astro
SvelteKit sveltekit.md examples/sveltekit
Vue vue.md examples/vue-vite
React react-solid.md examples/react-vite
Solid react-solid.md examples/solid-vite
Qwik react-solid.md examples/qwik-vite
Tailwind v4 bridge / cascade-layer interop tailwind.md examples/tailwind-vite

Extras

  • Tokens as dataimport tokens, { themeColor, cssVars } from '@ponchia/ui/tokens' (plus tokens.json, W3C DTCG tokens.dtcg.json, tokens/resolved.json for concrete values in canvas/SVG/MapLibre, and tokens/figma.variables.json for local Figma Variables import/sync scripts).
  • Chart colours for dashboardsimport charts from '@ponchia/ui/charts.json' with { type: 'json' } in Node ESM, or the same path through a bundler JSON import (resolved hex per theme; series 1 = your accent) plus the opt-in @ponchia/ui/css/dataviz.css.
  • Static reports for LLMs — add @ponchia/ui/css/report-kit.css for the complete report vocabulary, or @ponchia/ui/css/report.css plus the specific leaves a smaller report needs. Sidecar claim/source contracts can validate against @ponchia/ui/schemas/report-claims.v1.schema.json. Full cookbook: docs/reporting.md.
  • Modern-platform motion — overlays (modal/drawer/popover), toasts and the <details> accordion animate in and out with zero JS (@starting-style + allow-discrete, ::details-content + interpolate-size). Progressive-enhancement extras: .ui-scroll-progress / .ui-scroll-reveal (scroll-driven, no JS) and .ui-vt for View Transitions. All degrade to a static end-state and respect prefers-reduced-motion. For smooth cross-document navigations, add the document-global one-liner to your own top-level (unlayered) CSS: @view-transition { navigation: auto; }.
  • Editor IntelliSense — point VS Code at the shipped custom-data file so every token autocompletes in var(--…):
    { "css.customData": ["node_modules/@ponchia/ui/classes/vscode.css-custom-data.json"] }
  • For AI coding agents — the package ships llms.txt at its root plus docs/reference.md, docs/usage.md, docs/reporting.md, docs/theming.md, docs/contrast.md, docs/stability.md, docs/package-contract.md, the color constitution docs/adr/0001-color-system.md and the CHANGELOG inside the tarball, so an offline agent has the full API and rationale without guessing.

The package root is CSS-only. Use @import '@ponchia/ui' in CSS, or import '@ponchia/ui' only as a CSS side-effect import in a CSS-aware bundler (Vite, Astro, SvelteKit, webpack). Do not import the package root from Node/runtime JS. CSS helper subpaths are explicit too, including /tailwind for the Tailwind v4 theme/variant bridge. JS entrypoints are explicit subpaths: /tokens, /classes, /behaviors, /glyphs, /annotations, /connectors, /react, /solid, /qwik, /svelte, /vue, /skins, /charts, /mermaid, /d2, and /vega. JS subpaths are ESM-only. CommonJS consumers should use dynamic import('@ponchia/ui/behaviors').

Browser support

Recent-evergreen, by design. The framework targets the modern web platform — cascade layers, :has(), color-mix()/oklch(), logical properties, native <dialog>, and the 2026 interaction primitives (@starting-style, transition-behavior: allow-discrete, light-dark()). Floor: Chrome/Edge 125+, Safari 18+, Firefox 129+ (early–mid 2025). No fallback ships below this — pin an older tag if you need it. See ADR-0002 for the scope/greenfield rationale.

Versioning

Pre-1.0 and deliberately so. Until 1.0.0, breaking changes ship in the minor (0.x.0); patches (0.x.y) are always non-breaking. Pin with the patch range — at 0.x, ~0.6.0 (and equivalently ^0.6.0) resolves to >=0.6.0 <0.7.0, giving you safe patches while holding back the next breaking minor. Every breaking change is called out under a BREAKING heading in the CHANGELOG with a migration note.

Contractual (changes are breaking): token names and documented token roles, .ui-* class and recipe names, data-bronto-* attributes, exported behavior/glyph/binding function names and each behavior's cleanup contract. Not contractual (may change any release): exact token values and generated colour math outputs (visual tuning) unless a doc explicitly says the value is stable, plus internal leaf-file / @layer boundaries. See docs/stability.md for the semantic public-surface matrix and docs/package-contract.md for the generated export/file/provenance inventory.

Release candidates publish to the next dist-tag, never to latest — opt in with npm i @ponchia/ui@next to try an upcoming version early. A plain npm i @ponchia/ui only ever resolves a stable release.

Links

License

MIT © Ponchia.

The bundled Doto font (fonts/*.woff2) is © 2024 The Doto Project Authors and licensed separately under the SIL Open Font License 1.1 — see fonts/OFL.txt.

About

CSS-first design system for interfaces that explain themselves — standard components + an opt-in analytical/report layer for LLM-authored HTML/PDF reports. Monochrome, one rationed accent, zero runtime deps.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors