skrewww

Actions

Button

Button is a primary interactive trigger for user actions — submit, confirm, navigate, or initiate a process.

Style (Primary/Secondary/Danger) × Size (Small/Medium/Large) × State (Default/Hover/Pressed/Focused/Disabled) — 45 variants

betaReact AvailableFigma AvailableDocs Partial
React last updated
2026-07-11
Documentation last updated
2026-06-01
Accessibility target
WCAG 2.2 AA (target)
Version
0.1.0-beta

Known open questions

  • Confirm exact control height and horizontal padding per size from Figma.
  • Trailing icon is not defined as a separate Figma property on Button — supported in code for composition; confirm with design.
  • Gradient and Glass surface personalities for Button need Surface collection token values.

Live preview

Interactive Button instances using Skrewww tokens. Shape and surface are controlled globally through CSS custom properties — not separate component files.

Visual variants

Sizes

Small / Medium / Large

States

Default / Disabled / Loading

Icons & layout

Leading icon / Trailing icon / Full width

Purpose

Primary interactive trigger for user actions — submit, confirm, navigate, initiate a process.

Variants and states

primary · secondary · danger

When to use

For the main action(s) in a view. Use Primary for the single most important action, Secondary for alternative/less prominent actions, Danger for destructive actions requiring confirmation.

When not to use

For page-to-page navigation (use Link). For toggling a binary state (use Switch). For a single icon-only action (use Icon Button).

Accessibility

Renders as a real <button>, not a styled <div>. Keyboard: Tab to focus, Enter/Space to activate. Focus uses semantic/focus-ring (5.31:1 contrast, confirmed on the Accessibility page). Never rely on the Disabled state alone to explain unavailability — pair with visible explanatory text nearby.

Common mistakes

More than one Primary button in the same view (dilutes hierarchy). Not disabling the button during an async action (allows double-submission). Skipping a confirmation step for Danger actions just because the button is red.

Properties

Style × Size × State as variants. Label (text). Has Icon (boolean) + Icon (instance-swap).

Tokens used

component/radius/controlsemantic/action/primarysemantic/action/dangersemantic/surface/defaultsemantic/text/inversesemantic/text/primarysemantic/focus-ringopacity/disabled

Component API

PropTypeDefaultDescription
variant"primary" | "secondary" | "danger""primary"Visual style mapped to semantic action tokens.
size"sm" | "md" | "lg""md"Control height and typography scale.
loadingbooleanfalseDisables interaction, sets aria-busy, and shows a spinner with screen-reader text.
fullWidthbooleanfalseStretches the control to the width of its container.
leadingIconReactNodeOptional icon before the label (Figma: Has Icon + Icon).
trailingIconReactNodeOptional icon after the label. Not confirmed as a Figma Button property.
hrefstringWhen set, renders as a semantic link (Next.js Link or native anchor for external URLs).
targetstringLink target. `_blank` automatically adds `rel="noopener noreferrer"` when rel is omitted.
disabledbooleanfalseNative disabled for buttons; aria-disabled non-navigating link for href variant.
aria-labelstringRequired accessible name for icon-only buttons.

React example

Copy React example
import { Plus } from "@phosphor-icons/react";
import { Button } from "@/components/ui/Button";

export function Example() {
  return (
    <Button variant="primary" leadingIcon={<Plus size={16} />} type="button">
      Create project
    </Button>
  );
}