--- name: shadcn-plan description: "Human-triggered planning for UI built with defuss-shadcn - a page, a whole frontend or a new component: composed from the existing components, typed ATM/MOL/ORG/BLK/TPL, on the theme tokens, with explicit states, APIs, module boundaries, docs and examples." disable-model-invocation: true --- # defuss-shadcn / shadcn-plan Precondition: a person asked for this plan. Do not implement unless they ask for the plan and the implementation. Scope: what to build with defuss-shadcn 0.9.8 (234 components: 70 ATM, 27 MOL, 6 ORG, 128 BLK, 3 TPL). The process around it - evidence, tests, gates - stays with the project's own method (defuss-vae `plan`, for example); this skill adds the defuss-shadcn specifics. ## Where things are Read them; do not search the filesystem. Paths are relative to this file. - `references/catalog.md` - every component by sidebar section: type, states, script, when to use it; each links to its component skill. - `references/tokens.md` - every theme token with its role. - `references/rules.md` - the rules every markup follows. - `references/guides.md` - the guide pages: native APIs, data attributes, State API, cascade layers, modules, accessibility. - A component skill (markup, variants, sizes, ARIA, states): `../defuss-shadcn/references/components/.md`, else `https://raw.githubusercontent.com/kyr0/defuss-shadcn/v0.9.8/skills/defuss-shadcn/references/components/.md`. ## Workflow 1. **Ground.** Read the request, `references/rules.md` and `references/catalog.md`. In a repository that builds defuss-shadcn components itself (an `AGENTS.md` with the component rules), read `AGENTS.md` too: its verifier is the definition of done. 2. **Decompose.** Write the UI as a tree of regions - screen, blocks, organisms, molecules, atoms - down to native elements. For a whole frontend, list the screens first, then each screen's tree. A scaffold (Admin Dashboard, Messenger, Issue Tracker, Notes, Status Page, Desktop) or a Website template that already composes a screen is the first candidate for it. 3. **Deconstruct by reusability before you split by level** (strongly recommended for every ORG, TPL or whole frontend). Splitting "one level down" yields parts shaped by this one plan. Instead, look across the whole plan - every screen, every region - for the smallest common denominators: the units that recur, or that would be useful on their own in another plan. Plan those units first; the ORG or TPL is then a composition of them. For each unit, decide in this order: 1. **an existing component already does it** - reuse it as documented; 2. **a flavor of an existing component** - its behavior and design stay close to it: it is that component, with a documented variant, size or state, or simply an example of it; never a new component; 3. **generically useful on its own** - beyond this plan, with its own behavior or structure: a new smaller component (the lowest type that fits), planned before the ORG or TPL that uses it; 4. **neither** - plain composition of existing components inside the ORG or TPL. This keeps the effort low and the system consistent: one unit, built once, instead of near-duplicates that drift apart. 4. **Select, cheapest rung first** - stop at the first rung that holds: 1. an existing component, as documented; 2. its documented variant, size or state (`data-variant`, `data-size`, `el.api.setState`); 3. existing components composed inside one another; 4. layout and sizing utilities from `core.css` for the arrangement; 5. a new component - only when no composition expresses the behavior. Name the component and its skill for every region. Never invent a class or an attribute value: a value the skill does not list does not exist. 5. **Type every new or composed component** - in this order, the first match wins: the whole page or UI → `TPL`; a sectional template slice (header, hero, pricing, footer) → `BLK`; no descendant components → `ATM`; every direct child component an atom → `MOL`; some direct child a molecule → `ORG`; otherwise `BLK`. A descendant component is markup of another component anywhere inside; the component's own part classes (`card-title`) are DOM, not components. Names never carry the type. 6. **Tokens.** Colour, radius, shadow, font and spacing come from `references/tokens.md` through `var(--token)`. A colour without a token (a status green) is a literal in the component's CSS, never a new token. A new visual identity is a theme - plan it with shadcn-theme, not in component CSS. 7. **Boundaries.** One owner per concern; every other module asks it. A component reaches another only through its public `df$.shadcn.*` API or DOM `CustomEvent`s - never through another component's parts, shared mutable state or inheritance. State lives on the element (`el.api`, `el.store`), never in module scope. A component that ships its own `` owns it. 8. **A new component's contract** (when step 3 or step 4 ends in a new component): - native basis and the platform APIs it relies on (guide: Native Web APIs); - one base class, parts named `-`, variants and sizes as `data-*` axes; - ARIA after the WAI-ARIA APG pattern; - states, `default` first, with the markup each one changes; the State API (`setState`, `getState`, `render`, `el.store`), typed `CustomEvent` details, a public namespace `df$.shadcn.`; - CSS in `@layer components` with `prefers-reduced-motion`, `prefers-contrast` and `forced-colors` rules; - docs: a component skill (front matter `name`, `type`, `section`, `why`, `when`, `where`, `supportedStates`; Native basis, Native Web APIs, Structure, Variants, Sizes, ARIA, Notes), a page whose live examples show every variant, size and state, and an e2e fixture with every documented configuration. In the defuss-shadcn repository itself the section folder, the `nav.ts` entry, the schema and the screenshots follow - `AGENTS.md` "Adding a new component". 9. **Proof.** Name the check for every invariant: shadcn-review's `markup-check` for the vocabulary, an e2e test for behavior, shadcn-theme's `theme-check` for tokens and contrast, and `bun run verify` in the defuss-shadcn repository. ## Output contract ```text UNITS: - (recurs in: ) -> existing | flavor of (variant/state/example) | NEW | composition UI: - -> [TYPE] (skill: ) data-variant= states= NEW: [TYPE] native= parts=<...> variants=<...> states=<...> api=<...> events=<...> TOKENS: --primary (main action), ... BOUNDARIES: -> via DOCS: PROOF: = UNKNOWN[x] BC ; probe= ``` Omit empty lines. No implementation code beyond a markup skeleton for a NEW component.