Skip to main content

Button

A button triggers an event or action. They let users know what will happen next.

Usage

Buttons are used to trigger actions. Use clear, action-oriented labels.

import { Button } from '@hardwater/teardrop';

<Button variant="primary" onClick={handleClick}>
Save changes
</Button>

Variants

Primary

Primary buttons are for the main action on a page or in a section.

<Button variant="primary">Save</Button>

Secondary

Secondary buttons are for secondary actions.

<Button variant="secondary">Cancel</Button>

Tertiary

Tertiary buttons are for less important actions.

<Button variant="tertiary">Learn more</Button>

Destructive

Destructive buttons are for dangerous actions like delete.

<Button variant="destructive">Delete</Button>

Sizes

Small

<Button size="small">Small button</Button>

Medium (Default)

<Button size="medium">Medium button</Button>

Large

<Button size="large">Large button</Button>

States

Default

<Button>Default</Button>

Hover

Buttons automatically show hover states.

Active

Buttons show active states when clicked.

Disabled

<Button disabled>Disabled</Button>

Loading

<Button isLoading>Loading...</Button>

With Icons

Icon Before

import { Icon } from '@hardwater/teardrop';

<Button iconBefore={<Icon name="save" />}>
Save
</Button>

Icon After

<Button iconAfter={<Icon name="arrow-right" />}>
Continue
</Button>

Icon Only

<Button iconOnly aria-label="Close">
<Icon name="close" />
</Button>

Full Width

<Button fullWidth>Full width button</Button>

API

Props

PropTypeDefaultDescription
variant'primary' | 'secondary' | 'tertiary' | 'destructive''primary'Button variant
size'small' | 'medium' | 'large''medium'Button size
disabledbooleanfalseDisable the button
isLoadingbooleanfalseShow loading state
fullWidthbooleanfalseMake button full width
iconBeforeReactNode-Icon before text
iconAfterReactNode-Icon after text
iconOnlybooleanfalseIcon-only button
onClick(event: MouseEvent) => void-Click handler
type'button' | 'submit' | 'reset''button'Button type
aria-labelstring-Accessible label (required for icon-only)

Accessibility

  • Buttons are keyboard accessible
  • Focus indicators are visible
  • Icon-only buttons require aria-label
  • Loading states are announced to screen readers

Best Practices

  1. Clear labels - Use action verbs (Save, Delete, Submit)
  2. Primary action - Use primary variant for main action
  3. Destructive actions - Use destructive variant for dangerous actions
  4. Icon-only buttons - Always provide aria-label
  5. Loading states - Show loading state for async actions

Examples

Form Actions

<Inline gap="small">
<Button variant="primary" type="submit">
Save
</Button>
<Button variant="secondary" onClick={handleCancel}>
Cancel
</Button>
</Inline>

Destructive Action

<Button variant="destructive" onClick={handleDelete}>
Delete account
</Button>

Loading State

<Button
variant="primary"
isLoading={isSaving}
onClick={handleSave}
>
{isSaving ? 'Saving...' : 'Save changes'}
</Button>