2.7 KiB
2.7 KiB
T06 — Styling Guardrails + Lightweight Governance
Date: 2026-03-27
Scope: recipe-manager/frontend
Why this exists
The styling stabilization pass established a token + primitive contract. This governance doc keeps that contract from drifting back into mixed styling modes.
Canonical styling contract (short version)
- Tokens are defined in one place:
src/styles/tokens.css - Build UI from shared primitives first:
src/components/ui/primitives.tsx+ui-*classes fromsrc/index.css - Use tokenized values in classes/styles:
var(--...)or Tailwind theme aliases mapped to tokens - Do not add new raw Tailwind palette utilities (e.g.
bg-blue-500,text-slate-600) in stabilized shared surfaces - Do not hardcode hex colors in
className(e.g.bg-[#1f2937]) for app UI
Reference docs:
./styling-token-contract.md./ui-primitive-contract.md./t05-legacy-style-debt-cleanup.md
Lightweight automated guardrail
A scoped check is available:
cd frontend
npm run style:guardrails
Current guard scope (intentional, low-risk):
src/App.tsxsrc/components/MissionControlPanel.tsxsrc/components/ui/primitives.tsx
What it flags:
- direct palette utility classes (
bg-blue-*,text-slate-*, etc.) - hex colors in arbitrary utility classes (
bg-[#...],text-[#...], etc.)
If violations are found in guarded files, the script exits non-zero.
Contributor checklist (copy into PR template/comments as needed)
- New UI uses
Ui*primitives or existingui-*classes where possible - Any new visual token was added to
tokens.cssfirst - No new hardcoded palette utility classes in stabilized shell/shared primitive areas
- No new hardcoded hex colors in class utilities for app surfaces
npm run style:guardrailspassesnpm run lintpasses
Review heuristics for agents/contributors
When touching frontend UI, quickly answer:
- "Can this use an existing
Ui*primitive?" - "If I need a new color/radius/shadow, did I add a semantic token first?"
- "Am I introducing a second styling path that future edits will copy?"
If the answer to (3) is yes, pause and refactor to the contract.
Intentional limitations (for now)
- The guard script is scoped, not repo-wide, because existing pages still contain known legacy palette usage (tracked in T01/T04).
- The check is intentionally simple regex-based (fast, no lint plugin churn).
- This is not wired into heavy CI yet; it is run locally and can be added to future CI once high-drift pages are migrated.
Expansion path after T04/T07
As additional pages are stabilized, add them to frontend/scripts/style-guardrails.mjs scope to progressively tighten enforcement without breaking current workflows.