Skip to Content

Button

Buttons highlight actions available on a screen.

Interaction Modes

Reviewing

Selecting

Install

yarn add @workday/canvas-kit-react

Component Type

Button

Platform

Web

Component

Sana Canvas

Delivery Channels

Web

Version

16.1.7

Experience Surfaces

Page Body Inline

Component Type

Button

Platform

Web

Component

Sana Canvas

Delivery Channels

Web

Version

16.1.7

Experience Surfaces

Page Body Inline

Anatomy

Image of a Primary and Secondary Button with annotation markers.
  1. Container (Conditional): Houses the contents of the Button. Visual appearance differs based on button type.
  2. Label (Conditional): Specific text describing the action.
  3. Icon (Conditional): Supplementary visual indicator that can be positioned alone or added to the left or right of the label. Supplemental icons are used to promote the purpose of the Button.

Usage Guidance

  • Buttons should indicate an action.
  • They should be discoverable, easy to identify, and specific.
  • Make Buttons look and feel clickable.
  • Icons can be used alone or added to the left or right of the label. If used, the icon should signify what the Button does.
  • Use icon-only variants in dense environments or when space is limited.
  • Use accessible tooltips with icon-only variants to help explain ambiguous icons for everyone.
  • When deciding which Button to use, consider the level of priority of the action, as well as how much visual emphasis the Button should have in the context of the page it will live on. Be intentional and refer to the examples below to determine which is right for your use case.

When to Use Something Else

  • Use Hyperlinks within a paragraph to navigate to another page.
  • Consider using checkbox, switch, or segmented control when a component is needed that can capture 2 togglable states.

Design Annotations for Accessibility

  • Write accessible name for icon-only button variants.

Examples

PrimaryButton

The example below shows multiple instances of a PrimaryButton with various icon configurations.

import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
import {createStyles} from '@workday/canvas-kit-styling';
import {
  caretDownIcon,
  plusIcon,
  relatedActionsVerticalIcon,
} from '@workday/canvas-system-icons-web';
import {system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  gap: system.gap.md,
  padding: system.padding.md,
});

export default () => (
  <Flex cs={parentContainerStyles}>
    <PrimaryButton>Primary</PrimaryButton>
    <PrimaryButton icon={plusIcon} iconPosition="start">
      Primary
    </PrimaryButton>
    <PrimaryButton icon={caretDownIcon} iconPosition="end">
      Primary
    </PrimaryButton>
    <Tooltip title="Related Actions">
      <PrimaryButton icon={relatedActionsVerticalIcon} />
    </Tooltip>
  </Flex>
);

Primary Buttons also have an inverse variant. While it looks similar to the default Secondary Button, the default outline as well as the hover and focus states are different. Use this variant when you need to place a Primary Button on a dark or colorful background such as neutral400.

import React from 'react';

import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
import {createStyles} from '@workday/canvas-kit-styling';
import {
  caretDownIcon,
  plusIcon,
  relatedActionsVerticalIcon,
} from '@workday/canvas-system-icons-web';
import {system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  gap: system.gap.md,
  backgroundColor: system.color.surface.contrast.default,
  padding: system.padding.md,
});

export default () => (
  <Flex cs={parentContainerStyles}>
    <PrimaryButton variant="inverse">Primary</PrimaryButton>
    <PrimaryButton icon={plusIcon} iconPosition="start" variant="inverse">
      Primary
    </PrimaryButton>
    <PrimaryButton icon={caretDownIcon} iconPosition="end" variant="inverse">
      Primary
    </PrimaryButton>
    <Tooltip title="Related Actions">
      <PrimaryButton icon={relatedActionsVerticalIcon} variant="inverse" />
    </Tooltip>
  </Flex>
);

SecondaryButton

The example below shows multiple instances of a SecondaryButton with various icon configurations.

import React from 'react';

import {SecondaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
import {createStyles} from '@workday/canvas-kit-styling';
import {
  caretDownIcon,
  plusIcon,
  relatedActionsVerticalIcon,
} from '@workday/canvas-system-icons-web';
import {system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  gap: system.gap.md,
  padding: system.padding.md,
});

export default () => (
  <Flex cs={parentContainerStyles}>
    <SecondaryButton>Secondary</SecondaryButton>
    <SecondaryButton icon={plusIcon} iconPosition="start">
      Secondary
    </SecondaryButton>
    <SecondaryButton icon={caretDownIcon} iconPosition="end">
      Secondary
    </SecondaryButton>
    <Tooltip title="Related Actions">
      <SecondaryButton icon={relatedActionsVerticalIcon} />
    </Tooltip>
  </Flex>
);

Secondary Buttons also have an inverse variant. Use this when you need to place a Secondary Button on a dark or colorful background such as neutral400.

import React from 'react';

import {SecondaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
import {createStyles} from '@workday/canvas-kit-styling';
import {
  caretDownIcon,
  plusIcon,
  relatedActionsVerticalIcon,
} from '@workday/canvas-system-icons-web';
import {system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  gap: system.gap.md,
  padding: system.padding.md,
  backgroundColor: system.color.surface.contrast.default,
});

export default () => (
  <Flex cs={parentContainerStyles}>
    <SecondaryButton variant="inverse">Secondary</SecondaryButton>
    <SecondaryButton icon={plusIcon} variant="inverse">
      Secondary
    </SecondaryButton>
    <SecondaryButton icon={caretDownIcon} variant="inverse" iconPosition="end">
      Secondary
    </SecondaryButton>
    <Tooltip title="Related Actions">
      <SecondaryButton icon={relatedActionsVerticalIcon} variant="inverse" />
    </Tooltip>
  </Flex>
);

TertiaryButton

The example below shows multiple instances of a TertiaryButton with various icon configurations.

import React from 'react';

import {TertiaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
import {createStyles} from '@workday/canvas-kit-styling';
import {
  caretDownIcon,
  plusIcon,
  relatedActionsVerticalIcon,
} from '@workday/canvas-system-icons-web';
import {system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  gap: system.gap.md,
  padding: system.padding.md,
});

export default () => (
  <Flex cs={parentContainerStyles}>
    <TertiaryButton>Tertiary</TertiaryButton>
    <TertiaryButton icon={plusIcon} iconPosition="start">
      Tertiary
    </TertiaryButton>
    <TertiaryButton icon={caretDownIcon} iconPosition="end">
      Tertiary
    </TertiaryButton>
    <Tooltip title="Related Actions">
      <TertiaryButton icon={relatedActionsVerticalIcon} />
    </Tooltip>
  </Flex>
);

Tertiary Buttons also have an inverse variant. Use this when you need to place a Tertiary Button on a dark or colorful background such as neutral400.

import React from 'react';

import {TertiaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
import {createStyles} from '@workday/canvas-kit-styling';
import {
  caretDownIcon,
  plusIcon,
  relatedActionsVerticalIcon,
} from '@workday/canvas-system-icons-web';
import {system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  gap: system.gap.md,
  padding: system.padding.md,
  backgroundColor: system.color.surface.contrast.default,
});

export default () => (
  <Flex cs={parentContainerStyles}>
    <TertiaryButton variant="inverse">Tertiary</TertiaryButton>
    <TertiaryButton icon={plusIcon} iconPosition="start" variant="inverse">
      Tertiary
    </TertiaryButton>
    <TertiaryButton icon={caretDownIcon} iconPosition="end" variant="inverse">
      Tertiary
    </TertiaryButton>
    <Tooltip title="Related Actions">
      <TertiaryButton icon={relatedActionsVerticalIcon} variant="inverse" />
    </Tooltip>
  </Flex>
);

DeleteButton

Use sparingly for destructive actions that will result in data loss, can’t be undone, or will have significant consequences. They commonly appear in confirmation dialogs as the final confirmation before being deleted.

import {DeleteButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
import {createStyles} from '@workday/canvas-kit-styling';
import {trashIcon} from '@workday/canvas-system-icons-web';
import {system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  gap: system.gap.md,
  padding: system.padding.md,
});

export default () => (
  <Flex cs={parentContainerStyles}>
    <DeleteButton>Delete</DeleteButton>
    <DeleteButton icon={trashIcon} iconPosition="start">
      Delete
    </DeleteButton>
    <DeleteButton icon={trashIcon} iconPosition="end">
      Delete
    </DeleteButton>
    <Tooltip title="Delete">
      <DeleteButton icon={trashIcon} />
    </Tooltip>
  </Flex>
);

Delete Buttons also have an outline variant.

import {DeleteButton} from '@workday/canvas-kit-react/button';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
import {createStyles} from '@workday/canvas-kit-styling';
import {trashIcon} from '@workday/canvas-system-icons-web';
import {system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  display: 'flex',
  gap: system.gap.md,
  padding: system.padding.md,
});

export default () => (
  <div className={parentContainerStyles}>
    <DeleteButton variant="outline">Delete</DeleteButton>
    <DeleteButton icon={trashIcon} iconPosition="start" variant="outline">
      Delete
    </DeleteButton>
    <DeleteButton icon={trashIcon} iconPosition="end" variant="outline">
      Delete
    </DeleteButton>
    <Tooltip title="Delete">
      <DeleteButton icon={trashIcon} variant="outline" />
    </Tooltip>
  </div>
);

Grow Prop

The example below shows the use of the grow prop on different variants of buttons. This will set the width of the button to the width of its container.

import {
  DeleteButton,
  PrimaryButton,
  SecondaryButton,
  TertiaryButton,
} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {px2rem} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const baseStyles = {
  gap: system.gap.md,
  padding: system.padding.md,
  flexDirection: 'column',
  maxWidth: px2rem(300),
};

export default () => (
  <Flex cs={baseStyles}>
    <PrimaryButton size="small" grow={true}>
      Primary
    </PrimaryButton>
    <SecondaryButton size="small" grow={true}>
      Secondary
    </SecondaryButton>
    <TertiaryButton size="small" grow={true}>
      Tertiary
    </TertiaryButton>
    <DeleteButton size="small" grow={true}>
      Delete
    </DeleteButton>
  </Flex>
);

Custom Styles

All of our buttons support custom styling via the cs prop. For more information, check our “How To Customize Styles”  or view the example below.

import {PrimaryButton, PrimaryButtonProps, buttonStencil} from '@workday/canvas-kit-react/button';
import {createComponent} from '@workday/canvas-kit-react/common';
import {systemIconStencil} from '@workday/canvas-kit-react/icon';
import {Grid} from '@workday/canvas-kit-react/layout';
import {createStencil, createStyles, px2rem} from '@workday/canvas-kit-styling';
import {plusIcon} from '@workday/canvas-system-icons-web';
import {base, system} from '@workday/canvas-tokens-web';

const customContainer = createStyles({
  gap: system.gap.md,
  maxWidth: 'max-content',
});

const myButtonStencil = createStencil({
  base: {
    [buttonStencil.vars.background]: base.green100,
    [buttonStencil.vars.label]: base.green700,
    [systemIconStencil.vars.color]: base.green700,
    [buttonStencil.vars.borderRadius]: px2rem(2),
    border: `${px2rem(3)} solid transparent`,
    '&:focus-visible': {
      [buttonStencil.vars.background]: base.green700,
      [buttonStencil.vars.boxShadowInner]: base.green100,
      [buttonStencil.vars.boxShadowOuter]: base.green700,
      [systemIconStencil.vars.color]: system.color.fg.inverse,
    },
    '&:hover': {
      [buttonStencil.vars.background]: base.green600,
      border: `${px2rem(3)} dotted ${base.green700}`,
      [buttonStencil.vars.label]: base.green700,
      [systemIconStencil.vars.color]: system.color.fg.inverse,
    },
    '&:active': {
      [buttonStencil.vars.background]: base.green700,
      [buttonStencil.vars.label]: system.color.fg.inverse,
      [systemIconStencil.vars.color]: system.color.fg.inverse,
    },
  },
});

const MyCustomButton = createComponent('button')({
  Component: ({children, cs, ...elemProps}: PrimaryButtonProps, ref, Element) => (
    <PrimaryButton as={Element} ref={ref} cs={[myButtonStencil(), cs]} {...elemProps}>
      {children}
    </PrimaryButton>
  ),
});

const myCustomStyles = createStyles({
  padding: system.padding.md,
  textTransform: 'uppercase',
  [buttonStencil.vars.background]: base.slate200,
  [buttonStencil.vars.label]: base.slate700,
  [systemIconStencil.vars.color]: base.slate700,
  [buttonStencil.vars.borderRadius]: system.shape.md,
  [buttonStencil.vars.border]: base.slate800,
  '&:focus-visible': {
    [buttonStencil.vars.background]: base.slate700,
    [buttonStencil.vars.boxShadowInner]: base.slate200,
    [buttonStencil.vars.boxShadowOuter]: base.slate700,
    [systemIconStencil.vars.color]: system.color.fg.inverse,
  },
  '&:hover': {
    [buttonStencil.vars.background]: base.slate600,
    [buttonStencil.vars.border]: `${px2rem(3)} dotted ${base.slate700}`,
    [buttonStencil.vars.label]: base.slate700,
    [systemIconStencil.vars.color]: system.color.fg.inverse,
    border: `${px2rem(3)} dotted ${base.slate700}`,
  },
  '&:active': {
    [buttonStencil.vars.background]: base.slate700,
    [buttonStencil.vars.label]: system.color.fg.inverse,
    [systemIconStencil.vars.color]: system.color.fg.inverse,
  },
});

const customColors = {
  default: {
    background: base.amber100,
    icon: base.amber500,
    label: base.amber500,
  },
  focus: {
    background: base.amber500,
    boxShadowInner: base.amber100,
    boxShadowOuter: base.amber500,
  },
  hover: {
    background: base.amber400,
    icon: system.color.fg.inverse,
  },
  active: {
    background: base.amber500,
  },
  disabled: {},
};

export default () => (
  <Grid cs={customContainer}>
    <MyCustomButton icon={plusIcon}>Styling Override Via Stencil Variables</MyCustomButton>
    <MyCustomButton icon={plusIcon} cs={myCustomStyles}>
      Style Override Via Create Styles
    </MyCustomButton>
    <PrimaryButton icon={plusIcon} colors={customColors}>
      Styling Override Via Colors Prop
    </PrimaryButton>
  </Grid>
);

Theme Overrides

The most common way to theme our buttons is to pass a theme object at the root level of the application via the CanvasProvider. In the example below, our buttons use our brand.action.** tokens with the fallback being brand.primary.**.

Caution: Setting --cnvs-brand-action** tokens at the :root CSS will override all PrimaryButton theme colors set at the CanvasProvider level.

Note: You should not individually theme components wrapping them with the CanvasProvider, but rather theme at the root level of the application.

Override Primary Color Via Canvas Provider

Override Action Color Via CSS Action Token

import React from 'react';

import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {CanvasProvider} from '@workday/canvas-kit-react/common';
import {Flex} from '@workday/canvas-kit-react/layout';
import {Heading} from '@workday/canvas-kit-react/text';
import {createStyles} from '@workday/canvas-kit-styling';
import {
  caretDownIcon,
  plusIcon,
  relatedActionsVerticalIcon,
} from '@workday/canvas-system-icons-web';
import {brand, system} from '@workday/canvas-tokens-web';

const parentContainerStyles = createStyles({
  gap: system.gap.md,
  padding: system.padding.md,
});

const customActionTheme = createStyles({
  [brand.action.base]: 'teal',
  [brand.action.accent]: 'white',
  [brand.action.dark]: 'hsla(180, 100%, 20%)',
  [brand.action.darkest]: 'hsla(180, 100%, 16%)',
});

export default () => (
  <div>
    <Heading size="medium" as="h3">
      Override Primary Color Via Canvas Provider
    </Heading>
    <CanvasProvider
      theme={{
        canvas: {
          palette: {
            primary: {
              main: 'navy',
            },
          },
        },
      }}
    >
      <Flex cs={parentContainerStyles}>
        <PrimaryButton>Primary</PrimaryButton>
        <PrimaryButton icon={plusIcon} iconPosition="start">
          Primary
        </PrimaryButton>
        <PrimaryButton icon={caretDownIcon} iconPosition="end">
          Primary
        </PrimaryButton>
        <PrimaryButton aria-label="Related Actions" icon={relatedActionsVerticalIcon} />
      </Flex>
    </CanvasProvider>
    <Heading size="medium" as="h3">
      Override Action Color Via CSS Action Token
    </Heading>
    <div className={customActionTheme}>
      <Flex cs={parentContainerStyles}>
        <PrimaryButton>Primary</PrimaryButton>
        <PrimaryButton icon={plusIcon} iconPosition="start">
          Primary
        </PrimaryButton>
        <PrimaryButton icon={caretDownIcon} iconPosition="end">
          Primary
        </PrimaryButton>
        <PrimaryButton aria-label="Related Actions" icon={relatedActionsVerticalIcon} />
      </Flex>
    </div>
  </div>
);

Accessibility

The primary accessibility goal is a visible, programmatically determinable name on a native control that performs an in-page action (submit, open, dismiss, and similar). This page covers PrimaryButton, SecondaryButton, TertiaryButton, and DeleteButton. Use Hyperlink  when the control navigates to another URL or in-page location. For Toolbar  icon and dropdown controls, see that component’s documentation. For a control that opens a menu, compose Menu so Menu.Target wires popup state. When users choose one value from two or more mutually exclusive options, use Segmented Control (SegmentedControl.List with multiple SegmentedControl.Item components)—not a lone variant button.

See the Button pattern (APG)  and Canvas Kit Accessibility overview .

Minimum Accessible Structure

The following matches the PrimaryButton examples: visible text for the default case, text plus a decorative icon, and an icon-only control with an accessible name.

import {PrimaryButton} from '@workday/canvas-kit-react/button'; import {Tooltip} from '@workday/canvas-kit-react/tooltip'; import {plusIcon, relatedActionsVerticalIcon} from '@workday/canvas-system-icons-web'; <PrimaryButton>Save</PrimaryButton>; <PrimaryButton icon={plusIcon}>Add item</PrimaryButton>; <Tooltip title="Related Actions"> <PrimaryButton icon={relatedActionsVerticalIcon} /> </Tooltip>;

For icon-only buttons, prefer Tooltip with title and default type="label" (which sets aria-label from title so sighted users also see the label). If the spec explicitly says not to use a tooltip, set aria-label on the button instead. The same patterns apply to SecondaryButton, TertiaryButton, and DeleteButton.

Built-in Behaviors

Canvas Kit applies these automatically on PrimaryButton, SecondaryButton, TertiaryButton, and DeleteButton. Do not duplicate them in consuming code.

ARIA and DOM (applied by button components):

  • Variant buttons: Render a native <button type="button"> (via BaseButton). Do not add role="button".
  • Visible label: Button text is rendered in BaseButton.Label (<span>) inside the <button> so its text contributes to the accessible name.
  • icon: Renders BaseButton.Icon (SystemIcon). Canvas Kit icon SVG markup uses role="presentation" and focusable="false", so icons beside visible text are not announced separately.
  • disabled: Maps to the native disabled attribute; disabled buttons are skipped in the tab order.
  • Focus: Visible focus styling uses :focus-visible (and a .focus class twin for visual testing).
  • ref: Forwards to the underlying <button>.
  • Native button attributes: Standard props (for example aria-label, aria-pressed, aria-expanded, id, onClick) pass through to the <button> unless you change the element with as. Variant buttons do not set aria-pressed unless you pass it for a deliberate toggle design.
  • Menus: Variant buttons do not set aria-haspopup or aria-expanded. Menu.Target (and related Menu APIs) apply those when a menu is attached.

Keyboard (native <button> behavior):

Variant buttons use native button keyboard support: Tab / Shift+Tab for focus order, and Enter or Space to activate. Do not replace the <button> with a non-focusable element or suppress activation keys.

Screen reader expectations (when built-in behaviors are used as intended):

  • On focus, assistive technology announces the button name (visible text and/or aria-label) and role (for example, “Save, button”).
  • Icons rendered with icon next to visible text are not announced as separate images.
  • Disabled buttons are announced as unavailable and are not in the tab order.
  • When the button opens a menu through Menu, Menu.Target exposes popup and expanded state; see Menu accessibility.

Accessibility Requirements

Required in application code for an accessible button. Rows marked (conditional) apply only when the situation matches—otherwise omit.

If no design spec is provided: use a PrimaryButton (or the variant that matches the design) with non-empty visible text. Omit icon, disabled, Tooltip, aria-label, custom id, as, and a ref unless the spec requires them.

RequirementHow to satisfy
Accessible nameNon-empty visible text inside the variant button
Icon-only name (conditional)Tooltip with type="label" and title (preferred; see PrimaryButton), or aria-label when the spec explicitly says not to use a tooltip. Do not use type="muted" on Tooltip—it does not set an accessible name
Variant choicePrimaryButton, SecondaryButton, TertiaryButton, or DeleteButton per design; DeleteButton only for destructive actions
Decorative icon (conditional)icon with visible text—no extra ARIA on the icon; meaning comes from button text
Mutually exclusive group (conditional)Segmented Control with two or more SegmentedControl.Item siblings and aria-label on SegmentedControl.List—not for a single button or lone on/off control
Toggle pressed state (conditional)aria-pressed on a variant button for a standalone on/off control, or Toolbar  per toolbar specs—not for one-shot actions (Save, Delete, Open)
Menu trigger (conditional)Menu + Menu.Target (or Menu.ContextTarget) as the button—do not hand-wire aria-haspopup / aria-expanded without the Menu model; see Menu accessibility
Related button groups (conditional)Semantic grouping (<ul> / <li> or <fieldset> / <legend>) when several buttons share one question or legend; each control still needs its own accessible name
Disabled (conditional)Native disabled on the variant button when the spec marks the action unavailable
Navigation (conditional)Hyperlink  instead of a variant button when the action is navigation
Programmatic focus (conditional)ref on the variant button and focus() only when the product must move focus after an action—omit by default

Summary for code generation:

  • REQUIRED: variant button with a non-empty accessible name (visible text for text buttons; for icon-only, Tooltip with type="label" preferred, or aria-label when the spec says not to use a tooltip)
  • CONDITIONAL: icon; icon-only naming; disabled; aria-pressed for toggle specs; Menu for menus; Hyperlink for navigation; grouping markup; programmatic focus via ref

Anti-Patterns

Do not generate code that does the following (see Accessibility Requirements above for what to supply instead):

  • Use a <div> or <span> with onClick instead of a variant button—use PrimaryButton, SecondaryButton, TertiaryButton, or DeleteButton so keyboard and assistive technology get native <button> behavior
  • Add role="button" on variant buttons—the control is already a <button>
  • Use a variant button (or type="submit" without an intentional form action) for URL navigation—use Hyperlink 
  • Leave icon-only buttons without a name—prefer Tooltip with type="label", or aria-label when the spec says not to use a tooltip; do not rely on the icon graphic alone
  • Use Tooltip with type="muted" on icon-only buttons—muted tooltips do not set an accessible name
  • Use aria-label on icon-only buttons when the spec allows tooltips—prefer Tooltip with type="label" unless the spec explicitly says not to use a tooltip
  • Set aria-haspopup or aria-expanded on a variant button without Menu—use Menu.Target so open state stays in sync with the menu model
  • Set aria-pressed on one-shot actions (Save, Delete, Open)—see Toggle pressed state in the requirements table
  • Use SegmentedControl for a single option or a lone on/off control—see Mutually exclusive group in the requirements table
  • Add aria-hidden or change the role on icon when visible button text already conveys meaning—Canvas Kit icons are presentational.
  • Use aria-disabled instead of disabled—variant buttons map unavailability to the native disabled attribute
  • Duplicate menu ARIA that Menu.Target already applies

Component API

PrimaryButton

Props

Props extend from button. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
variant'inverse'

Variant has an option for inverse which will inverse the styling

iconPosition 'start' | 'end'

Button icon positions can either be start or end. If no value is provided, it defaults to start.

'start'
shouldMirrorIconboolean

If set to true, transform the icon's x-axis to mirror the graphic. Use this if you want to always mirror the icon regardless of the content direction. If the icon should mirror only when in an right-to-left language, use shouldMirrorIconInRTL instead.

false
shouldMirrorIconInRTLboolean

If set to true, transform the icon's x-axis to mirror the graphic when the content direction is rtl. Icons don't have enough context to know if they should be mirrored in all cases. Setting this to true indicates the icon should be mirrored in right-to-left languages.

false
size

There are four button sizes: extraSmall, small, medium, and large. If no size is provided, it will default to medium.

colors

Override default colors of a button. The default will depend on the button type

icon

The icon of the Button. Note: Not displayed at small size

shouldMirrorboolean

If set to true, transform the SVG's x-axis to mirror the graphic. Use this if you want to always mirror the icon regardless of the content direction. If the SVG should mirror only when in an right-to-left language, use shouldMirrorInRTL instead.

false
shouldMirrorInRTLboolean

If set to true, transform the SVG's x-axis to mirror the graphic when the content direction is rtl. Icons don't have enough context to know if they should be mirrored in all cases. Setting this to true indicates the icon should be mirrored in right-to-left languages.

false
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling'; import {mergeStyles} from '@workday/canvas-kit-react/layout'; // ... // `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same // function signature, but adds support for style props. return ( <Element {...handleCsProp(elemProps, [ myStyles, myModifiers({ size: 'medium' }), myVars({ backgroundColor: 'red' }) ])} > {children} </Element> )
colorstring

The color of the SystemIcon. This defines accent and fill. color may be overwritten by accent and fill.

childrenReactNode
accentstring

The accent color of the SystemIcon. This overrides color.

backgroundstring

The background color of the SystemIcon.

fillIconboolean

Whether the icon should received filled (colored background layer) or regular styles. Corresponds to toggled in ToolbarIconButton

growboolean

True if the component should grow to its container's width. False otherwise.

asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

button
refReact.Ref<R = button>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

SecondaryButton

Props

Props extend from button. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
variant'inverse'

Variant has an option for inverse which will inverse the styling

iconPosition 'start' | 'end'

Button icon positions can either be start or end. If no value is provided, it defaults to start.

'start'
shouldMirrorIconboolean

If set to true, transform the icon's x-axis to mirror the graphic. Use this if you want to always mirror the icon regardless of the content direction. If the icon should mirror only when in an right-to-left language, use shouldMirrorIconInRTL instead.

false
shouldMirrorIconInRTLboolean

If set to true, transform the icon's x-axis to mirror the graphic when the content direction is rtl. Icons don't have enough context to know if they should be mirrored in all cases. Setting this to true indicates the icon should be mirrored in right-to-left languages.

false
size

There are four button sizes: extraSmall, small, medium, and large. If no size is provided, it will default to medium.

colors

Override default colors of a button. The default will depend on the button type

icon

The icon of the Button. Note: Not displayed at small size

shouldMirrorboolean

If set to true, transform the SVG's x-axis to mirror the graphic. Use this if you want to always mirror the icon regardless of the content direction. If the SVG should mirror only when in an right-to-left language, use shouldMirrorInRTL instead.

false
shouldMirrorInRTLboolean

If set to true, transform the SVG's x-axis to mirror the graphic when the content direction is rtl. Icons don't have enough context to know if they should be mirrored in all cases. Setting this to true indicates the icon should be mirrored in right-to-left languages.

false
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling'; import {mergeStyles} from '@workday/canvas-kit-react/layout'; // ... // `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same // function signature, but adds support for style props. return ( <Element {...handleCsProp(elemProps, [ myStyles, myModifiers({ size: 'medium' }), myVars({ backgroundColor: 'red' }) ])} > {children} </Element> )
colorstring

The color of the SystemIcon. This defines accent and fill. color may be overwritten by accent and fill.

childrenReactNode
accentstring

The accent color of the SystemIcon. This overrides color.

backgroundstring

The background color of the SystemIcon.

fillIconboolean

Whether the icon should received filled (colored background layer) or regular styles. Corresponds to toggled in ToolbarIconButton

growboolean

True if the component should grow to its container's width. False otherwise.

asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

button
refReact.Ref<R = button>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

TertiaryButton

Props

Props extend from button. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
variant'inverse'

Variant has an option for inverse which will inverse the styling

iconPosition 'start' | 'end'

Button icon positions can either be start or end. If no value is provided, it defaults to start.

'start'
shouldMirrorIconboolean

If set to true, transform the icon's x-axis to mirror the graphic. Use this if you want to always mirror the icon regardless of the content direction. If the icon should mirror only when in an right-to-left language, use shouldMirrorIconInRTL instead.

false
shouldMirrorIconInRTLboolean

If set to true, transform the icon's x-axis to mirror the graphic when the content direction is rtl. Icons don't have enough context to know if they should be mirrored in all cases. Setting this to true indicates the icon should be mirrored in right-to-left languages.

false
size

There are four button sizes: extraSmall, small, medium, and large. If no size is provided, it will default to medium.

'medium'
colors

Override default colors of a button. The default will depend on the button type

icon

The icon of the Button. Note: Not displayed at small size

shouldMirrorboolean

If set to true, transform the SVG's x-axis to mirror the graphic. Use this if you want to always mirror the icon regardless of the content direction. If the SVG should mirror only when in an right-to-left language, use shouldMirrorInRTL instead.

false
shouldMirrorInRTLboolean

If set to true, transform the SVG's x-axis to mirror the graphic when the content direction is rtl. Icons don't have enough context to know if they should be mirrored in all cases. Setting this to true indicates the icon should be mirrored in right-to-left languages.

false
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling'; import {mergeStyles} from '@workday/canvas-kit-react/layout'; // ... // `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same // function signature, but adds support for style props. return ( <Element {...handleCsProp(elemProps, [ myStyles, myModifiers({ size: 'medium' }), myVars({ backgroundColor: 'red' }) ])} > {children} </Element> )
colorstring

The color of the SystemIcon. This defines accent and fill. color may be overwritten by accent and fill.

childrenReactNode
accentstring

The accent color of the SystemIcon. This overrides color.

backgroundstring

The background color of the SystemIcon.

fillIconboolean

Whether the icon should received filled (colored background layer) or regular styles. Corresponds to toggled in ToolbarIconButton

growboolean

True if the component should grow to its container's width. False otherwise.

asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

button
refReact.Ref<R = button>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

DeleteButton

Use sparingly for destructive actions that will result in data loss, can’t be undone, or will have significant consequences. They commonly appear in confirmation dialogs as the final confirmation before being deleted.

Props

Props extend from button. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
variant'outline'

Variant has an option for outline which will reverse the styling of the button

iconPosition 'start' | 'end'

Button icon positions can either be start or end. If no value is provided, it defaults to start.

'start'
shouldMirrorIconboolean

If set to true, transform the icon's x-axis to mirror the graphic. Use this if you want to always mirror the icon regardless of the content direction. If the icon should mirror only when in an right-to-left language, use shouldMirrorIconInRTL instead.

false
shouldMirrorIconInRTLboolean

If set to true, transform the icon's x-axis to mirror the graphic when the content direction is rtl. Icons don't have enough context to know if they should be mirrored in all cases. Setting this to true indicates the icon should be mirrored in right-to-left languages.

false
size

There are four button sizes: extraSmall, small, medium, and large. If no size is provided, it will default to medium.

colors

Override default colors of a button. The default will depend on the button type

icon

The icon of the Button. Note: Not displayed at small size

shouldMirrorboolean

If set to true, transform the SVG's x-axis to mirror the graphic. Use this if you want to always mirror the icon regardless of the content direction. If the SVG should mirror only when in an right-to-left language, use shouldMirrorInRTL instead.

false
shouldMirrorInRTLboolean

If set to true, transform the SVG's x-axis to mirror the graphic when the content direction is rtl. Icons don't have enough context to know if they should be mirrored in all cases. Setting this to true indicates the icon should be mirrored in right-to-left languages.

false
cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling'; import {mergeStyles} from '@workday/canvas-kit-react/layout'; // ... // `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same // function signature, but adds support for style props. return ( <Element {...handleCsProp(elemProps, [ myStyles, myModifiers({ size: 'medium' }), myVars({ backgroundColor: 'red' }) ])} > {children} </Element> )
colorstring

The color of the SystemIcon. This defines accent and fill. color may be overwritten by accent and fill.

childrenReactNode
accentstring

The accent color of the SystemIcon. This overrides color.

backgroundstring

The background color of the SystemIcon.

fillIconboolean

Whether the icon should received filled (colored background layer) or regular styles. Corresponds to toggled in ToolbarIconButton

growboolean

True if the component should grow to its container's width. False otherwise.

asReact.ElementType

Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

button
refReact.Ref<R = button>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).