Skip to content

No.48 · Buttons· New

Core Button

The everyday button set that product teams ship, done carefully: filled, soft, bordered, bare, destructive, positive, cautionary and text styles, each in three sizes with icons, an icon-only square, a loading state that keeps its width, and a disabled state, on light and dark.

The prompt

Copy this text

Automatic copying is unavailable. Copy the selected text using your device’s copy command.

Written for the variant you picked above: Primary

Build one reusable button in the style of a modern product design system (crisp, neutral, Inter at 500), in the single style selected below. Anatomy: a native <button type="button"> laid out as an inline flex row with an 8px gap. Sizes: small 32px tall, 12px side padding, 6px radius, 13.5px text, 14px icons; medium 40px, 16px, 8px radius, 15px text, 16px icons; large 48px, 22px, 10px radius, 16px text, 18px icons. Letter-spacing -0.01em, no wrapping. Optional icon before the label and optional icon after it (the trailing one slides 2px right on hover). With only an icon and an aria-label it becomes a square. States: hover changes the fill over 0.15s; press scales to 0.97; keyboard focus shows a 2px #2563eb ring 2px outside (#6ea8fe on dark). Loading: the content fades to opacity 0 but keeps its space (so neither the width nor the accessible name changes), a 16px spinner (2px border with one side clear, 0.7s per turn) sits in the middle, and the button gets aria-busy and aria-disabled and ignores clicks. Disabled: native disabled, 45% opacity, a not-allowed cursor, no hover. Show it at each size, with a leading icon, with a trailing arrow, as an icon-only square, in a 'Save changes' button that loads for 1.6s when pressed, and disabled. Show it on a white panel and a #0a0a0a panel side by side. Selected variant — Primary (primary): Primary: solid ink. Light: #0a0a0a fill, white text, hover #2e2e2e, a faint top highlight (inset 0 1px 0 white at 12%) and a 1px soft shadow. Dark: #ededed fill, #0a0a0a text, hover #cfcfcf. Copy: 'Continue', 'Deploy' with a plus icon. This selection takes precedence over references to other themes or options in the general brief. Implement this selected appearance; do not add a variant picker or alternative appearances unless requested. Implementation requirements: Use React and TypeScript. Keep the component self-contained, with uniquely scoped CSS and no animation libraries. Include required imports, styles and font setup in the result. Interaction: A real button: Enter and Space press it; loading buttons ignore presses; disabled buttons are skipped by Tab. Motion: 0.15s fill and ring changes, a 0.97 press, a 2px slide of the trailing icon and a 0.7s spinner. Reduced motion removes the press and slide and slows the spinner. Accessibility: Native button semantics. Loading keeps the label in the accessibility tree and sets aria-busy and aria-disabled; icon-only buttons need an aria-label; every fill keeps its text at 4.5:1 or better. Responsive behavior: Buttons keep their size; rows wrap, and the two panels stack on narrow screens. Touch: Nothing depends on hover; the press scale gives touch feedback. Preserve keyboard access, visible focus and reduced-motion behavior. Keep fictional demo data and simulated service calls in a separate usage example; expose callbacks for real actions and recover from rejected requests. Keep usage-example links inside the demo: use local buttons or prevent navigation. Demonstration links must not navigate to Vitrine routes or open other pages; preserve real URL support in the reusable component itself. Verify the result at narrow and wide viewport sizes, with keyboard input and reduced motion enabled.

Notes

Interaction
A real button: Enter and Space press it; loading buttons ignore presses; disabled buttons are skipped by Tab.
Motion
0.15s fill and ring changes, a 0.97 press, a 2px slide of the trailing icon and a 0.7s spinner. Reduced motion removes the press and slide and slows the spinner.
Accessibility
Native button semantics. Loading keeps the label in the accessibility tree and sets aria-busy and aria-disabled; icon-only buttons need an aria-label; every fill keeps its text at 4.5:1 or better.
Responsive
Buttons keep their size; rows wrap, and the two panels stack on narrow screens.
On touch
Nothing depends on hover; the press scale gives touch feedback.

Featured

402 components