--- 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