Metadata-Version: 2.4
Name: cjm-fasthtml-design-system
Version: 0.0.9
Summary: Named UI role recipes (panels, chrome, insets) for FastHTML applications — a stable abstraction layer over DaisyUI and Tailwind primitives.
Author-email: "Christian J. Mills" <9126128+cj-mills@users.noreply.github.com>
License: Apache-2.0
Project-URL: Repository, https://github.com/cj-mills/cjm-fasthtml-design-system
Project-URL: Documentation, https://cj-mills.github.io/cjm-fasthtml-design-system/
Keywords: nbdev
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: python-fasthtml
Requires-Dist: cjm-fasthtml-app-core
Requires-Dist: cjm-fasthtml-tailwind
Requires-Dist: cjm-fasthtml-daisyui
Requires-Dist: cjm_fasthtml_lucide_icons
Dynamic: license-file

# cjm-fasthtml-design-system


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

## Install

``` bash
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)
        ↓ depend on
    Design-system recipes (THIS LIBRARY: panels, chrome, insets, ...)
        ↓ depend on
    Styling primitives (cjm-fasthtml-daisyui, cjm-fasthtml-tailwind: tokens)

Consumers import *named roles* (`panels.dashboard_tile`,
`chrome.column_header`) 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.

## 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.** V10 panel /
  chrome / inset variants are codified today as running code with
  CI-asserted test guards. Future conventions (V1 buttons, G6 icon
  sizes, G8 destructive-confirm, text-role tiers) will land here as
  additional notebooks.
- **Non-codifiable content — the doc is authoritative.** Principles
  (P1–P12), the Refinement Procedure, 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 |
|:---|:---|:---|:---|
| V10 Panel variants | `nbs/panels.ipynb` | `cjm_fasthtml_design_system.panels` | P1–P5 full-panel recipes |
| V10 Chrome variants | `nbs/chrome.ipynb` | `cjm_fasthtml_design_system.chrome` | C1–C2 column header/footer recipes |
| V10 Inset variants | `nbs/insets.ipynb` | `cjm_fasthtml_design_system.insets` | I1 opacity-modulated inset 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.

## Usage

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

``` python
from fasthtml.common import Div

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_tailwind.core.base import combine_classes
from cjm_fasthtml_tailwind.utilities.sizing import w
from cjm_fasthtml_tailwind.utilities.spacing import m

# Stand-alone use
Div(..., cls=panels.structural_container)

# Composable with site-specific modifiers
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,
)
```

**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:** panels, chrome, and insets will evolve at
different cadences. Keeping them separate means a change to one category
doesn’t force re-export of the others.

## Extending the Library

When a new convention accrues enough evidence to codify (e.g., G6
icon-size roles, V1 button-role codification, G8 destructive-confirm
composition — each currently tracked in the design-system doc’s Open
Gaps), add a new notebook under `nbs/` following the V10 pattern:

1.  Create `nbs/<category>.ipynb` with `#| default_exp <category>`.
2.  Define a frozen `XVariants` dataclass enumerating the roles.
3.  Instantiate it at module scope as a singleton (e.g.,
    `x_variants = XVariants(...)`).
4.  Add attribute-level tests asserting each role contains its expected
    primitives.
5.  Update this index’s convention-to-notebook table and add a matching
    pointer row to the design-system doc’s Conventions Directory.

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 should declare the convention ID
and state the rationale directly — the design-system doc references the
library, not vice versa.

## 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`.
    ├── 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.
    └── 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: 6 notebooks

## Module Dependencies

``` mermaid
graph LR
    buttons[buttons<br/>Button Roles]
    chrome[chrome<br/>Chrome Variants]
    icons[icons<br/>Icon Size Roles]
    insets[insets<br/>Inset Variants]
    panels[panels<br/>Panel Variants]
    text_tiers[text_tiers<br/>Text Tier Roles]
```

No 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

``` python
from cjm_fasthtml_design_system.buttons import (
    buttons,
    ButtonRoles
)
```

#### Classes

``` python
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

``` python
from cjm_fasthtml_design_system.chrome import (
    chrome,
    ChromeVariants
)
```

#### Classes

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

### 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

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

#### Classes

``` python
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

``` python
from cjm_fasthtml_design_system.insets import (
    insets,
    InsetVariants
)
```

#### Classes

``` python
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

``` python
from cjm_fasthtml_design_system.panels import (
    panels,
    PanelVariants
)
```

#### Classes

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

### 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

``` python
from cjm_fasthtml_design_system.text_tiers import (
    text_tiers,
    TextTierRoles
)
```

#### Classes

``` python
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`."
```
