1---2name: component-library-architecture3description: Use when defining reusable component anatomy, variants, states, slots, composition, APIs, or component documentation. Use design-tokens-and-naming for shared values and figma-and-tooling-workflow for tool-specific library operations.4---56# Component Library Architecture78<!-- dual-compat-start -->9## Use When10- Defining the **structure** of a component library: what is an atom vs molecule vs organism, and what belongs in the library at all vs in product code.11- Designing a single component's **API surface**: its variants (e.g. `primary | secondary | ghost | destructive`), sizes, and the props/slots that drive them.12- Specifying **full interactive-state coverage** for a component — every state in the matrix (default, hover, focus-visible, active, disabled, loading, selected, error, read-only) is named and given a token-backed treatment, not left to chance.13- Choosing a **composition strategy** — compound components / slots vs a flat prop list — to avoid prop-explosion and boolean-soup.14- Writing the **per-component documentation** so designers and engineers consume the component the same way (anatomy, when-to-use, do/don't, a11y, the variant API).1516## Do Not Use When17- You are defining the **token tiers, naming, or export** (primitive → semantic → component tokens, CSS vars / Style Dictionary). Use `design-tokens-and-naming` — this skill *consumes* those tokens.18- You are producing **Figma-to-dev redlines / measured handoff sheets** for a specific screen. Use `design-handoff-and-dev-spec`.19- You are designing **dark-mode / multi-brand theming** of the same components. Use `dark-mode-and-theming` (this skill keeps every value token-referenced precisely so theming stays free).20- You are auditing **WCAG conformance** of a built UI. Use `accessibility-wcag-2-2-compliance`; here you *build a11y in* rather than audit it.21- You only need the copy inside a control (labels, button text). Use `ux-writing-and-microcopy`.2223## Required Inputs24| Input | Source | Required? | Evidence |25|---|---|---|---|26| Semantic tokens and supported themes | `design-tokens-and-naming` | yes | Token source and theme map |27| Component inventory and priority | Product and engineering owners | yes | Ranked use cases and consumers |28| Platform and accessibility contract | Target repositories and WCAG policy | yes | Framework constraints and required states |29- A **token layer to consume** — at minimum semantic tokens for color, space, radius, type, elevation, motion (`design-tokens-and-naming`). If absent, stop and build tokens first; a component library built on hex literals cannot be themed and is not a system.30- The **target platform(s)** — web (HTML/CSS, React/Vue/Web Components), or cross-platform — because composition mechanics (slots, `children`, named regions) differ.31- The **scope**: which components, and the priority order (foundations first: Button, Input/Field, Icon, Text, then molecules: Field-with-label, Select, then organisms).32- The **system boundary and operating owner**: consuming products/teams, accountable maintainer, contribution route, and review authority. If these are unknown, record a component proposal rather than a maintained system.33- An **accessibility floor** — WCAG 2.2 AA is the minimum (`doctrine/references/wcag-2.2-criteria.md`).3435## Workflow360. **Set the boundary before building the library.** Confirm the products, platforms, consumers, owner, contribution path, and maintenance capacity. Inventory repeated patterns, then prioritise the smallest high-frequency/high-risk component set; do not build a catalogue for its own sake.371. **Place the component on the atomic ladder before designing it.** Atom (indivisible: Button, Input, Icon, Text, Avatar), Molecule (a small bonded group with one job: Field = Label + Input + HelpText + Error; SearchBar = Input + Button), Organism (a self-contained section: Header, Card, DataTable, Form). The level dictates whether it owns layout or only fills a slot. See `references/atomic-structure.md`. Do not let an atom grow a layout or a molecule grow business logic — that is the #1 architecture smell.382. **Define the variant model along orthogonal axes — never one mega-enum.** Separate the axes that vary independently: **intent/variant** (primary/secondary/ghost/destructive), **size** (sm/md/lg), **state** (interactive, below), and **modifiers** (icon-only, full-width, loading). A component's API is the *product* of independent axes, expressed as small enums + booleans, not a `variant="primary-large-loading-icon"` string. State the axes explicitly so the matrix is finite and reviewable.393. **Cover the FULL interactive-state set — this is non-negotiable.** For every interactive component enumerate and give a token-backed treatment to: **default, hover, focus-visible, active/pressed, disabled, loading, selected/checked, error/invalid, read-only** (only the states the component can actually enter). Two rules from doctrine's a11y floor:40 - **focus-visible is mandatory and must be visible** — a real indicator with **≥ 3:1 contrast** against its background, and not obscured by sticky chrome (WCAG 2.2 **2.4.7**, **2.4.11**, **1.4.11**; see `doctrine/references/wcag-2.2-criteria.md`). Never `outline: none` without a replacement.41 - **disabled ≠ invisible** — disabled controls are exempt from contrast minimums but must still be perceivable; communicate state with more than color alone (1.4.1), and prefer not removing them from the tab/AX tree when their presence carries meaning. **loading** must expose `aria-busy`/a live status, and **error** must pair the color with text + `aria-invalid` + `aria-describedby`.424. **Choose composition over configuration.** When a component accumulates >~5 booleans, or needs to inject arbitrary content, switch from props to **composition**: slots / named regions / compound components (`Card.Header`, `Card.Body`, `Select` + `Select.Option`). Expose layout regions as slots; keep behavior in the parent. See `references/atomic-structure.md` §Composition. This is the doctrine "authored, not templated" lever applied to APIs — a small composable primitive beats a fat configurable one.435. **Bind every value to a semantic token.** Padding, color, radius, type, border, shadow, motion durations — all reference tokens (`--color-action-bg`, `--space-3`, `--radius-control`, `--duration-fast`), never literals. This is what makes the component themeable, dark-mode-ready, and multi-brand for free. Map per-component tokens to semantic ones (per `design-tokens-and-naming`); a hard-coded `#2563eb` in a component is a defect.446. **Meet the interaction minimums.** Pointer target **≥ 24×24 CSS px** (aim 44×44 touch / 48dp) — WCAG 2.2 **2.5.8**; honour `prefers-reduced-motion` on any state transition (2.3.3); every drag affordance has a single-pointer alternative (2.5.7). All from `doctrine/references/wcag-2.2-criteria.md`. Motion durations come from motion tokens, not magic numbers.457. **Document the component to the template.** Produce the per-component spec: anatomy diagram (named parts), when-to-use / when-not, the **variant × size × state matrix**, the prop/slot API table, a11y contract, and do/don't pairs. Use `references/component-doc-template.md`. A component without this doc is not "done" — undocumented variants get reinvented and the library forks.468. **Resist anti-slop sameness (`doctrine/design-doctrine.md`).** The default-looking Button (flat fill, generic radius, blue) is the convergent AI mean. Make the *one* authored choice — a deliberate radius, a considered pressed-state shift, a focus ring that belongs to the brand — and apply it systematically through tokens so it reads as one skilled hand, not a template.479. **Run the system as a product.** Before marking a library release complete, record component status (`draft`, `in review`, `approved`, `needs work`), documentation/a11y checks, version/changelog impact, consumer notification, and the next review date. Track adoption/reuse, one-off exceptions, defects, and drift as signals for the next priority.4849## Decision Rules5051| Condition | Architecture choice | Wrong-choice failure |52|---|---|---|53| Variations are mutually exclusive | One typed variant axis | Boolean soup permits contradictory combinations |54| Consumer supplies structured content | Slot or compound composition | Content props expand into an unmaintainable API |55| Behaviour and semantics differ materially | Separate components sharing primitives | One mega-component accumulates conditional branches |56| Difference is only visual role | Same component with semantic variant | Duplicate components drift in behaviour and accessibility |57| A component is requested outside the agreed boundary | Record it as a proposal and route it through contribution review | Silent scope growth makes the system unmaintainable |58| The library has no owner, docs, or review route | Stop release and assign the operating controls | An ownerless library becomes a second source of truth |5960## Capability Contract6162Read and search are required across tokens, usage, components, and accessibility tests. Editing is allowed only for authorised implementation. Execution is required to claim state, API, visual-regression, or accessibility compatibility; publishing a library requires separate authority.6364## Degraded Mode6566Without repository access, return a proposed inventory, API, and state matrix rather than claiming compatibility. Without test or render capability, mark keyboard, assistive-technology, responsive, and theme evidence unverified and block publication.6768## Anti-Patterns69- **State gaps.** Shipping default + hover and forgetting focus-visible, loading, disabled, or error. The matrix exists so nothing is forgotten; an empty cell is a bug, not a default.70- **`outline: none` with no replacement** — a WCAG 2.4.7 failure and the single most common a11y regression in component libraries.71- **Prop-explosion / boolean soup.** A Button with `isPrimary`, `isSecondary`, `isGhost`, `isDanger` booleans (mutually exclusive states as separate flags) instead of one `variant` enum; switch to enums + composition.72- **The mega-variant enum.** `variant="primary-lg-loading"` collapses orthogonal axes into one string — un-typed, un-composable, combinatorially exploding.73- **Hard-coded values.** Any literal hex/px in a component body — it can't theme, can't go dark, can't rebrand. Token it.74- **Atomic-level creep.** An atom that owns page layout; a molecule that fetches data; an organism duplicated three ways because no one documented the first.75- **Disabled-by-color-only / error-by-color-only** — fails 1.4.1; pair with text, icon, or shape.76- **Undocumented component** — no anatomy, no API table, no do/don't → it forks the moment a second person touches it.77- **Ownerless or overbuilt system** — dozens of low-use components with no maintainer, contribution route, or adoption signal. Fix: start with the smallest high-value set and assign operating ownership before expanding.7879## Outputs80| Artefact | Consumer | Evidence and acceptance condition |81|---|---|---|82| Component inventory and composition map | Design-system owners | Scope, dependencies, and ownership are explicit |83| Variant, state, slot, and API contracts | Designers and engineers | Reachable combinations are finite, typed, token-backed, and accessible |84| Component documentation and verification record | Consumers and QA | Examples, theme renders, interaction tests, and known gaps are recorded |85| System operating record | Design-system owner and consuming teams | Scope, owner, contribution status, release change, adoption/quality signals, and review date are visible |86- An **atomic inventory** classifying each component (atom/molecule/organism) with composition relationships.87- A **variant model** per component — the orthogonal axes (variant × size × state × modifier) as small enums + booleans.88- A **full state matrix** per interactive component with a token-backed treatment for every reachable state.89- A **prop/slot API** table and composition contract (slots vs props decision recorded).90- A **per-component spec doc** following `references/component-doc-template.md`, with the a11y contract referencing WCAG 2.2 criteria.9192## Examples93- `examples/button-component-spec.md` — a complete, concrete Button spec: 4 variants × 3 sizes × 9 states, every cell mapped to semantic tokens, the prop/slot API, the focus-ring and target-size a11y contract, and do/don't pairs. Use it as the pattern for any new component. (See `CONTRIBUTING.md` — examples are mandatory and never lorem.)9495## References96- `doctrine/design-doctrine.md` — the anti-slop charter; §0 "looks human-made" applied to API design (composition over configuration, one authored choice applied systematically).97- `doctrine/references/wcag-2.2-criteria.md` — the a11y floor cited throughout: focus-visible & contrast (2.4.7, 1.4.11), focus-not-obscured (2.4.11), target size 24px (2.5.8), reduced motion (2.3.3), dragging alternative (2.5.7), name/role/value (4.1.2), color-not-alone (1.4.1).98- `references/atomic-structure.md` — the atomic ladder, classification rules, and composition (slots/compound) decision guide.99- `references/component-doc-template.md` — the per-component documentation template (anatomy, variant API, state matrix, a11y contract, do/don't).100- Sibling: `design-tokens-and-naming` (tokens this skill consumes), `dark-mode-and-theming`, `design-handoff-and-dev-spec`, `accessibility-wcag-2-2-compliance`.101- Practitioner cross-check: [Eleken design-system checklist](https://www.eleken.co/blog-posts/design-system-checklist) and [design-consistency guide](https://www.eleken.co/blog-posts/design-consistency). Use for operating prompts only; do not import outcomes or benchmarks.102<!-- dual-compat-end -->