Pill-shaped button with three variants (primary/secondary/tertiary), four colour schemes (navy/red/light/surface), three sizes, and optional left/right icon slots. 17 Storybook stories cover all combinations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2.4 KiB
2.4 KiB
Button Component Plan
Source
Example pasted into Figma Examples page (node 10:20). Original has 5 properties × many values = 360+ variants. We're building the light-mode subset.
Props (React)
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary' | 'tertiary'
color?: 'navy' | 'red' | 'light' | 'surface'
size?: 'default' | 'comfortable' | 'compact'
leftIcon?: React.ReactNode
rightIcon?: React.ReactNode
}
childrenis the label text- States (hover, active, focus, disabled) handled via CSS pseudo-classes
- Uses
forwardRefto wrap<button>
Colour Scheme Mapping
| Prop value | Example name | Primary bg | Primary text | Secondary border | Our tokens |
|---|---|---|---|---|---|
navy |
Navy | #002664 | white | #002664 | blue-01, white |
red |
Red | #D7153A | white | #D7153A | red-02, white |
light |
On Primary (Teal) | #CBEDFD | #002664 | #002664 | blue-04, blue-01 |
surface |
On Surface | #22272B | white | #22272B | grey-01*, white |
*Note: source uses #22272B, our grey-01 is #3D3D3D. Close enough for now — revisit if the NSW DS specifies #22272B.
Variant × Colour behaviour
- Primary: filled background, white or dark text
- Secondary: transparent bg, 2px border, coloured text
- Tertiary: no fill, no border, coloured text (ghost)
Sizes
| Size | Height | Padding | Typography |
|---|---|---|---|
| Default | 48px | 24px horizontal | Body Strong (16/24 bold) |
| Comfortable | 40px | 20px horizontal | Body Strong (16/24 bold) |
| Compact | 36px | 16px horizontal | Small Strong (14/19 bold) |
Shared Styling
- Border radius:
rounded-full(pill shape, 9999px) - Icon size: 24px (default), 20px (compact)
- Content gap: 8px
- Focus ring: 2px border offset (matches example's "Border" layer)
- Disabled: opacity 50%, cursor not-allowed
Hover/Active States
- Primary: overlay with white at ~10% opacity (hover), ~20% (active)
- Secondary/Tertiary: bg fill at ~5% opacity (hover), ~10% (active)
- Implementation: CSS
hover:andactive:with bg-opacity modifiers
Build Order
- Add tokens (if needed) to tokens.css
- Build React component + stories
- Build Figma component on Components page (rebind to our variables)
- Code Connect link
- addon-designs embed in story
Questions resolved
- All four colour schemes included
- Icon slots as ReactNode
- No dark mode