Skip to main content

Named UI role recipes (panels, chrome, insets) for FastHTML applications — a stable abstraction layer over DaisyUI and Tailwind primitives.

Project description

cjm-fasthtml-design-system

Install

pip install cjm_fasthtml_design_system

Role in the Multi-Workflow Pipeline

This library sits between UI-bearing consumer libraries and the underlying styling primitives:

Consumers (page-centric libraries, host apps, demo apps)
    ↓ depend on
Layout primitives (cjm-fasthtml-app-core: page chrome, column+queue, toolbar, FT-returning helpers)
    ↓ depend on
Design-system recipes (THIS LIBRARY: buttons, step_chrome, empty_states, panels, chrome, insets, icons, text_tiers)
    ↓ depend on
Styling primitives (cjm-fasthtml-daisyui, cjm-fasthtml-tailwind: tokens)

Consumers import named roles (buttons.primary_action, panels.dashboard_tile, step_header_band.title, text_tiers.secondary) instead of reaching for styling tokens directly. This makes coordinated styling changes a single-file edit in this library rather than N-file edits across every consumer, and keeps the role API stable across a potential future FastHTML-to-native port.

Some catalogs are flat registries of independently-usable variants (buttons, chrome, panels, insets, text_tiers, icons). Others are anatomies whose slots compose together to form one surface (empty_states, step_chrome). Anatomies pair with FT-returning rendering helpers in cjm-fasthtml-app-core per the convention-and-implementation split (V12 pattern).

Design System Document

The multi-workflow design system is split between this library’s notebooks (codified conventions as running code) and a pointer-first Markdown document (cross-cutting content that cannot be codified):

  • Codified conventions — the library is authoritative. Each codified convention lives as a notebook in nbs/ with CI-asserted test guards. Additional codifications follow the same pattern as evidence accrues; the multi-workflow design-system doc’s Open Gaps section tracks candidates.
  • Non-codifiable content — the doc is authoritative. Principles (P1–P12), the Refinement Procedure, codification disciplines (CD1–CD3), library architecture rules, open gaps, open questions, priority tasks by workflow phase, and cross-library interaction / layout / component directories live in claude-docs/multi-workflow-design-system.md. The doc’s Conventions Directory references this library’s notebooks by convention ID.

Each codified convention maps to a notebook in nbs/:

Convention Notebook Module What it codifies
V1 Button roles nbs/buttons.ipynb cjm_fasthtml_design_system.buttons 11 surface-scoped button role recipes (primary trio sm/md/lg, dismissal pair sm/md, plus secondary, soft utility, item-remove, modal-disclosure, destructive-cancellable, destructive-confirm)
V2 Step header band anatomy nbs/step_chrome.ipynb cjm_fasthtml_design_system.step_chrome 4-slot anatomy (layout, title, subtitle, trailing) for step-level header bands. First responsive role catalog — codifies LG5 compression at the M2/M3 boundary (lg: breakpoint)
V8 Empty-state anatomy nbs/empty_states.ipynb cjm_fasthtml_design_system.empty_states 4-slot anatomy (wrapper, icon, title, detail) for zero-data placeholder UI. Composes V11 + V13
V10 Panel variants nbs/panels.ipynb cjm_fasthtml_design_system.panels P1–P5 full-panel recipes (dashboard_tile, content_panel, structural_container, minimal_container, content_card)
V10 Chrome variants nbs/chrome.ipynb cjm_fasthtml_design_system.chrome C1–C2 column header/footer recipes (page-level-sibling chrome bands)
V10 Inset variants nbs/insets.ipynb cjm_fasthtml_design_system.insets I1 opacity-modulated inset recipes (in-panel sub-regions)
V11 Icon size roles nbs/icons.ipynb cjm_fasthtml_design_system.icons 9 placement-context icon size roles (text-button, icon-button, ghost-button “full” container-fill, section-header, empty-state, page-title, status-inline, compact-button, dense-inline)
V13 Text emphasis tiers nbs/text_tiers.ipynb cjm_fasthtml_design_system.text_tiers 4 emphasis tiers (secondary 70 / tertiary 60 / muted 50 / subtle 40) — opacity-modulated text_dui.base_content recipes

The 2026-04-20 content-heavy inventory is preserved as a historical snapshot at claude-docs/multi-workflow-design-system-2026-04-23_11-53-14.md; the pointer-first successor at claude-docs/multi-workflow-design-system.md replaced it on 2026-04-23 as part of this library’s Phase 3 restructure. See claude-docs/cjm-fasthtml-design-system-bootstrap-plan.md Appendix C for the restructure rationale. Running ledger of post-bootstrap codifications: claude-docs/codification-history.md. Layout-system framework (P6 operationalization): claude-docs/layout-system.md.

Usage

Every recipe module exports a module-level instance of a frozen dataclass. Consumers import the instance and use attribute access:

from fasthtml.common import Div, H2, P, Button

from cjm_fasthtml_design_system.buttons import buttons
from cjm_fasthtml_design_system.panels import panels
from cjm_fasthtml_design_system.chrome import chrome
from cjm_fasthtml_design_system.insets import insets
from cjm_fasthtml_design_system.step_chrome import step_header_band
from cjm_fasthtml_design_system.text_tiers import text_tiers

from cjm_fasthtml_tailwind.core.base import combine_classes
from cjm_fasthtml_tailwind.utilities.sizing import w
from cjm_fasthtml_tailwind.utilities.spacing import m

Flat registry example (V10 panels + V10 chrome). Each role is a single class string applied independently:

Div(..., cls=panels.structural_container)
Div(..., cls=combine_classes(w.full, m.t(4), panels.content_panel))

# Chrome sits inside a panel
Div(
    Div('Header', cls=chrome.column_header),
    Div('Body'),
    Div('Status', cls=chrome.column_footer),
    cls=panels.structural_container,
)

Button role example (V1):

Button("Continue", cls=buttons.step_primary)   # md+primary, step-completion CTA
Button("Cancel",   cls=buttons.step_dismissal) # md+ghost, step-scope terminal exit
Button("Delete",   cls=buttons.destructive_confirm)

Anatomy example (V2 step header band). Slots compose together to form one surface; consumer-opt-in trailing slot wraps multi-trigger groups:

Div(
    Div(
        H2("Review & Commit", cls=step_header_band.title),
        P("Verify segments and commit.", cls=step_header_band.subtitle),
    ),
    Div(
        settings_trigger,
        hints_trigger,
        cls=step_header_band.trailing,
    ),
    cls=step_header_band.layout,
)

Text-tier example (V13). Roles compose orthogonally with font_size, text_align, etc.:

P("Setting label", cls=text_tiers.secondary)
P("Auxiliary detail", cls=combine_classes(text_tiers.tertiary, m.t(1)))

Why frozen dataclass: renaming a field is a breaking change announced in the type, which enforces namespace-as-public-contract discipline. Consumers can’t accidentally mutate roles at runtime. A native-platform port replaces the instantiation while keeping the class shape stable; consumer imports never move.

Why per-category modules: catalogs evolve at different cadences (V10 stabilized 2026-04-22, V11 2026-04-24, V1 2026-05-04, V13 2026-05-05, V8 2026-05-15, V2 2026-05-16). Keeping them separate means a change to one category doesn’t force re-export of the others. The convention/implementation split (V12 pattern) further decouples anatomy recipes here from FT-returning rendering helpers in cjm-fasthtml-app-core.

Extending the Library

When a new convention accrues enough evidence to codify, add a new notebook under nbs/ following one of the two established shapes:

Flat registry shape (V1 buttons, V10 panels/chrome/insets, V11 icons, V13 text_tiers). Use when each role is independently usable — a single class string consumers apply on its own. The dataclass enumerates the variants:

  1. Create nbs/<category>.ipynb with #| default_exp <category>.
  2. Define a frozen XRoles (or XVariants) dataclass enumerating the role names.
  3. Instantiate at module scope as a singleton (e.g., category_roles = XRoles(...)).
  4. Add attribute-level tests asserting each role contains its expected primitives + an anti-coincidence-collapse note (CD1) for roles that share styling by coincidence.

Anatomy shape (V8 empty_states, V2 step_chrome). Use when slots compose together to form one surface. Pair with an FT-returning rendering helper in cjm-fasthtml-app-core per the convention-and-implementation split (V12 pattern):

  1. Create nbs/<category>.ipynb with #| default_exp <category>.
  2. Define a frozen XAnatomy dataclass with one field per slot.
  3. Instantiate at module scope as a singleton describing the canonical slot recipes.
  4. Add per-slot positive assertions + cross-catalog reference integrity (e.g., V13 base-tier guard) + hierarchy sentinels where slot ordering encodes intent.
  5. Author the matching FT helper in cjm-fasthtml-app-core/nbs/components/<category>.ipynb.

Both shapes apply the same per-step discipline:

  • The recipe layer’s public contract is the set of dataclass class names and field names. Internal composition (which primitives each recipe combines) can evolve without breaking consumers as long as the field names stay stable.
  • Notebook preambles declare the convention ID and state the rationale directly — the design-system doc references the library, not vice versa.
  • After codification, update the convention-to-notebook table in this index’s “Design System Document” section above (manually maintained — one row per codified convention). Also add a matching pointer row to the multi-workflow design-system doc’s Conventions Directory. The Module Overview / Module Dependencies sections lower in this index are auto-generated and refresh on each publish.

Currently-open codification candidates live in claude-docs/multi-workflow-design-system.md Open Gaps (G11 page chrome shared primitive, G12 column+queue layout primitive, G13 toolbar primitive, G14 preview panel primitive, G21–G25 V1 catalog gaps) and claude-docs/layout-system.md Open Gaps (LG1 mode/shape registry codification, LG2 per-card-type density preference, LG6 tabs-with-sync collapse pattern, LG7 custom Tailwind breakpoint codification). Each will earn codification as the relevant consumer evidence accumulates.

For codification disciplines (CD1 anti-coincidence-collapse, CD2 anti-premature-codification, CD3 two-evidence) and the Refinement Procedure that operationalizes a codification session, see claude-docs/multi-workflow-design-system.md.

Project Structure

nbs/
├── buttons.ipynb      # Named button-role recipes for content-action affordances. Each role maps a semantic intent (primary call-to-action at a given surface scope, alternative path, soft dismissal, soft utility, item removal, destructive-but-cancellable, destructive irreversible) to a pre-composed CSS class string consumers apply via `Button(..., cls=buttons.X)`.
├── chrome.ipynb       # Named chrome-role recipes for header and footer bands that accompany a content panel. Chrome is a `base_200` fill + rounded-corners band with intrinsic padding — no border of its own. When placed as a page-level sibling of a panel, the panel's border handles the between-surfaces separator; chrome's fill + radius read it as a self-contained sibling surface against the page's `base_100`.
├── empty_states.ipynb # Named anatomy-slot recipes for empty-state surfaces (zero-data placeholder UI in list-like primitives). Each field maps a structural slot (wrapper, icon, title, detail) to a pre-composed CSS class string consumers apply to the corresponding element. The catalog encodes the canonical empty-state shape — vertically centered, icon-above-text, soft emphasis — observed across ~6 production consumers (`cjm-fasthtml-card-stack`, `cjm-fasthtml-file-browser`, `cjm-fasthtml-virtual-collection`-driven libraries) and composes V11 icon-size roles + V13 text-tier roles into a single named convention.
├── icons.ipynb        # Named icon-size-role recipes for the `lucide_icon(name, size=...)` factory. Each role maps a structural placement context (text-labeled button, ghost-styled standalone trigger, section-header decoration, empty-state illustration, etc.) to a size value the consumer passes through to `lucide_icon`. Two sizing strategies coexist in the catalog: fixed numeric (icon owns its absolute size) and container-fill (`"full"`, parent button's intrinsic padding owns the size).
├── insets.ipynb       # Named inset-role recipes for opacity-modulated low-emphasis regions *inside* a panel. Insets never stand alone — they're sub-regions that need visual grouping without adding a second panel border.
├── panels.ipynb       # Named panel-role recipes for full content containers with `border_radius.box`. Each role composes a specific set of DaisyUI and Tailwind primitives and exposes a stable attribute-access API for consumers.
├── step_chrome.ipynb  # Named anatomy-slot recipes for the step-level header band — the title + subtitle + trailing-trigger surface that introduces each workflow step inside StepFlow's per-step render. Each field maps a structural slot (layout, title, subtitle, trailing) to a pre-composed CSS class string consumers apply to the corresponding element. The catalog encodes the canonical step-header shape — title block on the left, optional trailing trigger group on the right — observed across four production consumers (`cjm-transcript-review`, `cjm-transcript-segment-align`, `cjm-transcript-source-select`, `cjm-transcription-source-select`) and codifies LG5 (workspace-shape-aware step chrome) responsive compression at the M2↔M3 mode boundary.
└── text_tiers.ipynb   # Named text-emphasis-tier recipes for opacity-modulated `text_dui.base_content` patterns. Each role maps an emphasis level (secondary, tertiary, muted, subtle) to a pre-composed CSS class string consumers apply via `Span(..., cls=text_tiers.X)` or compose into larger class lists. The catalog encodes the emphasis hierarchy observed across ~160 production sites; the roles compose orthogonally with `font_size`, `text_align`, `font_style.italic`, etc., which stay outside the catalog.

Total: 8 notebooks

Module Dependencies

graph LR
    buttons[buttons<br/>Button Roles]
    chrome[chrome<br/>Chrome Variants]
    empty_states[empty_states<br/>Empty State Anatomy]
    icons[icons<br/>Icon Size Roles]
    insets[insets<br/>Inset Variants]
    panels[panels<br/>Panel Variants]
    step_chrome[step_chrome<br/>Step Header Band Anatomy]
    text_tiers[text_tiers<br/>Text Tier Roles]

    empty_states --> text_tiers
    step_chrome --> text_tiers

2 cross-module dependencies detected

CLI Reference

No CLI commands found in this project.

Module Overview

Detailed documentation for each module in the project:

Button Roles (buttons.ipynb)

Named button-role recipes for content-action affordances. Each role maps a semantic intent (primary call-to-action at a given surface scope, alternative path, soft dismissal, soft utility, item removal, destructive-but-cancellable, destructive irreversible) to a pre-composed CSS class string consumers apply via Button(..., cls=buttons.X).

Import

from cjm_fasthtml_design_system.buttons import (
    buttons,
    ButtonRoles
)

Classes

class ButtonRoles:
    "Named button-role recipes (V1). Each field is a pre-composed CSS class string."

Chrome Variants (chrome.ipynb)

Named chrome-role recipes for header and footer bands that accompany a content panel. Chrome is a base_200 fill + rounded-corners band with intrinsic padding — no border of its own. When placed as a page-level sibling of a panel, the panel’s border handles the between-surfaces separator; chrome’s fill + radius read it as a self-contained sibling surface against the page’s base_100.

Import

from cjm_fasthtml_design_system.chrome import (
    chrome,
    ChromeVariants
)

Classes

class ChromeVariants:
    "Named chrome-role recipes (V10). Header/footer bands with base_200 fill and rounded corners (no own border)."

Empty State Anatomy (empty_states.ipynb)

Named anatomy-slot recipes for empty-state surfaces (zero-data placeholder UI in list-like primitives). Each field maps a structural slot (wrapper, icon, title, detail) to a pre-composed CSS class string consumers apply to the corresponding element. The catalog encodes the canonical empty-state shape — vertically centered, icon-above-text, soft emphasis — observed across ~6 production consumers (cjm-fasthtml-card-stack, cjm-fasthtml-file-browser, cjm-fasthtml-virtual-collection-driven libraries) and composes V11 icon-size roles + V13 text-tier roles into a single named convention.

Import

from cjm_fasthtml_design_system.empty_states import (
    empty_states,
    EmptyStateAnatomy
)

Classes

class EmptyStateAnatomy:
    "Named empty-state anatomy-slot recipes (V8). Each field is a pre-composed CSS class string applied to the corresponding slot element (wrapper Div, icon, title text, detail text)."

Icon Size Roles (icons.ipynb)

Named icon-size-role recipes for the lucide_icon(name, size=...) factory. Each role maps a structural placement context (text-labeled button, ghost-styled standalone trigger, section-header decoration, empty-state illustration, etc.) to a size value the consumer passes through to lucide_icon. Two sizing strategies coexist in the catalog: fixed numeric (icon owns its absolute size) and container-fill ("full", parent button’s intrinsic padding owns the size).

Import

from cjm_fasthtml_design_system.icons import (
    IconSize,
    icons,
    IconRoles
)

Classes

class IconRoles:
    "Named icon-size-role recipes (V11). Each field maps a structural placement to a size value passed to `lucide_icon(name, size=...)`."

Inset Variants (insets.ipynb)

Named inset-role recipes for opacity-modulated low-emphasis regions inside a panel. Insets never stand alone — they’re sub-regions that need visual grouping without adding a second panel border.

Import

from cjm_fasthtml_design_system.insets import (
    insets,
    InsetVariants
)

Classes

class InsetVariants:
    "Named inset-role recipes (V10). Opacity-modulated low-emphasis regions inside a panel."

Panel Variants (panels.ipynb)

Named panel-role recipes for full content containers with border_radius.box. Each role composes a specific set of DaisyUI and Tailwind primitives and exposes a stable attribute-access API for consumers.

Import

from cjm_fasthtml_design_system.panels import (
    panels,
    PanelVariants
)

Classes

class PanelVariants:
    "Named panel-role recipes (V10). Each field is a pre-composed CSS class string."

Step Header Band Anatomy (step_chrome.ipynb)

Named anatomy-slot recipes for the step-level header band — the title + subtitle + trailing-trigger surface that introduces each workflow step inside StepFlow’s per-step render. Each field maps a structural slot (layout, title, subtitle, trailing) to a pre-composed CSS class string consumers apply to the corresponding element. The catalog encodes the canonical step-header shape — title block on the left, optional trailing trigger group on the right — observed across four production consumers (cjm-transcript-review, cjm-transcript-segment-align, cjm-transcript-source-select, cjm-transcription-source-select) and codifies LG5 (workspace-shape-aware step chrome) responsive compression at the M2↔M3 mode boundary.

Import

from cjm_fasthtml_design_system.step_chrome import (
    step_header_band,
    StepHeaderAnatomy
)

Classes

class StepHeaderAnatomy:
    "Named step-header-band anatomy-slot recipes (V2). Each field is a pre-composed CSS class string applied to the corresponding slot element (outer Div, H2 title, P subtitle, optional trailing-wrapper Div). Codifies LG5 responsive compression at the M2/M3 boundary."

Text Tier Roles (text_tiers.ipynb)

Named text-emphasis-tier recipes for opacity-modulated text_dui.base_content patterns. Each role maps an emphasis level (secondary, tertiary, muted, subtle) to a pre-composed CSS class string consumers apply via Span(..., cls=text_tiers.X) or compose into larger class lists. The catalog encodes the emphasis hierarchy observed across ~160 production sites; the roles compose orthogonally with font_size, text_align, font_style.italic, etc., which stay outside the catalog.

Import

from cjm_fasthtml_design_system.text_tiers import (
    text_tiers,
    TextTierRoles
)

Classes

class TextTierRoles:
    "Named text-emphasis-tier recipes (V13). Each field is a pre-composed CSS class string applying opacity modulation to `text_dui.base_content`."

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cjm_fasthtml_design_system-0.0.13.tar.gz (22.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cjm_fasthtml_design_system-0.0.13-py3-none-any.whl (22.1 kB view details)

Uploaded Python 3

File details

Details for the file cjm_fasthtml_design_system-0.0.13.tar.gz.

File metadata

File hashes

Hashes for cjm_fasthtml_design_system-0.0.13.tar.gz
Algorithm Hash digest
SHA256 24a0037ebf5c961a140caee5e958892b3514a18b1ff0e842525efb04edd58fb1
MD5 828dd774198c163a2d2946c3f8a904cf
BLAKE2b-256 711782ef1631c7ab4cde06d4f26a989c42d7fb9aeef5522fce1b1188924da422

See more details on using hashes here.

File details

Details for the file cjm_fasthtml_design_system-0.0.13-py3-none-any.whl.

File metadata

File hashes

Hashes for cjm_fasthtml_design_system-0.0.13-py3-none-any.whl
Algorithm Hash digest
SHA256 6bae817ec7a0d2c8b89fad85c371e1cd454a17b8bf57101d6b6d7656b26d0c67
MD5 49e262cf08c74729e86e63100c4c4613
BLAKE2b-256 a190564f5ed9225f0fb3039a9da9f3e9a7018e757efefd540e5268821726dbaa

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page