Component Composition Style
Compose UI from small, named components with slot-friendly APIs; avoid cards-inside-cards and god components that mix data, motion, and chrome.
Layering
Separate structure (Reticle grid, section wrappers), content, and interactive controls. Reticle Design System components (ReticleSection, ReticleCard, ReticleButton) exist so pages do not reimplement grid math. Source: Reticle Design System
shadcn patterns
Install primitives from registries documented in Shadcn UI Ecosystem; extend via cn() wrappers, not forked copies unless behavior diverges. Source: Shadcn UI Ecosystem
Props and variants
Use discriminated unions or variant helpers (CVA-style) for visual states. Name components after what they render, hooks after what they return (useOrgData, not useFetchAndCache). Source: React Style
Vercel composition patterns
The reviewed Vercel Labs composition-patterns skill reinforces the same boundary with sharper failure names:
| Problem | Preferred move |
|---|---|
| Boolean prop soup | Replace independent booleans with explicit variants, discriminated unions, or separate named components so impossible combinations are unrepresentable. |
| Layout owned by leaf widgets | Let the parent own placement; leaf components own behavior and local chrome. |
| Copy-pasted near matches | Extract the shared component only after the repeated shape is real; prefer composition slots before broad configuration APIs. |
| State leaking through props | Put state ownership behind a hook/provider with a narrow interface, then expose compound components for consumers. |
| Provider blob context | Split context by update frequency and read pattern so one changing value does not rerender the whole tree. |
Use this as source-level support for the existing contract, not a new style system. Route exact upstream checks through Vercel Agent Skills; local implementation still follows CSS UI Enforcement and React. Source: vercel-labs/agent-skills composition-patterns, commit f8a72b9603728bb92a217a879b7e62e43ad76c81, checked 2026-07-06
No nested component definitions
Define components at module scope. Nested definitions inside parents break reconciliation and confuse agents diffing files. Source: ui/AGENTS.md
Agent-authored UI
Prefer catalog-constrained generation (JSON Render -- Generative UI Framework pattern) or Sigil token consumption over freeform JSX when LLMs build screens. Source: Sigil Token Architecture
Composition Contract
| Concern | Default | Banned pattern |
|---|---|---|
| Ownership | One component owns one visible structure | Component that fetches data, manages motion, owns layout, and draws chrome |
| Variants | Typed variants or discriminated unions | Boolean prop soup that creates invalid combinations |
| Slots | Slot-friendly composition for variable content | Copy-pasted near-duplicate components |
| State | State machine or hook with named output | Hidden derived state in effects |
| Styling | cn() plus tokens |
Forked registry code with ad hoc class drift |
Proof
For a new component, render at least the main variant, empty/disabled state, and the densest expected content. If text or layout breaks only in the real viewport, the component contract was incomplete. Shared components need tests or stories when their variants can regress independently.
Style Rule Contract
This page follows Style Rule Contract: name the default pattern, banned pattern, reason, exception, proof, and codification path clearly enough that the next agent can apply the rule without asking Kevin again. If a local repo has a stricter rule, follow the local rule and update the wiki when the decision becomes durable.
Timeline
- 2026-07-01 | Aligned this page with Style Rule Contract so style guidance names default behavior, banned patterns, exceptions, proof, and codification expectations. Source: User request, 2026-07-01
- 2026-07-01 | Added a composition contract and proof section for ownership, variants, slots, state, styling, and viewport validation. Source: User request, 2026-07-01
- 2026-07-06 | Folded Vercel Labs
composition-patternsinto the local composition contract: avoid boolean prop soup, keep parent layout ownership, prefer slots/compound components, and split provider state by update frequency. Source:vercel-labs/agent-skillscommitf8a72b9603728bb92a217a879b7e62e43ad76c81 - 2026-05-11 | React style documents hooks naming and lint rules. Source: React Style
- 2026-05-31 | Component composition style page compiled. Source: compiled from wiki graph