Workday Canvas

Banner

Banners surface important information and feedback to the user about a task, action, or state.

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

Anatomy

Image of an alert and error Banner in its default state.

  1. Icon: Supplementary visual indicator used to distinguish between error and alert Banners.
  2. Label: Total count of all errors and/or alerts on a page.
  3. Action Text (Conditional): Link text that indicates the Banner is actionable. Activating the link opens a list of all errors and alerts on a page. Action text is only available in the full Banner variant and has a default value of View All.
  4. Container: Colored container that houses the error or alert icon, message, and action text. The container can be full or sticky, in which the Banner is to be displayed along the right edge of the page.

Usage Guidance

Banners consist of errors and alerts:

  • Typically appearing in response to user action, errors prevent the user from moving forward in their process until the error is corrected. Common error triggers include failing to enter a value for required fields, entering values in a form that are incompatible, or when user input is not understood.
  • Alerts convey information the user should be aware of to help prevent a future error, but allow the user to proceed without addressing the alert.

When to Use

  • Use Banners to notify users of missteps that happen within a workflow and describe how the user can take appropriate action to resolve them.
  • Banners should bring a user’s attention to problems or mistakes either before they happen, or before the user can move on.

When to Use Something Else

  • Ideally, a design won’t create a scenario that causes the need for a Banner. If you can avoid these scenarios by mentioning information that will help in hint text, or by simplifying your design, always do so.

Do’s and Don’ts

Combine error and alert messages into a single error Banner.

Do

Combine error and alert messages into a single error Banner.

Do not use separate error and alert Banners if there are both errors and alerts on the same page.

Don't

Do not use separate error and alert Banners if there are both errors and alerts on the same page.

Examples

Basic Example

Use the children of Banner.Label to set the main text for the Banner.

import React from 'react';

import {Banner} from '@workday/canvas-kit-react/banner';

export default () => {
  return (
    <Banner onClick={() => console.log('clicked banner')}>
      <Banner.Icon />
      <Banner.Label>3 Warnings</Banner.Label>
      <Banner.ActionText />
    </Banner>
  );
};

Action Text

Use the children of Banner.ActionText to customize the action text contained in the Banner. The text has default value of View All.

import React from 'react';

import {Banner} from '@workday/canvas-kit-react/banner';

export default () => {
  return (
    <Banner>
      <Banner.Icon />
      <Banner.Label>3 Warnings</Banner.Label>
      <Banner.ActionText>Show Details</Banner.ActionText>
    </Banner>
  );
};

Error Type

Set the hasError prop of the Banner to designate the severity of the message presented in the banner. This will change the defualt icon to exclamationCircleIcon.

import {Banner} from '@workday/canvas-kit-react/banner';

export default () => {
  return (
    <Banner hasError={true}>
      <Banner.Icon />
      <Banner.Label>3 Errors</Banner.Label>
      <Banner.ActionText />
    </Banner>
  );
};

Icon Banner

When only using an icon in the Banner, use our Tooltip component to both show a visible text alternative, and assign an aria-label string to the child Banner.

import React from 'react';

import {Banner} from '@workday/canvas-kit-react/banner';
import {Tooltip} from '@workday/canvas-kit-react/tooltip';
import {styled} from '@workday/canvas-kit-react/common';

export default () => {
  return (
    <Tooltip title="Warning">
      <Banner width="4em">
        <Banner.Icon />
      </Banner>
    </Tooltip>
  );
};

Sticky

Set the isSticky prop of the Banner to display it along the right edge of the page. When true, the Banner.ActionText will be hidden. Some basic styles will be applied, but you will still need to manually set the css position value.

import {Box} from '@workday/canvas-kit-react/layout';
import {Banner} from '@workday/canvas-kit-react/banner';
import {styled} from '@workday/canvas-kit-react/common';

const StyledBanner = styled(Banner)({
  position: 'absolute',
  right: 0,
});

export default () => {
  return (
    <Box height={64}>
      <StyledBanner hasError={true} isSticky={true}>
        <Banner.Icon />
        <Banner.Label>3 Errors</Banner.Label>
        <Banner.ActionText />
      </StyledBanner>
    </Box>
  );
};

You can use keyframes to animate the Banner in.

import React from 'react';

import {useTheme} from '@workday/canvas-kit-react/common';
import {Box} from '@workday/canvas-kit-react/layout';
import {loopIcon} from '@workday/canvas-system-icons-web';
import {Banner} from '@workday/canvas-kit-react/banner';
import {
  createStencil,
  createStyles,
  createVars,
  keyframes,
  handleCsProp,
  cssVar,
} from '@workday/canvas-kit-styling';
import {system} from '@workday/canvas-tokens-web';

const containerStyles = createStyles({
  position: 'absolute',
  right: 0,
  overflow: 'hidden',
});
const stickyAnimationVars = createVars('width', 'rerun');
const stickAnimationKeyframes = keyframes({
  '0%': {
    transform: `translateX(${cssVar(stickyAnimationVars.width)})`,
  },
  '100%': {
    transform: `translateX(0 * ${cssVar(stickyAnimationVars.rerun)})`,
  },
});

const stickyAnimationStencil = createStencil({
  base: {
    marginBlock: system.space.x1,
    marginInlineStart: system.space.x1,
    marginInlineEnd: 0,
    animationName: stickAnimationKeyframes,
    animationDuration: '.3s',
    animationTimingFunction: 'ease-out',
  },
});

export default () => {
  const theme = useTheme();
  const bannerRef = React.useRef<HTMLButtonElement>(null);
  const containerRef = React.useRef<HTMLDivElement>(null);
  const [bannerWidth, setBannerWidth] = React.useState(0);

  const [rerun, setRerun] = React.useState(1); // Only needed for demo purposes

  React.useLayoutEffect(() => {
    const width = bannerRef.current.offsetWidth;
    setBannerWidth(theme.canvas.direction === 'rtl' ? width * -1 : width);
  }, [theme.canvas.direction, rerun]);

  return (
    <Box height={64}>
      <div className={containerStyles} ref={containerRef}>
        <div
          key={rerun}
          {...handleCsProp({}, [
            stickyAnimationStencil(),
            stickyAnimationVars({width: `${bannerWidth}px`, rerun: `${rerun}`}),
          ])}
        >
          <Banner
            onClick={() => setRerun(r => r + 1)}
            hasError={true}
            isSticky={true}
            ref={bannerRef}
          >
            <Banner.Icon icon={loopIcon} />
            <Banner.Label>Click to run animation</Banner.Label>
            <Banner.ActionText />
          </Banner>
        </div>
      </div>
    </Box>
  );
};

RefForwarding

Banner supports ref forwarding. It will forward ref to its underlying button element.

import React from 'react';

import {changeFocus} from '@workday/canvas-kit-react/common';
import {Banner} from '@workday/canvas-kit-react/banner';
import {SecondaryButton} from '@workday/canvas-kit-react/button';
import {Flex} from '@workday/canvas-kit-react/layout';

export default () => {
  const bannerRef = React.useRef<HTMLButtonElement>(null);

  const focusBanner = () => {
    changeFocus(bannerRef.current);
  };

  return (
    <Flex flexDirection="column" gap="xs" alignItems="flex-start">
      <Banner ref={bannerRef}>
        <Banner.Icon />
        <Banner.Label>3 Warnings</Banner.Label>
        <Banner.ActionText />
      </Banner>
      <SecondaryButton onClick={focusBanner}>Focus Banner</SecondaryButton>
    </Flex>
  );
};

Right-to-Left (RTL)

Banner supports right-to-left languages when specified in the CanvasProvider theme.

import React from 'react';

import {Box} from '@workday/canvas-kit-react/layout';
import {CanvasProvider, styled} from '@workday/canvas-kit-react/common';
import {Banner} from '@workday/canvas-kit-react/banner';

const StyledStickyBanner = styled(Banner)({
  position: 'absolute',
  right: 0,
});

export default () => {
  return (
    <CanvasProvider dir="rtl">
      <Box height={64}>
        <StyledStickyBanner isSticky={true}>
          <Banner.Icon />
          <Banner.Label>3 אזהרות</Banner.Label>
          <Banner.ActionText />
        </StyledStickyBanner>
      </Box>
    </CanvasProvider>
  );
};

Themed Banners

Banners use the useThemedPalette hook for themeing. By default, your alert theme is used. main will be used for the background, dark for the hover background, and contrast for the text.

import React from 'react';

import {Banner} from '@workday/canvas-kit-react/banner';
import {CanvasProvider, PartialEmotionCanvasTheme} from '@workday/canvas-kit-react/common';
import {colors} from '@workday/canvas-kit-react/tokens';

export default () => {
  const theme: PartialEmotionCanvasTheme = {
    canvas: {
      palette: {
        alert: {
          main: colors.kiwi200,
          dark: colors.kiwi300,
        },
      },
    },
  };

  return (
    <CanvasProvider theme={theme}>
      <Banner>
        <Banner.Icon />
        <Banner.Label>3 Items</Banner.Label>
        <Banner.ActionText />
      </Banner>
    </CanvasProvider>
  );
};

If you set the hasError prop, the banner will use your error theme.

import React from 'react';

import {Banner} from '@workday/canvas-kit-react/banner';
import {CanvasProvider, PartialEmotionCanvasTheme} from '@workday/canvas-kit-react/common';
import {colors} from '@workday/canvas-kit-react/tokens';

export default () => {
  const theme: PartialEmotionCanvasTheme = {
    canvas: {
      palette: {
        error: {
          main: colors.islandPunch500,
          dark: colors.islandPunch600,
          contrast: colors.berrySmoothie100,
        },
      },
    },
  };

  return (
    <CanvasProvider theme={theme}>
      <Banner hasError={true}>
        <Banner.Icon />
        <Banner.Label>3 Items</Banner.Label>
        <Banner.ActionText />
      </Banner>
    </CanvasProvider>
  );
};

Component API

Banner is a container component rendered as a <button> element that is responsible for creating a BannerModel and sharing it with its subcomponents using React context.

<Banner
    isSticky={true}
    hasError={true}
    id='custom-banner-id'
    onClick={() => console.log('clicked banner')}
>
  {Child components}
</Banner>

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

const model = useBannerModel({
  isSticky: true,
  hasError: true,
  id: 'custom-banner-id',
});

return (
  <Banner onClick={() => console.log('clicked banner')} model={model}>
    {Child components}
  </Banner>
);

Banner supports all props from thelayout component.

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

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

NameTypeDescriptionDefault
childrenReactNode

Children of the Banner. Should contain a <Banner.Label> a <Banner.Icon> and an optional <Banner.ActionText>

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.

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.

Banner.Icon

Banner.Icon is a styled {@link SystemIcon }. The icon defaults to exclamationTriangleIcon or exclamationCircleIcon when the model's hasError is true.

<Banner.Icon />

Layout Component

Banner.Icon supports all props from thelayout component.

Props

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

NameTypeDescriptionDefault
icon

Icon to show next to label

size number string

The size of the SystemIcon in px.

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.

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.

span
refReact.Ref<R = span>

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.

useBannerIcon

Adds the necessary props to a Icon component. Used by the Banner.Icon subcomponent

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  icon: ;
  size: 24;
}

Banner.Label

Banner.Label is a div element with flex styles. This component will get an id that will be used for the aria-describedby on the top level <button>.

<Banner.Label>3 Warnings</Banner.Label>

Layout Component

Banner.Label supports all props from thelayout component.

Props

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

NameTypeDescriptionDefault
childrenReactNode

The text of the Banner.

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.

useBannerLabel

Adds the necessary props to a Label component. Used by the Banner.Label subcomponent

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  id: any;
}

Banner.ActionText

Banner.ActionText is a span element. This component will get an id that will be used for the aria-labelledby on the top level <button>. This component will be visually hidden when the model's isSticky prop is set to true.

<Banner.ActionText>Custom call to action</Banner.ActionText>

Layout Component

Banner.ActionTextText supports all props from thelayout component.

Props

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

NameTypeDescriptionDefault
childrenReactNode

The text of the Banner action.

'View All'
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.

span
refReact.Ref<R = span>

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.

useBannerActionText

Adds the necessary props to a ActionText component. Used by the Banner.ActionText subcomponent

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {
  id: any;
}

useBannerModel

useBannerModel (config: ):

Accessibility Guidelines

How Banners Impact the Accessible Experience

Banner components can introduce accessibility barriers to successfully and accurately completing forms when accessibility is neglected. Users must be able to navigate to, and activate, a Banner component without using a mouse or trackpad. Banners must be keyboard focusable in the order they are appearing visually on screen. (Logical, left to right, top to bottom for left to right languages.)

When Banners appear on form submission, or from another explicit action by the user, setting keyboard focus onto the Banner can be a helpful way of guiding the interaction.

When Banners are generated by the system, or when users focus out of form fields, then it is not appropriate to move keyboard focus in these scenarios. This can be very disruptive, and may block users from completing their task.

Keyboard Interaction

Each Banner must have a focus indicator that is highly visible against the background and against the non-focused state. Refer to Accessible Colors for more information.

Keyboard focus must be set to the Banner component when it appears after a form submission, but do not force any focus movements on other events such as blur or change.

Banners must support the following keyboard interactions:

  • Tab: focus the Banner element
  • Enter or Space: activate the Banner element

Screen Reader Interaction

Banners must communicate the following to users:

  • The text displayed inside the Banner
  • The Banner is either an “alert” or an “error”
  • The Banner is an interactive “button” element

Design Annotations Needed

  • Specify the Banner’s error type: Alert or Error
  • Specify the keyboard focus order for the Banner in context of the page
  • Write the text alternative for the Icon when it conveys information to users. Read more about Non-Text Content

Implementation Markup Needed

  • When the Banner Icon requires text alternative, set ARIA role=”img” and an aria-label string describing the Icon.
  • Banner must be rendered in the DOM structure relative to where it is positioned visually on screen for the best keyboard focus accessibility.
  • When a Banner is generated from a user action, set keyboard focus to the Banner.
  • When a Banner is generated by the system, avoid moving the keyboard focus away from users’ context. Instead, use an aria-live region in the DOM to send the Banner message for screen readers to announce in real-time.

Content Guidelines

  • When writing error or alert messages, refer to the Errors and Alerts 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.

On this Page: