92 lines
3.2 KiB
Markdown
92 lines
3.2 KiB
Markdown
# T03 — UI Primitive Contract (Recipe Manager UI Kit)
|
|
|
|
Date: 2026-03-27
|
|
Scope: `recipe-manager/frontend`
|
|
|
|
## Goal
|
|
Stabilize core UI primitives so pages stop re-implementing button/card/chip/layout class strings.
|
|
|
|
This is a **low-risk contract layer**, not a redesign system.
|
|
|
|
---
|
|
|
|
## Contract surface (v1)
|
|
|
|
Implemented in:
|
|
- `frontend/src/components/ui/cn.ts`
|
|
- `frontend/src/components/ui/primitives.tsx`
|
|
|
|
### `cn(...values)`
|
|
- Lightweight class composer used by primitives and page-level variant helpers.
|
|
- Avoids repetitive template-string class logic.
|
|
|
|
### `UiPage`
|
|
- Canonical page shell wrapper (`ui-page` + optional additions).
|
|
- Use for top-level layout regions (header container, footer container, page root if needed).
|
|
|
|
### `UiSection`
|
|
- Canonical section shell (`ui-section`) with controlled padding options:
|
|
- `padding="md"` (default)
|
|
- `padding="lg"`
|
|
- `padding="none"`
|
|
- Use for grouped content blocks and major page sections.
|
|
|
|
### `UiCard`
|
|
- Canonical card surface (`ui-card`) with optional tone:
|
|
- `tone="default"`
|
|
- `tone="muted"`
|
|
- Use for repeatable content cards and skeleton containers.
|
|
|
|
### `UiButton`
|
|
- Canonical button primitive (`ui-btn` + variant mapping):
|
|
- `variant="primary"`
|
|
- `variant="secondary"` (default)
|
|
- Use for interactive `<button>` actions.
|
|
|
|
### `UiLinkButton`
|
|
- Anchor-style button for actual links (kept for future use where semantic `<a>` is needed).
|
|
|
|
### `UiChip` / `UiBadge`
|
|
- Canonical chip and badge wrappers around `ui-chip` / `ui-badge`.
|
|
- Use for compact status pills/filter tokens.
|
|
|
|
---
|
|
|
|
## Representative adoption in T03
|
|
|
|
### 1) App shell (`src/App.tsx`)
|
|
- Header and footer wrappers now use `UiPage`.
|
|
- Navigation active/inactive styles now use a `cn(...)` helper contract rather than bespoke duplicated class strings.
|
|
- Shell color treatment shifted to tokenized variables (`var(--...)`) instead of slate/blue freelancing.
|
|
|
|
### 2) Mission Control (`src/components/MissionControlPanel.tsx`)
|
|
- Converted from gray utility block to tokenized contract primitives:
|
|
- `UiSection` for panel shell
|
|
- `UiChip` for status pills
|
|
- Removes bespoke gray class styling drift from this shared panel.
|
|
|
|
### 3) Recipe list page (`src/pages/RecipeListPage.tsx`)
|
|
- Core repeated shells now use primitives:
|
|
- hero wrapper and filter blocks via `UiSection`
|
|
- feature cards and loading skeleton via `UiCard`
|
|
- key actions (`Search`, `Load More`, `Clear all filters`) via `UiButton`
|
|
- This proves the contract on a high-traffic page without broad redesign.
|
|
|
|
---
|
|
|
|
## Usage guidance for follow-on tasks
|
|
|
|
1. Prefer `UiSection`/`UiCard`/`UiButton` before writing new utility-heavy class blocks.
|
|
2. Use tokenized vars (`var(--...)`) for one-off values; avoid raw palette classes in shared surfaces.
|
|
3. Keep inline `style={{ ... }}` for runtime values only (e.g., tag color from data), not static radius/shadow/colors.
|
|
4. When classes need conditional composition, use `cn(...)` in one helper instead of many inlined strings.
|
|
|
|
---
|
|
|
|
## Intentionally deferred (not in T03)
|
|
- Broad conversion of `CookModePage`, `ImportUrlPage`, and full `RecipeDetailPage`.
|
|
- Full button/link semantic normalization (e.g., dedicated router-aware LinkButton primitive).
|
|
- Removal of all legacy one-off class usage in older components.
|
|
|
|
These are better handled in T04/T05 to keep T03 low-risk.
|