Returnless UI

Button

Buttons are used primarily for actions, such as “Add”, “Close”, “Cancel”, or “Save”. Plain buttons, which look similar to links, are used for less important or less commonly used actions, such as “view shipping settings”.

Variants

Primary

Use to highlight the most important actions in any experience. Don’t use more than one primary button in a section or screen to avoid overwhelming users.

js
<script lang="ts" setup>
import { Button } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="primary">Primary</Button>
</template>

Secondary

Used most in the interface. Only use another style if a button requires more or less visual weight.

js
<script lang="ts" setup>
import { Button } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="secondary">Primary</Button>
</template>

Outline

Use when a button needs to be less prominent than a secondary button. Outline buttons are often used for less important or less commonly used actions.

js
<script lang="ts" setup>
import { Button } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="outline">Outline</Button>
</template>

Destructive

Used when the action will delete user data or be otherwise difficult to recover from. Destructive buttons should trigger a confirmation dialog before the action is completed. Be thoughtful about using destructive buttons because they can feel stressful for users.

js
<script lang="ts" setup>
import { Button } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="destructive">Destructive</Button>
</template>

Ghost

Used for less important or less commonly used actions. Ghost buttons are less prominent than other button styles,

js
<script lang="ts" setup>
import { Button } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="ghost">Ghost</Button>
</template>

Outline

Used for less important or less commonly used actions. Outline buttons are less prominent than other button styles.

js
<script lang="ts" setup>
import { Button } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="outline">Outline</Button>
</template>

Loading

Use when a button has been pressed and the associated action is in progress.

js
<script lang="ts" setup>
import { Button } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="secondary" loading>
    Loading button
  </Button>
</template>

Button with icon

Use when a button needs to be paired with an icon to help convey its purpose.

js
<script lang="ts" setup>
import { Button, ButtonIcon, ButtonContent } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="primary">
    <ButtonIcon :icon="ArrowDownTrayIcon" />
    <ButtonContent>Button with icon on the left</ButtonContent>
  </Button>
  <Button variant="primary">
    <ButtonContent>Button with icon on the right</ButtonContent>
    <ButtonIcon :icon="ArrowDownTrayIcon" />
  </Button>
</template>

Button with image

Use when a button needs to be paired with an image to help convey its purpose.

js
<script lang="ts" setup>
import { Button, ButtonIcon, ButtonContent } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="secondary">
    <ButtonIcon source="https://panel.returnless.test/img/integrations/demo-logo.svg" />
    <ButtonContent>Create coupon</ButtonContent>
  </Button>
  <Button variant="secondary">
    <ButtonContent>Button with icon on the right</ButtonContent>
    <ButtonIcon source="https://panel.returnless.test/img/integrations/demo-logo.svg" />
  </Button>
</template>

Icon only button

Use when a button only needs to be an icon.

js
<script lang="ts" setup>
import { Button, ButtonIcon } from '@returnless/focus-ui';
</script>

<template>
  <Button icon-only variant="secondary">
    <ButtonIcon :icon="EllipsisVerticalIcon"></ButtonIcon>
  </Button>
  <Button icon-only variant="ghost">
    <ButtonIcon :icon="EllipsisVerticalIcon"></ButtonIcon>
  </Button>
</template>

Button with badge

js
<script lang="ts" setup>
import { Button, ButtonBadge, ButtonContent } from '@returnless/focus-ui';
</script>

<template>
  <Button variant="secondary">
    <ButtonContent>Return orders</ButtonContent>
    <ButtonBadge color="slate">100</ButtonBadge>
  </Button>
</template>

Full width button

Use when a button needs to span the full width of its container.

js
<script lang="ts" setup>
import { Button } from '@returnless/focus-ui';
</script>

<template>
  <Button full-width>Full width button</Button>
</template>

Best practices

Buttons should:

  • Be clearly and accurately labeled.
  • Lead with a strong, actionable verb.
  • Use established button colors appropriately. For example, only use a red button for an action that's difficult or impossible to undo.
  • Prioritize the most important actions. Too many calls to action can cause confusion and make users unsure of what to do next.
  • Be positioned in consistent locations in the interface.

Buttons are used primarily for actions, such as "Add", "Close", "Cancel", or "Save". Plain buttons, which look similar to links, are used for less important or less commonly used actions, such as "view shipping settings".

Links are used primarily for navigation, and usually appear within or directly following a sentence.

The HTML that renders for the Button and Link components carriers meaning. Using these components intentionally and consistently results in:

  • A more inclusive experience for assistive technology users.
  • A more cohesive visual experience for sighted users.
  • Products that are easier to maintain at scale.

Content guidelines

Buttons need to be clear and predictable. Users should be able to anticipate what will happen when they select a button. Never mislead someone by mislabeling a button.

Buttons should always lead with a strong verb that encourages action. To provide enough context to users, use the {verb} + {noun} content formula on buttons except in the case of common actions like "Done", "Close", "Cancel", or "OK".

Always write button text in sentence case, which means the first word is capitalized and the rest are lowercase (unless a term is a proper noun).

Avoid unnecessary words and articles such as "the", "an", or "a" to keep button text short and actionable.

Accessibility

Buttons can have different states that are visually and programmatically conveyed to users.

  • Use the ariaControls prop to add an aria-controls attribute to the button. Use the attribute to point to the unique id of the content that the button manages.
  • If a button expands or collapses adjacent content, then use the ariaExpanded prop to add the aria-expanded attribute to the button. Set the value to convey the current expanded (true) or collapsed (false) state of the content.
  • Use the disabled prop to set the disabled state of the button. This prevents users from being able to interact with the button, and conveys its inactive state to assistive technologies.
  • Use the pressed prop to add an aria-pressed attribute to the button.

Users generally expect buttons to submit data or take action, and for links to navigate. If navigation is required for the button component, use the href prop. The control will output an anchor styled as a button, instead of a button in HTML, to help convey this difference.

Labeling

THe accessibilityLabel prop adds an aria-label attribute to the button, which can be accessed by assistive technologies like screen readers. Typically, this label text replaces the visible text on the button for users who use assistive technologies.

Use accessibilityLabel for a button if:

  • The button's visible text does not adequately convey the purpose of the button to non-visual users.
  • The button has no text and relies on an icon alone to convey its purpose.

To help support users who use speech activation software as well as sighted screen reader users, make sure that the aria-label text includes any button text that's visible. Mismatches between visible and programmatic labeling can cause confusion, and might prevent voice recognition commands from working.

When possible, give the button visible text that clearly conveys its purpose without the user of accessibilityLabel. When no additional content is needed, duplication the button text with accessibilityLabel isn't necessary.

When you use the button component to create a link to an external resource:

  • Use the external prop to make the link open in a new tab (or window, depending on the user's browser settings).
  • Use the icon prop to add the external icon to the button.
  • Use the accessibilityLabel prop to include the warning about opening a new tab in the button text for non-visual screen reader users.