Button usage guidelines
Buttons are used to give users a next step or call to action to move them forward in a flow or task.
When to use
Section titled “When to use”- To perform an action
- To close a modal dialog
- To link to the next page in a flow
When not to use
Section titled “When not to use”- Use radio buttons, checkboxes, or toggle buttons when a user must select from a group of options.
- Use tabs to switch between views or sections of content.
- When the action takes a user to a different URL a link should be used instead unless the navigation action is part of a specific form or wizard flow.
Properties
Section titled “Properties”Variant
Section titled “Variant”import { Button, Stack } from '@cimpress-ui/react';
export default function Demo() { return ( <Stack direction="horizontal" gap={16} wrap> <Button variant="primary">Primary</Button> <Button variant="secondary">Secondary</Button> <Button variant="tertiary">Tertiary</Button> </Stack> );}
Value | Use cases |
---|---|
Primary | Primary buttons are reserved for the most important action on the page. There should only be 1 primary button on a given page. This is the most common or most important action the user is taking. |
Secondary (default) | Secondary buttons are used for actions that are important for the user to see but might not be needed or applicable for every user. They can be used when there are multiple actions on a page or for negative actions such as “Cancel”, “Back”, or “Delete”. |
Tertiary | Used for optional actions that require less visual prominence. Should only be used on backgrounds that provide adequate contrast to ensure readability and accessibility. |
import { Button, Stack } from '@cimpress-ui/react';
export default function Demo() { return ( <Stack direction="horizontal" gap={16} align="center" wrap> <Button size="small">Small</Button> <Button size="medium">Medium</Button> <Button size="large">Large</Button> </Stack> );}
Value | Use cases |
---|---|
Small | Small buttons should be used sparingly and are reserved for more compact UI areas. |
Medium (default) | Medium buttons are the default button size in the design system. Medium buttons are the same height as the form components (select, text field, etc.) and should always be used when placed next to form components. |
Large | Use large buttons sparingly. Large buttons should only be used to achieve visual consistency, not for emphasis. |
import { Button, Stack } from '@cimpress-ui/react';
export default function Demo() { return ( <Stack direction="vertical" gap={16}> <Stack direction="horizontal" gap={16} wrap> <Button variant="primary">Primary</Button> <Button variant="secondary">Secondary</Button> <Button variant="tertiary">Tertiary</Button> </Stack> <Stack direction="horizontal" gap={16} wrap> <Button variant="primary" tone="critical"> Primary </Button> <Button variant="secondary" tone="critical"> Secondary </Button> <Button variant="tertiary" tone="critical"> Tertiary </Button> </Stack> </Stack> );}
Value | Use cases |
---|---|
Base (default) | Base buttons should be used for the majority of buttons. They are the standard tone which implies that a button is interactive. |
Critical | Critical buttons are used when the action is destructive (e.g., “Delete”) or is otherwise difficult to reverse. Critical buttons should be used sparingly to warn users of significantly destructive actions and should be limited to one critical button per page. The button label and UI should make it clear what the impact of taking the critical action will be on the user and their data. |
Icon-only button
Section titled “Icon-only button”import { IconButton, Stack } from '@cimpress-ui/react';import { IconAdd } from '@cimpress-ui/react/icons';
export default function Demo() { return ( <Stack direction="horizontal" gap={16}> <IconButton variant="primary" icon={<IconAdd />} aria-label="Add" /> <IconButton variant="secondary" icon={<IconAdd />} aria-label="Add" /> <IconButton variant="tertiary" icon={<IconAdd />} aria-label="Add" /> </Stack> );}
Use extremely sparingly. Icons can be confusing when used for unusual actions or inconsistently, so icon-only buttons should only be used for very common actions like “Edit”, “Delete”, and “Add”.
Formatting and layout
Section titled “Formatting and layout”Placement
Section titled “Placement”Any given page should have one primary action on it. This is the most important action you want users to take so it should stand out and be easily recognizable and discoverable. If there is no primary action and all actions have the same level of importance, the secondary variant should be used because it cuts down on visual noise and doesn’t distract the user from other areas of the page that are more important. See examples below.
Two or three buttons
Section titled “Two or three buttons”When there are two or three buttons grouped together, only one button should be the primary variant. The remaining actions can be tertiary, or if there are different levels of importance, they can be secondary and tertiary.
Buttons of equal importance
Section titled “Buttons of equal importance”When there are multiple buttons of equal importance, they should all use the secondary or tertiary variant depending on how much visual emphasis the buttons need. There should never be two primary buttons next to each other.
Four or more buttons
Section titled “Four or more buttons”If four or more actions need to be grouped together, they should be condensed under a Menu.
Spacing
Section titled “Spacing”- Buttons placed together in groups should have 16px spacing between them.
- Buttons should be placed with at least 8px spacing between the button and other related elements like tables. When possible, use at least 16px spacing, but 8px can be used if the space on the page is tight.
- Buttons should have at least 16px spacing between the button and any unrelated element on the page.
Modal dialog alignment
Section titled “Modal dialog alignment”The primary and secondary actions in a modal dialog are right-aligned. Any tertiary buttons (“Cancel”, etc.) are left-aligned.
Wizard and multi-page flow alignment
Section titled “Wizard and multi-page flow alignment”The “Next” or “Save” button is always right-aligned, and the “Cancel” or “Back” button is always left-aligned. The “Next” or “Save” button should be the primary action in a wizard or multi-page flow.
Form action alignment
Section titled “Form action alignment”Form action buttons are always left-aligned at the bottom of the form, unless it is a wizard with “Next” and “Back” actions. “Save” or “Next” should always be the primary action of a form.
Content writing
Section titled “Content writing”- Do be descriptive, but also concise.
- Instead of saying “Go”, explicitly say where the user will go to, such as “Go to products”.
- If it’s not obvious where a user will navigate back to, say “Back to products” instead of just “Back”.
- Instead of “Add” or “Remove”, include what will be added/removed, for example “Add/remove attribute” or “Add another attribute”.
- Do use sentence case with button labels.
- Do not use long phrases as button labels.
- Use “Back to products” instead of “Go back to where you last came from”.
Behaviors
Section titled “Behaviors”Flexible width
Section titled “Flexible width”The width of a button changes dynamically based on the width of its label. The button width is determined by the component and should not be changed.
Text wrapping
Section titled “Text wrapping”Button labels should never wrap. If you find that your button label is too long, consider changing the phrasing to shorten the label or add additional context in the UI outside of the button.
Loading state
Section titled “Loading state”The button component has a loading state for actions that have longer loading times (1-10 seconds). This is the standard method of showing that an action is loading or being processed so that users know something is happening.
import { Button } from '@cimpress-ui/react';import { useEffect, useState } from 'react';
/** Generate a random loading time between 1-10 seconds. */function generateLoadingTime(): number { return Math.random() * (10_000 - 1_000) + 1_000;}
export default function Demo() { const [isLoading, setIsLoading] = useState(false);
useEffect(() => { const timeout = isLoading ? setTimeout(() => setIsLoading(false), generateLoadingTime()) : undefined;
return () => { clearTimeout(timeout); }; }, [isLoading]);
return ( <Button onPress={() => setIsLoading(true)} isLoading={isLoading} loadingLabel="Loading for example purposes"> Start loading (1-10s) </Button> );}