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