@provinggroundslabs/temple-design-system
v1.5.0
Published
Token-driven React components and CSS for the Ghost theme design system
Readme
Design system (Ghost theme)
This folder holds the source CSS for the Ghost theme (screen.css → ghost-theme/assets/css/screen.css) and a small React component layer used in Storybook and embeddable web projects.
Principles (Ghost parity for overlapping patterns): see ../docs/design-system-principles.md.
Agent implementation contract: use the canonical AI agent design-system implementation contract for cross-project rules covering public imports, component selection, tokens, accessibility, themes, RTL, SSR/RSC, validation, and Linear escalation.
Node version
From the repository root, always load nvm and run nvm use so your shell matches .nvmrc (required before any npm commands). In scripts or CI shells that do not load your profile, source nvm first:
export NVM_DIR="${NVM_DIR:-$HOME/.nvm}" && [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" && nvm use
Commands (repo root)
Requires Node.js per .nvmrc and package.json engines (>=22.12 — Storybook, Vite, and PostCSS).
| Script | Purpose |
| --- | --- |
| npm run storybook | Interactive component preview |
| npm run build-storybook | Static Storybook output (storybook-static/) |
| npm run test:storybook | Run all stories and accessibility checks in headless Chromium |
| npm run typecheck | tsc --noEmit for components + Storybook |
| npm run build | Compile canonical minified CSS into the Ghost theme |
| npm run build:dev | Compile readable CSS for local inspection |
| npm run watch | Rebuild readable CSS while source files change |
| npm run lint:generated-css | Fail when source CSS and the checked-in Ghost artifact differ |
| npm run example-site:dev | Run canonical example website |
| npm run example-site:typecheck | Typecheck canonical website |
| npm run lint:design-system-parity | Enforce Storybook + example-site parity checks |
| npm run lint:a11y-baseline | Verify Storybook a11y enforcement and baseline coverage |
| npm run lint:ssr-rsc | Verify SSR/RSC labels and client-only boundaries |
| npm run example-site:check-components | Run parity checks directly in example-site workspace |
| npm run example-site:build | Build canonical example website |
Published Storybook
Published releases build and push the static Storybook container image to GHCR as ghcr.io/provinggroundslabs/temple-design-system/storybook:latest and the release tag. The root CI workflow runs on pull requests and every push to main; its npm test step includes npm run build-storybook, so Storybook build failures surface in CI.
Canonical website reference
design-system/example-site is the baseline, full-page implementation that demonstrates how to compose a site entirely from library components.
Component status
Storybook publishes a lifecycle status table at Introduction / Component status. It defines stable, experimental, and deprecated statuses, lists the public exports covered by each component page, and documents the rules for promoting or deprecating components. Component stories also declare parameters.componentStatus, which Storybook displays as a status badge on each component page.
Release policy
SemVer impact, changelog format, and Release Drafter labels are documented in ../docs/release-policy.md and summarized in Storybook at Introduction / Release policy.
Accessibility baseline
Storybook publishes the WCAG 2.1 AA component baseline at Introduction / Accessibility baseline. Run npm run test:storybook to render every testable story in headless Chromium and fail on addon-a11y violations; run npm run lint:a11y-baseline to verify enforcement metadata and baseline coverage. Both commands are part of npm test and must pass when adding component stories or documenting exceptions.
The component-level scan excludes axe's heading-order rule because reusable components cannot know the surrounding page hierarchy. Consumers and full-page references remain responsible for a logical heading outline; components that render headings should expose a level option when their position can vary.
SSR and RSC compatibility
Storybook publishes Next.js app-router rendering compatibility at Introduction / SSR and RSC and in the component status table. Components labeled ssr-safe are exported from @provinggroundslabs/temple-design-system/server for server-rendered routes when used as static markup. Components labeled client-only use state, effects, context, browser listeners, timers, or imperative focus behavior and must be rendered behind a "use client" boundary.
RTL and i18n
Storybook publishes the RTL and i18n smoke-test baseline at Introduction / RTL and i18n. Use the Direction toolbar control to set html[dir="rtl"] across component stories, and keep the component status table's RTL readiness column aligned with known follow-up work.
Use logical placements (top-start, top-end, bottom-start, bottom-end) for direction-aware toast positioning. Physical toast placements remain available when an exact viewport edge matters. Directional icons can opt into visual mirroring with mirroredInRtl; otherwise ArrowLeft and ArrowRight keep their physical direction.
Bundle size
Bundle-size and tree-shaking budgets are documented in ../docs/bundle-size.md. Keep npm run lint:bundle-size passing when adding component exports, changing package sideEffects, or introducing heavier dependencies.
Theme matrix
Storybook publishes dark-mode and accent-preset coverage at Introduction / Theme matrix coverage. Use Introduction / Theme matrix surfaces to render the informational, game, and marketing reference surfaces with every accent preset and appearance mode.
Rich content rendering
Use Prose for caller-owned React children and RichContent when an app needs a standard rich-content rendering boundary.
RichContent supports two explicit modes:
source="sanitized-html"acceptssanitizedHtmland requiressanitizedBy. The caller remains responsible for sanitizing arbitrary HTML before passing it to the design system; the component owns the finaldangerouslySetInnerHTMLedge so consuming apps do not duplicate it.source="limited-markdown"parses paragraphs, line breaks, and markdown links without raw HTML. Externalhttpandhttpslinks receivetarget="_blank"andrel="noopener noreferrer"by default, while relative, hash,mailto, andtellinks remain in-app.
Use sanitized HTML for article bodies that already pass through an application sanitizer. Use limited markdown for AI-generated summaries, digests, and short generated notes where only links and paragraph breaks are needed.
Recommended React setup
Import exactly one public stylesheet and wrap app content with ThemeProvider so the design-system document hooks are initialized for you.
- Use
app.cssfor lean application surfaces built fromThemeProvider, typography primitives,Alert, andEmptyState. - Use
screen.cssfor the complete component catalog, marketing/layout components, rich post content, Koenig cards, or Ghost theme parity. - Do not import both. Move from
app.csstoscreen.csswhen the application adopts a component outside the documented core set.
Lean application setup:
import "@provinggroundslabs/temple-design-system/app.css";
import {
Alert,
EmptyState,
ThemeProvider,
} from "@provinggroundslabs/temple-design-system";
export function AppShell() {
return (
<ThemeProvider accentPreset="emerald" colorScheme="system">
<Alert title="Connected">Application tokens are active.</Alert>
<EmptyState title="No records yet" />
</ThemeProvider>
);
}Complete catalog setup:
import "@provinggroundslabs/temple-design-system/screen.css";
import { ThemeProvider } from "@provinggroundslabs/temple-design-system";
export function AppShell() {
return (
<ThemeProvider accentPreset="emerald" colorScheme="system">
{/* app UI */}
</ThemeProvider>
);
}ThemeProvider applies the library bootstrap hooks that the CSS expects:
body.ds-body- a
.ds-rootwrapper around your React app html[data-color-scheme]html.accent-*
If an app already sets those hooks manually, remove the duplicate html / body bootstrap once it adopts ThemeProvider.
Logo assets
The package ships SVG and generated browser/PWA icon assets under @provinggroundslabs/temple-design-system/assets/*.
Use createLogoIconLinks() and createWebManifestIcons() from the root package to generate consistent metadata for whichever public asset path your app uses after copying the assets.
Contributor rules for this app:
- Import visible UI from
@provinggroundslabs/temple-design-system. - Do not add ad-hoc app-local class styling for page composition.
- Do not render raw semantic UI primitives directly (
h1,p,img,button, form controls, table tags); use the design-system components. - Run
npm run example-site:check-componentsbefore merging canonical-site updates.
Adding a component
- Add or reuse semantic tokens in
styles/03-semantics.csswhen introducing new global primitives. - Add styles to
styles/10-react-components.css(or extend existing06-components.csspatterns) usingvar(--ds-*)— avoid hard-coded palette values. - Implement the React API under
components/with accessibility defaults (aria-*, labels, keyboard). - Add a Storybook story under
stories/covering default, error/disabled, and keyboard behavior where relevant. - Add the component to
stories/componentStatus.tsand the story'sparameters.componentStatusmetadata with a stable, experimental, or deprecated status. - Represent the component in
example-site/srcby importing and composing at least one export from that module. - Run
npm run lint:design-system-paritybefore opening/merging a PR.
Autocomplete
components/Autocomplete.tsx is a headless, MUI-inspired combobox (single value). It does not bundle Material UI; behavior follows ARIA combobox + listbox patterns and theme tokens for visuals.
