UNPKG

@spark-web/design-system

Version:

--- title: Design System ---

237 lines (172 loc) 8.82 kB
# Layer 2 — Surface & Pattern files ## What this layer is The surface and pattern layer sits between the root and individual component rules. It has two responsibilities: 1. **Surface classifier** determines _which product_ is being built before any component is touched. 2. **Surface rules** defines interaction behaviour that applies globally across all components on that surface. Together they answer: _"For this surface, what are the rules that override component defaults?"_ --- ## Where these files live ``` docs/patterns/ CLAUDE.md surface classifier (always read first) internal-admin/ CLAUDE.md surface rules for internal admin list-page.md feature pattern: list of records form-page.md feature pattern: create / edit (coming soon) detail-page.md feature pattern: record detail (coming soon) customer-portal/ not yet defined website/ not yet defined ``` --- ## File 1 — The surface classifier (`docs/patterns/CLAUDE.md`) ### What it does This is the agent's second read (after the root). Its only job is to map signals from a PRD or feature brief to a named surface, then point the agent at the correct surface rules file. ### What it must contain **A signal-to-surface lookup table.** Words or phrases that appear in a PRD, mapped to the surface they indicate: | Signal in PRD | Surface | | ---------------------------------------------------------------- | --------------- | | "admin", "internal", "back office", "ops", "manage", "dashboard" | Internal admin | | "customer", "portal", "my account", "self-service" | Customer portal | | "website", "marketing", "landing page", "public" | Website | | "mobile", "app", "iOS", "Android" | Mobile app | **A pointer to the surface rules file for each defined surface.** Undefined surfaces should be flagged explicitly so the agent stops and asks rather than guessing: ```markdown | Surface | Rules location | | --------------- | -------------------------------------- | | Internal admin | docs/patterns/internal-admin/CLAUDE.md | | Customer portal | Not yet defined flag to the team | ``` **A pointer to feature pattern files** for each surface: ```markdown | Feature type | Pattern file | | ---------------------------- | ----------------------------------------- | | List of records with actions | docs/patterns/internal-admin/list-page.md | | Create or edit a record | docs/patterns/internal-admin/form-page.md | ``` **The canonical reading order** a numbered list reinforcing the full sequence from root to component. This is intentional redundancy: the more times the agent sees the reading order, the less likely it is to skip steps. ```markdown 1. docs/patterns/CLAUDE.md surface classifier (this file) 2. docs/patterns/[surface]/CLAUDE.md surface rules 3. docs/patterns/[surface]/[pattern].md feature pattern (if exists) 4. packages/[component]/CLAUDE.md component rules 5. packages/[component]/src/[component].stories.tsx usage examples ``` --- ## File 2 — Surface rules (`docs/patterns/[surface]/CLAUDE.md`) ### What it does Defines interaction and visual rules that apply across **all** components when building for this surface. These rules sit above component-level CLAUDE.md files. When a conflict exists between a surface rule and a component rule, the surface rule wins. ### What it must contain Rules that are **cross-component** in nature things that would otherwise be decided inconsistently component by component. Examples from the internal admin surface: **Row interaction rules** Whether a table row is clickable, and what that implies for hover state. Connecting row clickability to the data model (does a detail page exist?) rather than leaving it to the agent to infer: ```markdown ### Clickable rows - If the PRD describes a detail page, record view, or drill-down row is clickable - If the PRD describes a read-only display with no destination row is not clickable - If unsure, default to clickable ### Hover state - Row is clickable hover state always applied - Row is not clickable hover state never applied, no exceptions ``` **Overflow menu rules** A decision tree for when a row gets an overflow menu vs. an inline button vs. nothing: ```markdown Does the row have actions? No no overflow menu, no action column Yes how many actions? 1 action + row is NOT clickable inline button or icon 1 action + row IS clickable overflow menu 2+ actions always overflow menu ``` **Badge and pill rules** When to use a status badge, and how to map status values to visual tones. Explicit tone definitions prevent the agent from inventing tones: ```markdown - Positive / active / approved / complete `positive` - Warning / approaching limit / expiring `caution` - Critical / rejected / failed / overdue `critical` - Neutral / inactive / archived / unknown `neutral` - Pending / in review / awaiting approval `pending` ``` ### What it must NOT contain - Component-specific implementation rules (those live in component CLAUDE.md) - Rules that only apply to one feature type (those live in pattern files) - Duplication of anything that already lives in a lower layer --- ## File 3 — Feature pattern file (`[surface]/[pattern].md`) ### What it does Describes how to assemble a specific type of page or feature which components to use, in what order, with what configuration. It is a recipe, not a reference. The agent reads this _after_ the surface rules and _before_ component docs. ### What it must contain - **Component list** the exact packages to use for this feature type - **Assembly order** the layout structure from outermost to innermost - **Per-component configuration** which props to set, what to avoid - **A validation checklist** the agent must run this before marking the task complete Example structure for a list page: ```markdown ## Components required - @spark-web/header - @spark-web/table (Table, TableHeaderRow, TableHeaderCell, TableRow, TableCell) - @spark-web/status-badge (if status column present) - @spark-web/meatball (if row actions present) - @spark-web/table (TablePagination, outside Table) ## Assembly order 1. Header 2. Table a. TableHeaderRow TableHeaderCell (one per column) b. TableRow (one per record) TableCell 3. TablePagination (sibling of Table, never inside it) ## Validation checklist - [ ] Header has a title prop - [ ] Hover state matches row clickability (see surface rules) - [ ] Meatball only present when 2+ row actions exist - [ ] Status cells use StatusBadge no inline styling - [ ] TablePagination is outside Table ``` --- ## How this layer connects to the others | Layer | Reads from | Overrides | | ------------------- | ------------------------------- | ---------------------------------------- | | Root CLAUDE.md | Nothing entry point | | | Surface classifier | Root (via reading order) | | | Surface rules | Surface classifier | Component defaults | | Feature pattern | Surface rules | Nothing it assembles, doesn't override | | Component CLAUDE.md | Feature pattern (per component) | Nothing for this surface | --- ## How to add a new surface 1. Create a folder at `docs/patterns/[surface-name]/`. 2. Create `CLAUDE.md` inside it with the surface rules (row behaviour, badge rules, any globally applicable interaction patterns). 3. Add a row to the signal table in `docs/patterns/CLAUDE.md` pointing to the new file. 4. Update the root `CLAUDE.md` if needed to note the new surface. 5. Create pattern files (list, form, detail, etc.) as features are designed. Do not build for a surface until its rules file exists. An undefined surface means the agent has no contract and will make assumptions. --- ## What happens if this layer is missing or incomplete - The agent applies component defaults regardless of surface context hover states, overflow menus, and badge tones become inconsistent across pages. - Surface-level rules that conflict with component defaults are silently ignored. - Two agents working on the same surface independently will produce different interaction patterns.