Skip to content

Button ​

Buttons trigger actions. Use for primary, secondary, ghost, ghost-subtle, and tertiary actions with configurable appearance, intent, and size.

Main text buttons keep the design minimum width for their size (s: 96px, m: 120px, l: 136px) and grow when the label requires more space. Utility and icon-only buttons remain content-sized or square.

Overview ​

The catnip-button component renders a native button element with consistent styling. It supports leading/trailing icons, icon-only mode, semantic intent (default, danger), and an optional loading state (aria-busy + native disabled + catnip-button--loading class). Note: using the same disabled look for loading is interim until UX defines final loading visuals; you supply spinners or labels via slots or icons.

Appearance rules: tertiary and ghost-subtle require purpose="utility"; otherwise the component renders as primary. ghost-subtle is the lower-emphasis utility treatment and only supports intent="default". size="xs" requires purpose="utility"; otherwise the button renders as s. intent="danger" is supported with appearance="primary" or appearance="ghost". It is also supported with appearance="secondary" when purpose="utility"; the same appearance and intent on a main button render as primary + danger. Other invalid combinations also render as primary + danger and log a dev-mode console warning.

selected: Only applies with purpose="utility" (e.g. utility toggle groups); sets aria-pressed and dedicated selected styles via catnip-button--selected (primary: filled pressed; other appearances, including ghost-subtle: subtle fill + primary border).

For static icon names in HTML, use kebab-case attributes. For reactive Vue values, bind the camelCase DOM properties:

vue
<catnip-button purpose="utility" appearance="ghost-subtle" left-icon="plus" right-icon="chevron-down">
  Add
</catnip-button>

<catnip-button purpose="utility" appearance="ghost-subtle" .leftIcon="leadingIcon" .rightIcon="trailingIcon">
  Add
</catnip-button>

<catnip-button purpose="utility" appearance="secondary" intent="danger">Delete</catnip-button>

Live example ​

Accessibility ​

  • Native <button> with disabled — no redundant aria-disabled; the disabled attribute is enough for assistive technology (including when loading forces disabled).
  • loading: sets aria-busy="true", uses native disabled (same as disabled prop for interaction), and adds catnip-button--loading. Interim: this disabled look-and-feel for loading is provisional until UX signs off on final loading patterns; the accessible contract (aria-busy, no activation) should remain. Spinner/label visuals are yours (e.g. leftIconSlot with catnip-spinner).
  • Icon-only (no visible label): set buttonAriaLabel (HTML: button-aria-label) so the control has an accessible name. In development, a console warning is logged if an icon-only button has no buttonAriaLabel.
  • type: defaults to button so buttons inside forms do not accidentally submit; use submit / reset only when intended.
  • Meet contrast requirements for text and icons on the button surface (WCAG AA).

Catnip Design System by Signicat