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:
<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>withdisabled— no redundantaria-disabled; the disabled attribute is enough for assistive technology (including whenloadingforces disabled). loading: setsaria-busy="true", uses nativedisabled(same asdisabledprop for interaction), and addscatnip-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.leftIconSlotwithcatnip-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 nobuttonAriaLabel. type: defaults tobuttonso buttons inside forms do not accidentally submit; usesubmit/resetonly when intended.- Meet contrast requirements for text and icons on the button surface (WCAG AA).