Buttons
Interactive controls for primary actions, secondary options, and tertiary navigation. Built on a shared seed architecture with consistent token bindings across 4 color themes.
Overview
Button
The Button component has 3 variant axes: Type, Structure, and Size.
| Property | Values |
|---|---|
| Type | Primary, Secondary, Tertiary |
| Structure | Text-only, Text + Icon |
| Size | Large (64px), Medium (56px), Small (48px), Extra Small (40px) |
Anatomy
button-primary — filllabel-primary — text + icon colorborder-focus — focus ring strokeLive Examples
Button Variants
Hover and press to see interactive states. All 4 color themes shown side by side.
Sizes
Four heights on an 8 px ladder: 64 / 56 / 48 / 40. Large, Medium and Small share the label type (16 px); Extra Small (40 px, new 2026-10-22) drops to label-sm (14 px) and is for dense UI such as comparison-table heads and card corners, never for page-level CTAs, where Small is the floor.
Types & Structures
States
Button States
All 5 interactive states for each button type. Tab through the live examples above to see focus rings.
Icons
Button Icons
The trailing icon can change to suit the action. Pick any 16×16 icon from the Icon Library. Icons come in two types: animated icons move on hover to show what the button does, and static icons only change colour with the button. Hover the examples below.
Animated
Static
When to use
| Type | Use when | Examples |
|---|---|---|
| Animated | The icon shows the action or its direction. The motion acts it out: go forward, bring the file down. | Forward arrow (default), Download |
| Static | The icon labels where the button leads or what it opens. Motion would add nothing. | Add to calendar, Contact us, Call sales |
Tokens
Button Tokens
Fill Tokens
| Token | Light | Dark | Gray | Colored |
|---|---|---|---|---|
button-primary | Orange50 | Orange50 | Orange50 | AlphaWhite90 |
button-primary-hover | Orange70 | Orange70 | Orange70 | White |
button-primary-pressed | Orange60 | Orange60 | Orange60 | AlphaWhite70 |
button-primary-disabled | AlphaBlack20 | AlphaWhite20 | AlphaBlack20 | AlphaWhite20 |
button-secondary | DeepBlue80 | DeepBlue10 | DeepBlue80 | AlphaBlack80 |
button-secondary-hover | DeepBlue90 | White | DeepBlue90 | Black |
button-secondary-pressed | DeepBlue75 | DeepBlue15 | DeepBlue75 | AlphaBlack70 |
button-secondary-disabled | AlphaBlack20 | AlphaWhite20 | AlphaBlack20 | AlphaWhite20 |
button-tertiary | Transparent | Transparent | Transparent | Transparent |
button-tertiary-hover | AlphaBlack20 | AlphaWhite20 | AlphaBlack20 | AlphaWhite20 |
button-tertiary-pressed | AlphaBlack10 | AlphaWhite10 | AlphaBlack10 | AlphaWhite40 |
Label Color Tokens
| Token | Light | Dark | Gray | Colored |
|---|---|---|---|---|
label-primary | White | White | White | Black |
label-secondary | White | Black | White | White |
label-tertiary | Black | White | Black | White |
Stroke Tokens (Tertiary)
| Token | Light | Dark | Gray | Colored |
|---|---|---|---|---|
button-tertiary-stroke | → button-secondary | → button-secondary | → button-secondary | → button-primary-hover |
button-tertiary-stroke-hover | → button-secondary-hover | → button-secondary-hover | → button-secondary-hover | → button-primary-hover |
button-tertiary-stroke-pressed | → button-secondary-pressed | → button-secondary-pressed | → button-secondary-pressed | → button-primary-hover |
button-tertiary-stroke-disabled | → button-secondary-disabled | → button-secondary-disabled | → button-secondary-disabled | → button-primary-disabled |
Focus Ring
| Token | Light | Dark | Gray | Colored |
|---|---|---|---|---|
border-focus | Teal50 | Teal40 | Teal50 | White |
Specs
Button Specs
Padding — Text + Icon
| Size | Height | Top | Right | Bottom | Left | Gap |
|---|---|---|---|---|---|---|
| Large | 64px | 18 | 22 | 18 | 28 | 8 |
| Medium | 56px | 14 | 18 | 14 | 24 | 8 |
| Small | 48px | 10 | 16 | 10 | 20 | 8 |
Padding — Text-only (symmetric)
| Size | Height | V-pad | H-pad |
|---|---|---|---|
| Large | 64px | 18 | 28 |
| Medium | 56px | 14 | 24 |
| Small | 48px | 10 | 20 |
Typography
- Font: Poppins SemiBold 600
- Size: 16px
- Letter-spacing: −0.025em
- Line-height: 1 (single-line labels only)
Optical Alignment
The .btn__label wrapper adds padding-bottom: 2px for optical vertical centering. For Text+Icon buttons, left padding is 6px larger than right padding at each size to balance the visual weight of the arrow.
Arrow Animation Chain
- Default:
translateX(0) - Hover intermediary: quick shift, 50ms linear
- Hover:
translateX(4px)with 150ms ease-out-backcubic-bezier(0.175, 0.885, 0.32, 1.275) - Pressed:
translateX(3px)— slight pull-back - Background fill transitions at 150ms with same easing
Overview
Arrow Button
Icon-only button with arrow. 36 variants from 4 axes: Type, Size, Direction, Shape.
| Property | Values |
|---|---|
| Type | Primary, Secondary, Tertiary |
| Size | Large (64px), Medium (56px), Small (48px) |
| Direction | Forward (→), Back (←) |
| Shape | Square (0 radius), Circle (10000px radius) |
= 3 × 3 × 2 × 2 = 36 variants. Wraps an Arrow Button Seed (18 variants: 3 Types × 6 States) that handles all interaction states internally.
Live Examples
Arrow Button Variants
Sizes
Types, Shapes & Directions
States
Arrow Button States
Arrow Button Seed has 6 states including a Hover Intermediary that creates the two-step animation chain.
Two-Step Animation Chain
- Default → Hover Intermediary: instant — Arrow 1 opacity fades to 0 (disappears)
- Hover Intermediary → Hover: after 25ms delay, Arrow 2 slides in from left to centered position —
SMART_ANIMATE, Ease in and out, 150ms - Hover → Pressed: instant — Arrow 2 shifts 1px to the left
- Hover → Mouse Leave → Default: instant snap back — Arrow 1 reappears, Arrow 2 returns offscreen
Tokens
Arrow Button Tokens
Arrow Button shares the same fill, label, and stroke tokens as Button — they both derive from the shared seed architecture. See the Button token table above for the complete reference.
Specs
Arrow Button Specs
Padding (symmetric)
| Size | Dimensions | Padding | Icon |
|---|---|---|---|
| Large | 64 × 64 | 24px all | 16 × 16 |
| Medium | 56 × 56 | 20px all | 16 × 16 |
| Small | 48 × 48 | 16px all | 16 × 16 |
Direction
Back direction is achieved with scaleX(-1) on the icon wrapper, flipping the arrow horizontally. The transform is applied to the seed instance, not individual vector children.
Shape
Square uses border-radius: 0. Circle uses border-radius: 10000px (effectively a pill/circle at any size).
Overview
Play Button
Circle play button for video thumbnails. Two types (Primary = Orange50, Secondary = DeepBlue80), four sizes. The play triangle is always white and optically centered within the circle.
| Size | Diameter | Icon | Optical offset | Class |
|---|---|---|---|---|
| Extra Large | 96px | 64px | +5px right | play-btn--xl |
| Large | 64px | 42.67px | +4px right | play-btn--lg |
| Medium | 48px | 32px | +3px right | play-btn--md |
| Small | 24px | 16px | +2px right | play-btn--sm |
Anatomy
Play Button Anatomy
btn-primary — Primary fillbtn-secondary — Secondary fill#FFFFFF — icon (always white)border-focus — focus ringLive Examples
Play Button Variants
Hover and click to see interactive states. Both types shown at all 4 sizes.
Primary — all sizes
Secondary — all sizes
States — Extra Large (Primary / Secondary)
#FA4616
#FA4616 · 100%
#C2320C · 100%
#293940
#293940 · 100%
#172125 · 100%
Tokens
Play Button Tokens
| Type | State | Token | Value |
|---|---|---|---|
| Primary | Default | btn-primary | #FA4616 · 60% opacity |
| Primary | Hover | btn-primary | #FA4616 · 100% opacity (reveals solid) |
| Primary | Pressed | btn-primary-hover | #C2320C · 100% opacity |
| Secondary | Default | btn-secondary | #293940 · 60% opacity |
| Secondary | Hover | btn-secondary | #293940 · 100% opacity |
| Secondary | Pressed | btn-secondary-hover | #172125 · 100% opacity |
| Both | All states | — | #FFFFFF icon · always 100% opacity |
| Both | All states | — | backdrop-filter: blur(30px) |
Specs
Play Button Specs
| Size | Diameter | Icon (CSS) | Optical offset |
|---|---|---|---|
| Extra Large | 96px | 64px | margin-left: 5px |
| Large | 64px | 42.67px | margin-left: 4px |
| Medium | 48px | 32px | margin-left: 3px |
| Small | 24px | 16px | margin-left: 2px |
Optical Centering
The play triangle's geometric centroid sits left of center — the left edge (base) is wider than the right tip. Icon is offset right by a small fixed amount per size so it appears visually centered in the circle.
SVG
Single viewBox="0 0 64 64" path for all sizes. CSS width/height on the icon controls rendered size. No separate path per size.
Transparency + Backdrop Blur
Default state is 60% opacity with backdrop-filter: blur(30px) — the circle is semi-transparent and blurs whatever is behind it (e.g. the video thumbnail). On hover, opacity goes to 100% (same color, just solid). On press, color darkens and stays at 100%. The icon SVG is a separate layer at full opacity — it's never dimmed by the button's opacity.
No Shadow
No box-shadow. The frosted fill provides sufficient contrast against the video overlay.
Accessibility
ARIA & Keyboard
ARIA Attributes
| Element | Attribute | Value |
|---|---|---|
| All buttons | role | Implicit from <button> — never use <div> or <span> |
| Link-styled buttons | role="link" | Only if a <button> is visually styled as a link |
| Disabled buttons | disabled + aria-disabled="true" | Both attributes required — disabled removes from tab order, aria-disabled announces state |
| Icon-only buttons (Arrow Button) | aria-label | Descriptive label (e.g. "Next", "Previous") — CSS-masked icons are invisible to screen readers |
| Text + icon buttons | aria-hidden="true" | On the arrow icon element — the label already describes the action |
Focus
| State | Style |
|---|---|
:focus-visible | outline: 2px solid Teal50 (#0BA2B3); outline-offset: 2px |
:focus:not(:focus-visible) | No outline — mouse clicks don't show the ring |
| Disabled | Not focusable — removed from tab order by disabled attribute |
Keyboard Interaction
| Key | Action |
|---|---|
| Tab | Moves focus to the next interactive element |
| Enter / Space | Activates the button (native <button> behavior) |