Phase 1: Session log archived (1096→91 lines), D031 token access convention
Phase 2: ESLint v9 + Prettier + jsx-a11y, initial config and lint fixes
Phase 3: 7 new skills (polish, harden, normalize, clarify, typeset, quieter, adapt)
+ Vercel reference docs, updated audit/review-component refs
Phase 4: Husky + lint-staged pre-commit hooks, preflight updated to 8 checks
Phase 5: Vitest + Testing Library + /write-tests skill
- Badge.tsx colour maps unified to CSS variables (D031)
- 5 empty interface→type alias fixes (Switch, Radio, Divider, IconButton, Link)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
147 lines
6.7 KiB
Markdown
147 lines
6.7 KiB
Markdown
---
|
|
name: normalize
|
|
description: Cross-component consistency scan — checks token access patterns, transitions, focus styles, spacing methods, and displayName across all components in a tier or the entire system.
|
|
user-invocable: true
|
|
argument-hint: "[tier (atoms/molecules/organisms) or 'all']"
|
|
---
|
|
|
|
Scan all components in a tier (or the entire system) for consistency violations and fix them. Unlike audit/critique which evaluate individual components, **normalize ensures the system behaves as one cohesive whole**. This skill finds AND fixes issues.
|
|
|
|
**Target tier:** $ARGUMENTS
|
|
|
|
## Preparation
|
|
|
|
1. Read `docs/design-system.md` for FA design conventions
|
|
2. Read `docs/memory/decisions-log.md` for design rationale (especially D031 on token access)
|
|
3. Read `docs/conventions/component-conventions.md` for structural rules
|
|
4. List all component files in the target tier(s):
|
|
- Atoms: `src/components/atoms/*/`
|
|
- Molecules: `src/components/molecules/*/`
|
|
- Organisms: `src/components/organisms/*/`
|
|
- If target is "all", scan every tier
|
|
|
|
**FA context**: Consistency is trust. When components behave differently for no reason — different transition speeds, different focus styles, different spacing methods — users sense it even if they cannot articulate it. For families in distress, inconsistency creates subconscious unease. Normalize ruthlessly.
|
|
|
|
## Consistency Dimensions
|
|
|
|
For each dimension, scan ALL components in the target scope, compare patterns, identify outliers, and fix them to match the established convention.
|
|
|
|
### 1. Token Access Patterns (D031)
|
|
|
|
**Convention**: Two access methods, by token tier:
|
|
- **Semantic tokens** (colour, spacing, typography, shape): `theme.palette.*`, `theme.spacing()`, `theme.typography.*`, `theme.shape.*` inside theme callbacks. `var(--fa-color-*)`, `var(--fa-spacing-*)` in static contexts.
|
|
- **Component tokens** (badge sizes, card shadows, input dimensions): `var(--fa-badge-*)`, `var(--fa-card-*)` CSS variables only — these are NOT in the MUI theme.
|
|
|
|
**Scan for violations**:
|
|
- [ ] Hardcoded hex/rgb colour values (should use theme or CSS var)
|
|
- [ ] Hardcoded px spacing values (should use `theme.spacing()` or `var(--fa-spacing-*)`)
|
|
- [ ] Hardcoded font sizes or weights (should use `theme.typography.*`)
|
|
- [ ] Semantic tokens accessed via CSS var when inside a theme callback (prefer theme accessor)
|
|
- [ ] Component tokens accessed via theme (they are CSS vars only)
|
|
- [ ] Primitive tokens used directly instead of semantic tokens
|
|
|
|
### 2. Transition Timing
|
|
|
|
**Convention**: 150ms ease-in-out for all state transitions.
|
|
|
|
**Scan for violations**:
|
|
- [ ] Transitions using durations other than 150ms (or `theme.transitions.duration.short`)
|
|
- [ ] Transitions using easing other than ease-in-out
|
|
- [ ] Transitions using bounce, elastic, or spring easing (remove — feels dated)
|
|
- [ ] Missing transitions on interactive state changes (hover, focus, active)
|
|
- [ ] Transitions on layout properties (`width`, `height`, `top`, `left`) instead of `transform`/`opacity`
|
|
|
|
### 3. Focus-Visible Style
|
|
|
|
**Convention**: `:focus-visible` with 2px outline, offset 2px, high contrast (3:1 minimum against adjacent colours).
|
|
|
|
**Scan for violations**:
|
|
- [ ] `outline: none` without `:focus-visible` replacement
|
|
- [ ] Focus styles on `:focus` instead of `:focus-visible` (shows ring on click)
|
|
- [ ] Inconsistent outline width, colour, or offset across components
|
|
- [ ] Missing focus styles entirely on interactive elements
|
|
- [ ] Focus ring colour that does not meet 3:1 contrast
|
|
|
|
### 4. Spacing Method
|
|
|
|
**Convention**: `theme.spacing()` in styled components and `sx` props. `var(--fa-spacing-*)` in static contexts.
|
|
|
|
**Scan for violations**:
|
|
- [ ] Raw pixel values for padding/margin/gap (e.g., `padding: '16px'`)
|
|
- [ ] Mixed methods in the same component (some `theme.spacing()`, some raw values)
|
|
- [ ] Inconsistent spacing scale usage across similar components (e.g., one card uses `spacing(2)` for padding, another uses `spacing(3)`)
|
|
|
|
### 5. Component Structure
|
|
|
|
**Convention**: Per `docs/conventions/component-conventions.md`.
|
|
|
|
**Scan for violations**:
|
|
- [ ] Missing `displayName` on the component
|
|
- [ ] Missing barrel export (`index.ts` with `export { default }` and `export *`)
|
|
- [ ] Missing JSDoc on props interface (every prop needs a `/** description */`)
|
|
- [ ] Missing JSDoc on the component itself
|
|
- [ ] Props defined as `type` instead of `interface` (interfaces produce better autodocs)
|
|
- [ ] Missing `sx` prop forwarding (every component must accept consumer overrides)
|
|
- [ ] Interactive elements not using `React.forwardRef`
|
|
|
|
### 6. Story Coverage
|
|
|
|
**Convention**: Per story coverage checklist in `docs/conventions/component-conventions.md`.
|
|
|
|
**Scan for violations**:
|
|
- [ ] Missing `tags: ['autodocs']` in story meta
|
|
- [ ] Missing Default story
|
|
- [ ] Missing AllVariants story (if component has variants)
|
|
- [ ] Missing Disabled story (if component can be disabled)
|
|
- [ ] Missing Loading story (if component has loading state)
|
|
- [ ] Incorrect `title` prefix (should match tier: `Atoms/`, `Molecules/`, `Organisms/`)
|
|
|
|
### 7. Naming Consistency
|
|
|
|
**Scan for violations**:
|
|
- [ ] Component folder not in PascalCase
|
|
- [ ] File names not matching component name
|
|
- [ ] Inconsistent prop naming across similar components (e.g., `isDisabled` vs `disabled`, `colour` vs `color`)
|
|
- [ ] CSS custom properties not prefixed with `--fa-`
|
|
|
|
## Normalize Process
|
|
|
|
1. **Scan**: Read every component file in the target tier(s)
|
|
2. **Tabulate**: Build a comparison table for each dimension showing what each component does
|
|
3. **Identify outliers**: Find components that deviate from the convention
|
|
4. **Fix**: Update outlier components to match the convention
|
|
5. **Verify**: Ensure TypeScript compiles and Storybook renders after fixes
|
|
|
|
## Normalization Report
|
|
|
|
Present findings in this format:
|
|
|
|
### Scan Summary
|
|
|
|
| Dimension | Components scanned | Violations found | Fixed |
|
|
|-----------|-------------------|-----------------|-------|
|
|
| Token access | ? | ? | ? |
|
|
| Transitions | ? | ? | ? |
|
|
| Focus styles | ? | ? | ? |
|
|
| Spacing | ? | ? | ? |
|
|
| Structure | ? | ? | ? |
|
|
| Stories | ? | ? | ? |
|
|
| Naming | ? | ? | ? |
|
|
|
|
### Violations Fixed
|
|
|
|
For each fix, note:
|
|
- **Component**: Which component was changed
|
|
- **Dimension**: Which consistency rule was violated
|
|
- **Before**: What it was doing
|
|
- **After**: What it does now
|
|
|
|
### System-Level Observations
|
|
|
|
Note any patterns that suggest a convention should be updated (e.g., if most components deviate from the convention, perhaps the convention is wrong).
|
|
|
|
**NEVER**:
|
|
- Change a component's behaviour or API — normalize only changes implementation details
|
|
- Fix one component and leave similar components unfixed — normalize the whole tier
|
|
- Change conventions without flagging it — if you think a convention should change, note it as an observation, do not unilaterally change the rule
|