Skip to main content
Kaleidoscope

Button

Buttons are used to for clearly indicating discrete clickable actions that can be communicated with a simple label or icon.

Default

Buttons are ButtonType.Primary by default, and should contain a text label. For buttons with only an icon and no text, see . The button's children are rendered inside it, allowing for labels, icons, or other elements.

Editable example
<Button>Button</Button>

Best practices

  1. Stick to one primary button per view. The exception to this rule is contextual overlays that may appear within a view.
  2. Use short and clear labels. Avoid using more than three words, long complex words, and waffling sentences. For example, prefer Create page to Create a new page.
  3. Use labels that communicate the effect of their action. Never use Click here.

Types

Button types are used to form a hierarchy of actions. To draw focus to a particular action, ButtonSize.Primary can be used. Try to stick to a maximum of one primary action per context, and use ButtonType.Secondary for less important actions. ButtonType.Tertiary is useful for many densely grouped actions or to de-emphasize less important actions.

Editable example
<Button>Primary</Button>
<Button type={ButtonType.Secondary}>Secondary</Button>
<Button type={ButtonType.Tertiary}>Tertiary</Button>

Disabled

Disable a button to indicate that an action exists but is currently not possible, but will become available later. Disabling a button prevents all user interaction, and can cause issues with tooltips in certain browsers. Avoid disabling buttons in forms — it's often clearer to allow submission to be attempted but directly indicate errors with contextual error states on inputs.

Editable example
<Button disabled>Disabled</Button>
<Button disabled type={ButtonType.Secondary}>Disabled</Button>
<Button disabled type={ButtonType.Tertiary}>Disabled</Button>

Sizes

Size should be used to match a button's size to other controls around it. For example, a button placed in context with inputs that are InputSize.Small should use ButtonSize.Small so that it looks proportional and related as part of the same UI.

Editable example
<Button type={ButtonType.Secondary} size={ButtonSize.Large}>Large</Button>
<Button type={ButtonType.Secondary} size={ButtonSize.Medium}>Medium</Button>
<Button type={ButtonType.Secondary} size={ButtonSize.Small}>Small</Button>
<Button type={ButtonType.Secondary} size={ButtonSize.XSmall}>XSmall</Button>

Width

By default, the button will fit the contents of itself plus a bit of padding. You can use the width prop to either fill the container ("full") or half the width of the container ("half").

Editable example
<Card style={{'width': '500px', maxWidth: "100%", padding: '24px', display: "grid", gap: "16px"}}>
  <Button width="half">
    Half-width button
  </Button>
  <Button width="full">
    Full-width button
  </Button>
</Card>

Icons

Use an icon component as a child to add icons to a button.

Editable example
<Button type={ButtonType.Secondary}>
  <Team />
  Icon left
</Button>
<Button type={ButtonType.Secondary}>
  Icon right
  <Team />
</Button>
<Button type={ButtonType.Secondary}>
  <Team />
  Icon both
  <Team />
</Button>

Decorators

Use the decorator prop for common icon presets like arrows and chevrons. ButtonDecorator.Arrow should be used to emphasize that an action will navigate the user to another route or context. ButtonDecorator.Dropdown is used for buttons that trigger a menu or popover overlay.

Editable example
<Button decorator={ButtonDecorator.Arrow} type={ButtonType.Secondary}>Continue</Button>
<Button decorator={ButtonDecorator.Dropdown} type={ButtonType.Secondary}>Options</Button>

Async actions

A Button will automatically handle transitioning between loading states when onClick returns a promise. A custom success message can be added with the successMessage prop.

Editable example
<Button onClick={() => Promise.resolve()}>Click to load</Button>
<Button onClick={() => Promise.resolve()} successMessage="Success">Custom success</Button>

States

Instead of automatically applying the waiting and success states, the button's state can be manually controlled by using the buttonState prop.

Editable example
<Button buttonState={ButtonState.Idle}>Button state</Button>
<Button buttonState={ButtonState.Waiting}>Button state</Button>
<Button buttonState={ButtonState.Success}>Button state</Button>

Destructive actions

For buttons that perform destructive actions such as deletion or removal, use the isDestructive prop. It's also important to provide an icon or label that clearly indicates that the button will perform a destructive action such as "Delete" and not something vague like "Confirm".

Editable example
<Button isDestructive type={ButtonType.Primary}>
  <Delete />
  Delete
</Button>
<Button isDestructive type={ButtonType.Secondary}>
  <Delete />
  Delete
</Button>
<Button isDestructive type={ButtonType.Tertiary}>
  <Delete />
  Delete
</Button>

Round buttons

Use the isRound prop to render a pill-shaped button with fully rounded corners.

Editable example
<Button isRound>Rounded</Button>
<Button isRound type={ButtonType.Secondary}>Rounded</Button>

Button HTML type

By default the underlying <button> element has no explicit type attribute. Use the buttonType prop to set it to "submit" or "button" — this is important inside forms to prevent accidental submission.

Editable example
<Button buttonType="submit">Submit form</Button>
<Button buttonType="button">Non-submit</Button>

Custom element type

Use the as prop to change the underlying HTML element. For example, as="a" renders an anchor instead of a button.

Editable example
<Button as="a" href={() => "https://www.qwilr.com"}>Anchor button</Button>

Link buttons

Setting an href on a button will transform the underlying html element to an <a> tag. Note that href must be a function that returns the link. By default, links will open in a new tab. This can be changed by setting the openInSameTab prop to true.

Editable example
<Button href={() => "https://www.qwilr.com"}>Link button</Button>
<Button openInSameTab href={() => "https://www.qwilr.com"}>Same tab link</Button>