Component Spec Template — Ghasi Melmastoon
How to use: Copy this template into a per-component spec file (or as a sub-block of a screen spec). Fill every section. Sections marked (required) must not be skipped —
n/ais acceptable but must be justified.
Component name: <ComponentName>
- Package:
@ghasi/ui-melmastoon/packages/feature-<...> - Status: draft / review / approved
- Owner: ___________
- Last reviewed: YYYY-MM-DD
- Used in screens: [list of screen ids]
- Implements / inherits from: [primitives, base components]
1. Anatomy (required)
A labeled diagram or text-wire showing the component's regions.
┌─────────────────────────────────────────┐
│ [icon] Title [chev] │ <- Header (regions: leading icon, title, trailing chevron)
│ Body text on its own line │ <- Body
│ │
│ [primary CTA] [secondary CTA] │ <- Action row
└─────────────────────────────────────────┘
List every region with:
- Name
- What it is for
- Whether it is optional / always present
- Slot type (e.g. text, icon, primitive, custom)
2. Variants (required)
Enumerate. Each variant gets a one-line purpose + when to use.
| Variant | Purpose | When to use |
|---|---|---|
default | Standard render | Most cases |
compact | Reduced padding for dense lists | Power-user views |
emphasis | Higher visual weight | Hero placements |
3. States (required)
Every state the component can be in. Cover: default, hover, pressed, focus-visible, disabled, loading, error, success, empty, selected, plus any component-specific.
| State | Trigger | Visual change | Telemetry |
|---|---|---|---|
default | Mount | — | — |
hover | Mouse enter (web) | bg shifts to --color-surface-hover | — |
loading | isLoading prop true | Skeleton shimmer; CTA disabled | view.skeleton.shown |
error | error prop set | Border --color-danger; inline message | error.surfaced |
4. Tokens used (required)
Cross-reference the design system tokens this component reads.
| Token | Purpose |
|---|---|
--color-surface | Background |
--color-on-surface | Text |
--space-3 | Internal padding |
--radius-2 | Corner radius |
--shadow-sm | Resting elevation |
--motion-duration-fast | Hover transition |
--motion-easing-emphasised | Press feedback |
5. Accessibility (required)
- Roles / ARIA:
role="...", attributes used (aria-pressed,aria-disabled,aria-describedby, ...) - Keyboard: tab stops, expected key bindings (Enter, Space, Escape, ArrowUp/Down)
- Focus: visible focus ring; focus return on dismiss
- Screen reader: announced label; live region (
aria-live) usage - Touch target: confirms >= 44x44 pt mobile / 32x32 px web
- Reduced motion: how the component degrades when
prefers-reduced-motionis set - Contrast: text and non-text contrast ratios verified
6. Internationalisation (required)
- Strings: all rendered via
next-intl/@ghasi/i18n - RTL: any region that flips, any region that does not (e.g. brand mark)
- Numerals: which numerals format applies (Latin always for money/dates)
- Truncation: behaviour when localised string overflows (truncate with tooltip vs wrap)
7. Telemetry (required)
| Event | When | Properties |
|---|---|---|
component.<name>.viewed | Mount (if instrumented) | surface, screen |
component.<name>.interacted | Click / tap / submit | action, surface |
error.surfaced | Visible error | errorCode, httpStatus, traceId |
8. Performance budget
- Mount cost: < N ms p95 on Moto G4 / Pixel 4a
- Render cost on prop change: < N ms p95
- Bundle delta: <= N KiB gzipped
- No heavy synchronous work in mount path
9. Do / Don't
| Do | Don't |
|---|---|
Use variant="emphasis" for hero placements | Use it everywhere — defeats the emphasis |
Pass onPress for the entire row interaction | Place a button inside the row that swallows the row click |
| Use the loading state when fetching > 200 ms | Show a global spinner — block-level skeletons preferred |
10. Open questions
- Q1: ___
- Q2: ___
11. Stories (Storybook)
default(LTR + RTL)compactemphasisloadingerrordisabled- (any state not covered above)
12. Tests
- Unit: ___
- Component (interaction): ___
- Visual regression (Chromatic / Loki): all stories
- Accessibility (axe in Storybook): zero serious / critical