Button
Buttons highlight actions available on a screen.
Anatomy

- Container (Conditional): Houses the contents of the Button. Visual appearance differs based on button type.
- Label (Conditional): Specific text describing the action. Refer to the Buttons and Calls to Action section of the Content Style Guide.
- 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. Read more about non-text content.
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 {
plusIcon,
relatedActionsVerticalIcon,
caretDownIcon,
} from '@workday/canvas-system-icons-web';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
const parentContainerStyles = createStyles({
gap: system.space.x4,
padding: system.space.x4,
});
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 blueberry400.
import React from 'react';
import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {
plusIcon,
relatedActionsVerticalIcon,
caretDownIcon,
} from '@workday/canvas-system-icons-web';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
const parentContainerStyles = createStyles({
gap: system.space.x4,
backgroundColor: system.color.bg.primary.default,
padding: system.space.x4,
});
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 {
plusIcon,
relatedActionsVerticalIcon,
caretDownIcon,
} from '@workday/canvas-system-icons-web';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
const parentContainerStyles = createStyles({
gap: system.space.x4,
padding: system.space.x4,
});
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 blueberry400.
import React from 'react';
import {SecondaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {
plusIcon,
relatedActionsVerticalIcon,
caretDownIcon,
} from '@workday/canvas-system-icons-web';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
const parentContainerStyles = createStyles({
gap: system.space.x4,
padding: system.space.x4,
backgroundColor: system.color.bg.primary.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 {
plusIcon,
relatedActionsVerticalIcon,
caretDownIcon,
} from '@workday/canvas-system-icons-web';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
const parentContainerStyles = createStyles({
gap: system.space.x4,
padding: system.space.x4,
});
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 blueberry400.
import React from 'react';
import {TertiaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
import {
plusIcon,
relatedActionsVerticalIcon,
caretDownIcon,
} from '@workday/canvas-system-icons-web';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
const parentContainerStyles = createStyles({
gap: system.space.x4,
padding: system.space.x4,
backgroundColor: system.color.bg.primary.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 {trashIcon} from '@workday/canvas-system-icons-web';
import {createStyles} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
const parentContainerStyles = createStyles({
gap: system.space.x4,
padding: system.space.x4,
});
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>
);
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 React from 'react';
import {
DeleteButton,
PrimaryButton,
SecondaryButton,
TertiaryButton,
} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';
export default () => (
<Flex gap="s" padding="s" flexDirection="column" maxWidth={300}>
<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 {buttonStencil, PrimaryButton, PrimaryButtonProps} from '@workday/canvas-kit-react/button';
import {Grid} from '@workday/canvas-kit-react/layout';
import {plusIcon} from '@workday/canvas-system-icons-web';
import {createComponent} from '@workday/canvas-kit-react/common';
import {systemIconStencil} from '@workday/canvas-kit-react/icon';
import {createStencil, createStyles, px2rem} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';
const customContainer = createStyles({
gap: system.space.x4,
maxWidth: 'max-content',
});
const myButtonStencil = createStencil({
base: {
[buttonStencil.vars.background]: system.color.static.green.soft,
[buttonStencil.vars.label]: system.color.static.green.strong,
[systemIconStencil.vars.color]: system.color.static.green.strong,
[buttonStencil.vars.borderRadius]: system.shape.half,
border: `${px2rem(3)} solid transparent`,
'&:focus-visible': {
[buttonStencil.vars.background]: system.color.static.green.strong,
[buttonStencil.vars.boxShadowInner]: system.color.static.green.soft,
[buttonStencil.vars.boxShadowOuter]: system.color.static.green.strong,
[systemIconStencil.vars.color]: system.color.icon.inverse,
},
'&:hover': {
[buttonStencil.vars.background]: system.color.static.green.default,
border: `${px2rem(3)} dotted ${system.color.static.green.strong}`,
[systemIconStencil.vars.color]: system.color.static.green.strong,
[systemIconStencil.vars.color]: system.color.icon.inverse,
},
'&:active': {
[buttonStencil.vars.background]: system.color.static.green.strong,
[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.space.x4,
textTransform: 'uppercase',
[buttonStencil.vars.background]: system.color.static.gray.soft,
[buttonStencil.vars.label]: system.color.static.gray.strong,
[systemIconStencil.vars.color]: system.color.static.gray.strong,
[buttonStencil.vars.borderRadius]: system.shape.x2,
[buttonStencil.vars.border]: system.color.static.gray.stronger,
'&:focus-visible': {
[buttonStencil.vars.background]: system.color.static.gray.strong,
[buttonStencil.vars.boxShadowInner]: system.color.static.gray.soft,
[buttonStencil.vars.boxShadowOuter]: system.color.static.gray.strong,
[systemIconStencil.vars.color]: system.color.icon.inverse,
},
'&:hover': {
[buttonStencil.vars.background]: system.color.static.gray.default,
[buttonStencil.vars.border]: `${px2rem(3)} dotted ${system.color.static.gray.strong}`,
[systemIconStencil.vars.color]: system.color.static.gray.strong,
[systemIconStencil.vars.color]: system.color.icon.inverse,
border: `${px2rem(3)} dotted ${system.color.static.gray.strong}`,
},
'&:active': {
[buttonStencil.vars.background]: system.color.static.gray.strong,
[buttonStencil.vars.label]: system.color.fg.inverse,
[systemIconStencil.vars.color]: system.color.fg.inverse,
},
});
const customColors = {
default: {
background: system.color.static.amber.soft,
icon: system.color.static.amber.strong,
label: system.color.static.amber.strong,
},
focus: {
background: system.color.static.amber.strong,
boxShadowInner: system.color.static.amber.soft,
boxShadowOuter: system.color.static.amber.strong,
},
hover: {
background: system.color.static.amber.default,
icon: system.color.icon.inverse,
},
active: {
background: system.color.static.amber.strong,
},
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:rootCSS will override allPrimaryButtontheme colors set at theCanvasProviderlevel.
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 {Flex} from '@workday/canvas-kit-react/layout';
import {
plusIcon,
relatedActionsVerticalIcon,
caretDownIcon,
} from '@workday/canvas-system-icons-web';
import {createStyles} from '@workday/canvas-kit-styling';
import {brand, system} from '@workday/canvas-tokens-web';
import {CanvasProvider} from '@workday/canvas-kit-react/common';
import {Heading} from '@workday/canvas-kit-react/text';
const parentContainerStyles = createStyles({
gap: system.space.x4,
padding: system.space.x4,
});
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
Our button components render semantic HTML <button> elements to the browser DOM. This means that
ARIA roles won’t be necessary in most cases, and onClick listeners will automatically support the
Enter and Space keys for keyboard interactions.
Button Pattern | APG | WAI | W3C
- An
aria-labelis only necessary for icon-only buttons in most cases. Using Canvas Kit’s tooltip component will handle this for you, and all users will be able to see the label for the button. - When button designs have 2 toggle states, an
aria-pressed={true | false}property is required for screen reader support. For example, see Canvas Kit’s Segmented Control component. - When buttons have an attached menu, an
aria-haspopup="true"property is required. Using Canvas Kit’s Menu component will handle this for you. - The icons used in text buttons are decorative in most cases and include ARIA
role="presentation"andfocusable="false". In some special cases where an icon does add meaning, you may be required to change theroleand add anaria-labelto the icon for equivalent screen reader support.
Disabled Buttons
- Disabled buttons use the
disabledattribute, removing them from the tab order. - Disabled styling is exempt from WCAG contrast requirements.
Screen Reader Experience
- Button text content is announced along with the button role (e.g., “Primary, button”).
- Icon-only buttons announce the
aria-labelvalue along with the button role. - Toggle buttons announce their pressed/unpressed state (e.g., “Activity Stream, toggle button, pressed” and check out the Segmented Control component).
Touch Target Size
- All buttons meet the minimum 24px by 24px touch target size requirement for mobile accessibility.
- Button padding ensures adequate spacing between interactive elements to prevent accidental activation.
Button Groups
- Related buttons can be grouped together with HTML unordered list elements or with
<fieldset>and<legend>elements. This can help give additional context to screen readers about the purpose of the group.
Component API
PrimaryButton
Layout Component
PrimaryButton supports all props from thelayout component.
Props
Props extend from button. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
variant | 'inverse' | Variant has an option for | |
iconPosition | 'start' | 'end' | Button icon positions can either be | 'start' |
shouldMirrorIcon | boolean | If set to | false |
shouldMirrorIconInRTL | boolean | If set to | false |
size | | There are four button sizes: | |
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 | |
fill | string | The fill color of the SystemIcon. This overrides | |
background | string | The background color of the SystemIcon. | |
color | string | The color of the SystemIcon. This defines | |
shouldMirror | boolean | If set to | false |
shouldMirrorInRTL | boolean | If set to | false |
cs | | The | |
children | ReactNode | ||
accent | string | The accent color of the SystemIcon. This overrides | |
accentHover | string | The accent color of the SystemIcon on hover. This overrides | |
backgroundHover | string | The background color of the SystemIcon on hover. | |
colorHover | string | The hover color of the SystemIcon. This defines | |
fillHover | string | The fill color of the SystemIcon on hover. This overrides | |
fillIcon | boolean | Whether the icon should received filled (colored background layer) or regular styles.
Corresponds to | |
grow | boolean | True if the component should grow to its container's width. False otherwise. | |
as | React.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 Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | button |
ref | React.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 |
SecondaryButton
Layout Component
SecondaryButton supports all props from thelayout component.
Props
Props extend from button. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
variant | 'inverse' | Variant has an option for | |
iconPosition | 'start' | 'end' | Button icon positions can either be | 'start' |
shouldMirrorIcon | boolean | If set to | false |
shouldMirrorIconInRTL | boolean | If set to | false |
size | | There are four button sizes: | |
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 | |
fill | string | The fill color of the SystemIcon. This overrides | |
background | string | The background color of the SystemIcon. | |
color | string | The color of the SystemIcon. This defines | |
shouldMirror | boolean | If set to | false |
shouldMirrorInRTL | boolean | If set to | false |
cs | | The | |
children | ReactNode | ||
accent | string | The accent color of the SystemIcon. This overrides | |
accentHover | string | The accent color of the SystemIcon on hover. This overrides | |
backgroundHover | string | The background color of the SystemIcon on hover. | |
colorHover | string | The hover color of the SystemIcon. This defines | |
fillHover | string | The fill color of the SystemIcon on hover. This overrides | |
fillIcon | boolean | Whether the icon should received filled (colored background layer) or regular styles.
Corresponds to | |
grow | boolean | True if the component should grow to its container's width. False otherwise. | |
as | React.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 Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | button |
ref | React.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 |
TertiaryButton
Layout Component
TertiaryButton supports all props from thelayout component.
Props
Props extend from button. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
variant | 'inverse' | Variant has an option for | |
iconPosition | 'start' | 'end' | Button icon positions can either be | 'start' |
shouldMirrorIcon | boolean | If set to | false |
shouldMirrorIconInRTL | boolean | If set to | false |
size | | There are four button sizes: | '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 | |
fill | string | The fill color of the SystemIcon. This overrides | |
background | string | The background color of the SystemIcon. | |
color | string | The color of the SystemIcon. This defines | |
shouldMirror | boolean | If set to | false |
shouldMirrorInRTL | boolean | If set to | false |
cs | | The | |
children | ReactNode | ||
accent | string | The accent color of the SystemIcon. This overrides | |
accentHover | string | The accent color of the SystemIcon on hover. This overrides | |
backgroundHover | string | The background color of the SystemIcon on hover. | |
colorHover | string | The hover color of the SystemIcon. This defines | |
fillHover | string | The fill color of the SystemIcon on hover. This overrides | |
fillIcon | boolean | Whether the icon should received filled (colored background layer) or regular styles.
Corresponds to | |
grow | boolean | True if the component should grow to its container's width. False otherwise. | |
as | React.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 Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | button |
ref | React.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 |
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.
Layout Component
DeleteButton supports all props from thelayout component.
Props
Props extend from button. Changing the as prop will change the element interface.
| Name | Type | Description | Default |
|---|---|---|---|
iconPosition | 'start' | 'end' | Button icon positions can either be | 'start' |
shouldMirrorIcon | boolean | If set to | false |
shouldMirrorIconInRTL | boolean | If set to | false |
size | | There are four button sizes: | |
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 | |
fill | string | The fill color of the SystemIcon. This overrides | |
background | string | The background color of the SystemIcon. | |
color | string | The color of the SystemIcon. This defines | |
shouldMirror | boolean | If set to | false |
shouldMirrorInRTL | boolean | If set to | false |
cs | | The | |
children | ReactNode | ||
accent | string | The accent color of the SystemIcon. This overrides | |
accentHover | string | The accent color of the SystemIcon on hover. This overrides | |
backgroundHover | string | The background color of the SystemIcon on hover. | |
colorHover | string | The hover color of the SystemIcon. This defines | |
fillHover | string | The fill color of the SystemIcon on hover. This overrides | |
fillIcon | boolean | Whether the icon should received filled (colored background layer) or regular styles.
Corresponds to | |
grow | boolean | True if the component should grow to its container's width. False otherwise. | |
as | React.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 Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | button |
ref | React.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 |
Specifications
How Buttons Impact the Accessible Experience
When buttons are disabled on the UI, color contrast guidelines do not apply to disabled components. Minimum contrast guidelines set in WCAG 2.1 explicitly state disabled components are exempt from the guideline.
When identical buttons are used repeatedly on a screen, users must correctly identify the context around the buttons that cannot be distinguished from one another.
- For example: Pencil icon buttons used repeatedly on a profile screen, each designed to edit a section of the profile. Providing uniquely descriptive names (e.g. “Edit photo”, “Edit contact info”) for each icon button can be valuable for screen reader users.
When icons are used inside of buttons containing text, a text alternative is only necessary when the icon is communicating something about the button.
- For example: A ‘+’ icon used in a skill pill named “communication” signals an action that is not expressed in the text.
- On the other hand: An icon of an eye used to decorate a “View Details” button is redundant and should be hidden from screen readers.
Content Guidelines
- See the Buttons and Calls to Action page in the UI Text section of the Content Style Guide for button language guidelines.
- When writing Tooltips to pair with icon-only variants, refer to the Tooltips section of the Content Style Guide.
Anatomy

- Container (Conditional): Houses the contents of the Button. Visual appearance differs based on button type.
- Label: Specific text describing the action. Refer to the Buttons and Calls to Action section of the Content Style Guide.
- Icon (Optional): Supplementary visual indicator positioned to the left or right of the label used to promote the purpose of the Button.
Interaction States
Mobile Buttons have the Default/Inactive, Pressed, and Disabled interaction states.

Usage Guidance
- Buttons should indicate an action.
- They should be discoverable, easy to identify, and specific.
- Make Buttons look and feel tappable.
- Adding an icon to the left or right of the label is optional. If used, the icon should signify what the Button does.
- 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 button type is right for your use case.
When to Use Something Else
- Use Hyperlinks within a paragraph to navigate to another page.
Mobile Guidance
- Large Buttons on Mobile have larger typography to increase readability on smaller screens
- Mobile Buttons have reduced horizontal padding to decrease the likelihood of truncated text.
- XS Buttons are not supported on Mobile.
Tap Targets
Mobile Buttons have a minimum tap target height of 48dp to ensure that they are easy to interact with. The entire area of the Button should be tappable. On Medium and Small Size Buttons, an additional tappable top and bottom padding are added to meet this 48dp tappable height requirement. Make sure spacing between Buttons and other UI elements is enough to avoid intersecting tap targets.

Do
Use a minimum tap target of 48dp to ensure the Button is easy to interact with.

Don't
Use a tap target height smaller than 48dp, even if the Button might appear smaller visually.
Icon Placement
Icons can be used within Buttons to help reinforce the meaning of their labels, or to hint as to what tapping on the Button will accomplish.
- No Icon: Used when no icons are needed to reinforce the meaning of the Button or describe interactivity.
- Leading Icon: Icons placed in front of a label are used to reinforce the meaning of the Button label and are purely descriptive. For example, adding a plus icon will reinforce the actions of an “Add” button.
- Trailing Icon: Icons placed to the right of a label are used to hint the interaction to follow after tapping on the Button. For example, a Button with a “Caret Down” icon might open a menu with more options.
- Icon Only: Used for dense environments, or when space is limited on the screen.
Truncation
Button labels should be kept short and concise. Each Button should represent a single action the user can take, never multiple. However, do be mindful if a single action triggers multiple system processes (e.g. “Squash and Merge” closes a branch and moves it to another one in many coding environments).

Do
Try to keep label text concise. If needed, labels can be truncated to avoid wrapping.

Don't
Wrap Button text to the next line, with the exception of dynamic type scaling.
Variations
Primary Button
Primary Buttons are high emphasis. Use minimally to draw attention to the highest priority action. Too many primary buttons make it confusing for the user to understand what action they should take. Not all screens require a Primary Button.
Primary Buttons have three sizes: small, medium, and large. Icons are supported for every size and can be positioned to the left or right.
![]()
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 blueberry400.

Primary Buttons and their inverse variants support the Inactive, Pressed, and Disabled Interaction States.

Secondary Button
Secondary Buttons have a medium level of emphasis. Use them for non-critical actions. Secondary Buttons can be used on most pages without restrictions and work well for multiple actions of equal weight. They can be used in conjunction with a Primary Button or independently.
Secondary Buttons have three sizes: small, medium, and large. Icons are supported for every size and can be positioned to the left or right.
![]()
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 blueberry400.

Secondary Buttons and their inverse variants support the Inactive, Pressed, and Disabled Interaction States.

Tertiary Button
Tertiary Buttons have the lowest emphasis. Use for less important actions that the user may not often be looking to do. Tertiary Buttons have lower prominence as its container is not visible until it is interacted with. Use Tertiary Buttons for supplemental actions such as “View More”, “Read More” or “Select a File”. Tertiary Buttons are frequently used on List Items.
Tertiary Buttons have two sizes on mobile: small, and medium. Icons are supported for every size and can be positioned to the left or right with the iconPosition prop.
![]()
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 blueberry400.

Tertiary Buttons and their inverse variants support the Inactive, Pressed, and Disabled Interaction States.

API Guidelines
Primary, Secondary, and Tertiary Buttons
Methods
// ButtonV2
init(
featureData: FeatureMetricsData,
variant: Variant,
isLoading: Bool = false,
indication: Indication,
size: Size = .medium,
useInvertedTintStyle: Bool = false,
shouldFillHorizontalSpace: Bool = false,
localizer: LocalizationAdapting?,
action: @escaping () -> Void
)Types
enum Variant: Hashable {
case titleOnly(_ title: String)
case titleAndIcon(_ title: String, iconName: String, iconSide: HorizontalEdge)
case iconOnly(iconName: String, accessibilityLabel: String)
}
enum Indication: String, CaseIterable, Hashable {
case primary, secondary, tertiary
}
enum Size: CaseIterable, Hashable {
case large, medium, small
}Parameters
| Name | Description |
|---|---|
featureData | The feature name/context and the screen ID in which the component appears. |
variant | Specifies how the button is displayed: title, icon, or both. |
isLoading | Shows loading dots in place of content, maintaining the size of the hidden content. |
indication | The button’s visual emphasis: primary, secondary, or tertiary. |
size | The size class of the button: small, medium, or large (default is medium). |
useInvertedTintStyle | Provides an alternate appearance for buttons on a dark background. |
shouldFillHorizontalSpace | If true, the button label takes the full width available (defaults to false). |
localizer | A string localizer. |
action | The closure to run when the button is triggered. |
Delete Button
Methods
// DeleteButtonV2
public init(
featureData: FeatureMetricsData,
variant: Variant,
indication: Indication,
size: Size = .medium,
shouldFillHorizontalSpace: Bool = false,
localizer: LocalizationAdapting,
action: @escaping () -> Void
)Types
Delete Button uses the same types as Primary, Secondary, and Tertiary Buttons.
Parameters
| Name | Description |
|---|---|
featureData | The feature name/context and the screen ID in which the component appears. |
variant | Specifies how the button is displayed: title, icon, or both. |
indication | The button’s visual emphasis: primary, secondary, or tertiary. |
size | The size class of the button: small, medium, or large (default is medium). |
shouldFillHorizontalSpace | If true, the button label takes the full width available (defaults to false). |
localizer | A string localizer. |
action | The closure to run when the button is triggered. |
Content Guidelines
- See the Buttons and Calls to Action page in the UI Text section of the Content Style Guide for button language guidelines.
- When writing Tooltips to pair with Icon Buttons, refer to the Tooltips section of the Content Style Guide.
Anatomy

- Container (Conditional): Houses the contents of the Button. Visual appearance differs based on button type.
- Label: Specific text describing the action. Refer to the Buttons and Calls to Action section of the Content Style Guide.
- Icon (Optional): Supplementary visual indicator positioned to the left or right of the label used to promote the purpose of the Button.
Interaction States
Mobile Buttons have the Default/Inactive, Pressed, and Disabled interaction states.

Usage Guidance
- Buttons should indicate an action.
- They should be discoverable, easy to identify, and specific.
- Make Buttons look and feel tappable.
- Adding an icon to the left or right of the label is optional. If used, the icon should signify what the Button does.
- 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 button type is right for your use case.
When to Use Something Else
- Use Hyperlinks within a paragraph to navigate to another page.
Mobile Guidance
- Large Buttons on Mobile have larger typography to increase readability on smaller screens
- Mobile Buttons have reduced horizontal padding to decrease the likelihood of truncated text.
- XS Buttons are not supported on Mobile.
Tap Targets
Mobile Buttons have a minimum tap target height of 48dp to ensure that they are easy to interact with. The entire area of the Button should be tappable. On Medium and Small Size Buttons, an additional tappable top and bottom padding are added to meet this 48dp tappable height requirement. Make sure spacing between Buttons and other UI elements is enough to avoid intersecting tap targets.

Do
Use a minimum tap target of 48dp to ensure the Button is easy to interact with.

Don't
Use a tap target height smaller than 48dp, even if the Button might appear smaller visually.
Icon Placement
Icons can be used within Buttons to help reinforce the meaning of their labels, or to hint as to what tapping on the Button will accomplish.
- No Icon: Used when no icons are needed to reinforce the meaning of the Button or describe interactivity.
- Leading Icon: Icons placed in front of a label are used to reinforce the meaning of the Button label and are purely descriptive. For example, adding a plus icon will reinforce the actions of an “Add” button.
- Trailing Icon: Icons placed to the right of a label are used to hint the interaction to follow after tapping on the Button. For example, a Button with a “Caret Down” icon might open a menu with more options.
- Icon Only: Used for dense environments, or when space is limited on the screen.
Truncation
Button labels should be kept short and concise. Each Button should represent a single action the user can take, never multiple. However, do be mindful if a single action triggers multiple system processes (e.g. “Squash and Merge” closes a branch and moves it to another one in many coding environments).

Do
Try to keep label text concise. If needed, labels can be truncated to avoid wrapping.

Don't
Wrap Button text to the next line, with the exception of dynamic type scaling.
Variations
Primary Button
Primary Buttons are high emphasis. Use minimally to draw attention to the highest priority action. Too many primary buttons make it confusing for the user to understand what action they should take. Not all screens require a Primary Button.
Primary Buttons have three sizes: small, medium, and large. Icons are supported for every size and can be positioned to the left or right.
![]()
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 blueberry400.

Primary Buttons and their inverse variants support the Inactive, Pressed, and Disabled Interaction States.

Secondary Button
Secondary Buttons have a medium level of emphasis. Use them for non-critical actions. Secondary Buttons can be used on most pages without restrictions and work well for multiple actions of equal weight. They can be used in conjunction with a Primary Button or independently.
Secondary Buttons have three sizes: small, medium, and large. Icons are supported for every size and can be positioned to the left or right.
![]()
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 blueberry400.

Secondary Buttons and their inverse variants support the Inactive, Pressed, and Disabled Interaction States.

Tertiary Button
Tertiary Buttons have the lowest emphasis. Use for less important actions that the user may not often be looking to do. Tertiary Buttons have lower prominence as its container is not visible until it is interacted with. Use Tertiary Buttons for supplemental actions such as “View More”, “Read More” or “Select a File”. Tertiary Buttons are frequently used on List Items.
Tertiary Buttons have two sizes on mobile: small, and medium. Icons are supported for every size and can be positioned to the left or right with the iconPosition prop.
![]()
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 blueberry400.

Tertiary Buttons and their inverse variants support the Inactive, Pressed, and Disabled Interaction States.

API Guidelines
Component Definition
@Composable
fun ButtonUiComponent(
modifier: Modifier = Modifier,
enabled: Boolean = true,
size: ButtonSizeConfig = ButtonSizeConfig.Large,
iconConfig: ButtonIconConfig = ButtonIconConfig.NoIcon,
buttonStyle: ButtonStyles = primaryButtonStyle(),
iconPainter: Painter? = null,
contentPadding: PaddingValues = buttonPaddingValues(size, iconConfig),
contentDescription: String = "",
onClick: () -> Unit = {},
content: @Composable RowScope.() -> Unit,
) {Parameters
All undocumented parameters are native Android Compose types that can be found in the developer documentation.
| Name | Type | Default | Description |
|---|---|---|---|
| enabled | Boolean | true | Controls the enabled state of the button. When false, this button will not be clickable. |
| size | ButtonSizeConfig | ButtonSizeConfig.Large | Determines the size of the button using a ButtonSizeConfig enum. |
| iconConfig | ButtonIconConfig | ButtonIconConfig.NoIcon | Determines the position of a provided icon using a ButtonIconConfig. |
| buttonStyle | ButtonStyles | primaryButtonStyle() | Sets colors, border, and content padding based on defined primary, secondary, and tertiary button styles. Custom buttons can be made by using one of the default button styles with the .copy() function. |
| iconPainter | Painter? | null | The icon painter to be used in the button. |
| contentPadding | PaddingValues | largeNoIconPadding | The spacing values to apply internally between the container and the content. |
| contentDescription | String | "" | Content Description for the icon. |
| onClick | () -> Unit | Callback lambda that is executed when the user clicks on the button. |
Content Guidelines
- See the Buttons and Calls to Action page in the UI Text section of the Content Style Guide for button language guidelines.
- When writing Tooltips to pair with Icon Buttons, refer to the Tooltips section of the Content Style Guide.
Can't Find What You Need?
Check out our FAQ section which may help you find the information you're looking for. For further information, contact the #ask-canvas-design or #ask-canvas-kitchannels on Slack.