Workday Canvas

Action Bar

Action Bars contain primary and secondary actions related to a page or task.

v14.2.34
Install
yarn add @workday/canvas-kit-react

Anatomy

Image of a Action Bar with one primary button, two secondary buttons and an Icon Button.

  1. Primary Button: A button that is discoverable and used as the most important action to take on a page.
  2. Secondary Button: A button or set of buttons that is less important than the Primary Button.
  3. Overflow Menu: An Icon-Only Secondary Button Variant with an Ellipsis Icon used for responsive screens or small page width to show more actions.
  4. Container Bar: The Container Bar is used to house action buttons and is anchored at the bottom of the screen.

Usage Guidance

  • Primary Buttons should only be used once per screen. If there are other buttons on screen, use the Secondary or Tertiary Buttons. However, Tertiary Buttons should not be on the Action Bar unless it’s in the Overflow Menu.
  • Action Bars are placed at the bottom of the screen, and will stick as the user scrolls.
  • Although actions may change, the placement of the Action Bar should persist until the task is successfully submitted.
  • Action Bars can contain up to 3 actions and an Overflow Menu when appropriate.
  • If there are more than 3 actions, hide the 4th and other remaining actions in an Overflow Menu that is launched by clicking the Icon Only Secondary Button Variant.
  • There should be between 1-7 items to choose from in an Overflow Menu.
  • Buttons placed in Action Bars should be grouped logically, either by usage or importance.

When to Use

  • Use Action Bars for tasks that require navigating between pages, saving progress, submitting a task, or cancelling a task.

When to Use Something Else

  • Consider taking a Button outside of the Action Bar if the action is not related to the progress or status of a task.
  • Consider using a Text Button instead of an Action Bar if an action is less popular or less important.

Examples

Basic Example

ActionBar includes a container ActionBar component and the following subcomponent: ActionBar.List which should contains ActionBar.Item.

In a basic example of an ActionBar there are two buttons. The primary action button should be used only once and left aligned if content is left to right, followed by secondary buttons. Tertiary buttons should not be used in the Action Bar.

import {ActionBar} from '@workday/canvas-kit-react/action-bar';
import {PrimaryButton} from '@workday/canvas-kit-react/button';

export default () => {
  return (
    <ActionBar>
      <ActionBar.List position="relative" as="section" aria-label="Action Bar">
        <ActionBar.Item as={PrimaryButton} onClick={() => console.log('first action')}>
          First Action
        </ActionBar.Item>
        <ActionBar.Item>Second Action</ActionBar.Item>
      </ActionBar.List>
    </ActionBar>
  );
};

Icons Example

ActionBar.Item renders a SecondaryButton as default, so it’s possible to use other Button props with ActionBar.Item such as icon or size.

import {ActionBar} from '@workday/canvas-kit-react/action-bar';
import {notificationsIcon, alarmClockIcon} from '@workday/canvas-system-icons-web';
import {PrimaryButton} from '@workday/canvas-kit-react/button';

export default () => {
  return (
    <ActionBar>
      <ActionBar.List position="relative" as="section" aria-label="Action Bar">
        <ActionBar.Item as={PrimaryButton} icon={notificationsIcon}>
          First Action
        </ActionBar.Item>
        <ActionBar.Item icon={alarmClockIcon}>Second Action</ActionBar.Item>
      </ActionBar.List>
    </ActionBar>
  );
};

Delete Action Example

ActionBar.Item is a SecondaryButton by default but it’s posible to change it to another element, such as DeleteButton, by using as prop.

import {ActionBar} from '@workday/canvas-kit-react/action-bar';
import {DeleteButton} from '@workday/canvas-kit-react/button';

export default () => {
  return (
    <ActionBar>
      <ActionBar.List position="relative" as="section" aria-label="Action Bar">
        <ActionBar.Item as={DeleteButton}>Delete Action</ActionBar.Item>
        <ActionBar.Item>Second Action</ActionBar.Item>
      </ActionBar.List>
    </ActionBar>
  );
};

Overflow Example

ActionBar container can contain up to 3 actions and an Overflow Menu if there are more than 3 actions, the other remaining actions should be placed into an Overflow Menu that is launched by clicking the Overflow Button.

Also, ActionBar is a responsive component based on the width of its container. If the rendered actions exceed the width of the ActionBar.List, an overflow menu will be rendered. This only works against the dynamic API where you give the ActionBarModel an array of items to be rendered. The dynamic API handles the React key for you based on the item’s identifier. The dynamic API requires either an id on each item object or a getId function that returns an identifier based on the item. The below example uses an id property on each item.

The dynamic API takes in any object, but since nothing is known about your object, a render prop is necessary to instruct a list how it should render.

Change Action Bar container size

Selected: 100%

import React from 'react';
import {breakpoints} from '@workday/canvas-kit-react/common';
import {ActionBar, useActionBarModel} from '@workday/canvas-kit-react/action-bar';
import {PrimaryButton} from '@workday/canvas-kit-react/button';
import {SegmentedControl} from '@workday/canvas-kit-preview-react/segmented-control';
import {Box} from '@workday/canvas-kit-react/layout';

type MyActionItem = {
  id: string;
  text: React.ReactNode;
};

export default () => {
  const [items] = React.useState<MyActionItem[]>([
    {id: 'first', text: 'First Action'},
    {id: 'second', text: 'Second Action'},
    {id: 'third', text: 'Third Action'},
    {id: 'fourth', text: 'Fourth Action'},
    {id: 'fifth', text: 'Fifth Action'},
  ]);

  const model = useActionBarModel({items});
  const [containerWidth, setContainerWidth] = React.useState<string | number>('100%');

  return (
    <div>
      <Box maxWidth={containerWidth} marginBottom="xl">
        <ActionBar model={model}>
          <ActionBar.List
            position="relative"
            as="section"
            aria-label="Action Bar"
            overflowButton={<ActionBar.OverflowButton aria-label="More actions" />}
          >
            {(item: MyActionItem, index) => (
              <ActionBar.Item
                as={index === 0 ? PrimaryButton : undefined}
                onClick={() => console.log(item.id)}
              >
                {item.text}
              </ActionBar.Item>
            )}
          </ActionBar.List>
          <ActionBar.Menu.Popper>
            <ActionBar.Menu.Card maxWidth={300} maxHeight={200}>
              <ActionBar.Menu.List>
                {(item: MyActionItem) => (
                  <ActionBar.Menu.Item onClick={() => console.log(item.id)}>
                    {item.text}
                  </ActionBar.Menu.Item>
                )}
              </ActionBar.Menu.List>
            </ActionBar.Menu.Card>
          </ActionBar.Menu.Popper>
        </ActionBar>
      </Box>
      <footer>
        <h4>Change Action Bar container size</h4>
        <SegmentedControl onSelect={data => setContainerWidth(data.id)}>
          <SegmentedControl.List role="group" aria-label="container width control" marginBottom="m">
            <SegmentedControl.Item data-id="100%">100%</SegmentedControl.Item>
            <SegmentedControl.Item data-id={`${breakpoints.m}px`}>Small</SegmentedControl.Item>
            <SegmentedControl.Item data-id="420px">420px</SegmentedControl.Item>
            <SegmentedControl.Item data-id={`${breakpoints.s}px`}>
              Extra Small
            </SegmentedControl.Item>
          </SegmentedControl.List>
        </SegmentedControl>
        <p>Selected: {containerWidth}</p>
      </footer>
    </div>
  );
};

The number of visible buttons can also be adjusted by using the model’s maximumVisible attribute. You can change it from the default of 3 to any number greater than 1 and less than items.length.

import React from 'react';
import {ActionBar} from '@workday/canvas-kit-react/action-bar';

type MyActionItem = {
  id: string;
  text: React.ReactNode;
};

export default () => {
  const [items] = React.useState<MyActionItem[]>([
    {id: 'view', text: 'View'},
    {id: 'edit', text: 'Edit'},
    {id: 'delete', text: 'Delete'},
  ]);

  return (
    <ActionBar items={items} maximumVisible={2}>
      <ActionBar.List
        as="section"
        aria-label="Custom button count overflow example"
        position="relative"
        overflowButton={<ActionBar.OverflowButton aria-label="More actions" />}
      >
        {(item: MyActionItem) => (
          <ActionBar.Item onClick={() => console.log(item.id)}>{item.text}</ActionBar.Item>
        )}
      </ActionBar.List>
      <ActionBar.Menu.Popper>
        <ActionBar.Menu.Card>
          <ActionBar.Menu.List>
            {(item: MyActionItem) => (
              <ActionBar.Menu.Item onClick={() => console.log(item.id)}>
                {item.text}
              </ActionBar.Menu.Item>
            )}
          </ActionBar.Menu.List>
        </ActionBar.Menu.Card>
      </ActionBar.Menu.Popper>
    </ActionBar>
  );
};

Accessibility

Grouping the actions into an HTML <section> element with an aria-label string is recommended. This can be useful for helping screen reader users quickly jump down to the actions at the bottom of a page.

Refer to Button and Menus for more information about accessibiliy of these components in the Action Bar.

Component API

ActionBar

ActionBar is a container component that is responsible for creating an {@link ActionBarModel } and sharing it with its subcomponents using React context. It does not represent a real element.

<ActionBar items={[]}>{Child components}</ActionBar>

Alternatively, you may pass in a model using the hoisted model pattern.

const model = useActionBarModel({
  items: [],
});

<ActionBar model={model}>{Child components}</ActionBar>;

Props

Props extend from . If a model is passed, props from ActionBarModelConfig are ignored.

NameTypeDescriptionDefault
childrenReactNode

The contents of the ActionBar. Can be ActionBar children or any valid elements.

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

ActionBar.List

ActionBar.List is a {@link Flex } element. It is a container for subcomponents. To render an overflow button for ActionBar with overflow behavior overflowButton prop with overflow button component as a value should be passed.

// without overflow
<ActionBar.List>{ActionBar.Items}</ActionBar.List>

// with overflow
<ActionBar.List overflowButton={<ActionBar.OverflowButton aria-label="More actions"/>}>
  {ActionBar.Items}
</ActionBar.List>

Layout Component

ActionBar.List supports all props from thelayout component.

Props

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

NameTypeDescriptionDefault
children ((
    item: T,
    index: number
  ) => ReactNode)
ReactNode

If items are passed to a ActionBarModel, the child of ActionBar.List should be a render prop. The List will determine how and when the item will be rendered.

overflowButtonReactNode

ActionBar.List will render overflow button component if it's passed in overflowButton.

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 {@link mergeStyles } 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>
)
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.

div
refReact.Ref<R = div>

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).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useOverflowListMeasure

This elemProps hook measures a list and reports it to an OverflowListModel. This is used in overflow detection.

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  ref: (instance:  null) => void;
}

ActionBar.Item

ActionBar.Item is a button element, by default it's a SecondaryButton unless an as prop is passed.

<ActionBar.Item as={PrimaryButton} onClick={() => console.log('first action')}>
  First Action
</ActionBar.Item>

Props

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

NameTypeDescriptionDefault
childrenReactNode

The contents of the action item. This will be the accessible name of the action for screen readers.

<ActionBar.Item>First Action</ActionBar.Item>
data-idstring

The identifier of the action. This identifier will be used for correct overflow behavior. If this property is not provided, it will default to a string representation of the the zero-based index of the Item when it was initialized.

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.

refReact.Ref<R = >

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).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useActionBarItem

(
  ,
  
)

ActionBar.OverflowButton

Layout Component

ActionBar.OverflowButton supports all props from thelayout component.

Props

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

NameTypeDescriptionDefault
aria-labelstring
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

fillstring

The fill color of the SystemIcon. This overrides color.

backgroundstring

The background color of the SystemIcon.

colorstring

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

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 {@link mergeStyles } 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>
)
childrenReactNode
accentstring

The accent color of the SystemIcon. This overrides color.

accentHoverstring

The accent color of the SystemIcon on hover. This overrides colorHover.

backgroundHoverstring

The background color of the SystemIcon on hover.

colorHoverstring

The hover color of the SystemIcon. This defines accentHover and fillHover. colorHover may be overwritten by accentHover and fillHover.

fillHoverstring

The fill color of the SystemIcon on hover. This overrides colorHover.

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).

model

Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context.

elemPropsHook(
  model: ,
  elemProps: TProps
) => HTML Attributes

Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one.

useActionBarOverflowButton

(
  (
    model: ,
    elemProps: {},
    ref: React.Ref
  ) => {
    aria-haspopup: true;
  },
  ,
  (
    (model: ) => ,
    
  )
)

ActionBar.Menu

Basic type information:

Menu

Model

useActionBarModel

useActionBarModel (config: ):

Content Guidelines

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.

On this Page: