Modal

Modals are a type of interactive pop-up that can contain input fields or informative content.

GitHubStorybook
yarn add @workday/canvas-kit-react
Sources
GitHubStorybook
Install
yarn add @workday/canvas-kit-react

Anatomy

Image of a modal container with annotation markers.

  1. Title (Optional): Titles should display the title of the content or task.
  2. Content: Modals contain many different types of content. Typical types of content include media, alerts, dialogs, and/or task-oriented flows.
  3. Action Bar (Optional): Action should remain pinned at the bottom of the container when being used. When there is a user action, use the action bar. When displaying informational content, use in-line buttons.
  4. Close “X” Icon (Optional): Users must be able to intentionally dismiss a modal. This icon inherits styling and interactions from our Tertiary Icon-Only Button Variant. Use the Close "X" icon functionality for modals with optional inputs, easily dismissed informational content, or on small screens when tapping the background overlay won't exit the modal.
  5. Container: Use 1px Soap 500 Border and Depth 3.

Usage Guidance

  • Modals allow for entry of data on any given page.
  • On all platforms, modals show up similarly, over a darkened background that highlights the card containing the content.
  • Modals are often used to display media, alerts, dialogs, and/or task-oriented flows. Links, buttons, field sets, icons, text inputs, and prompts can all exist within modals.
  • When using an Action Bar with a Modal, action bar buttons should be right aligned for step based flows. For inline buttons used in modal dialogs and non-user input modals, the alignment could be Left (Default), Center, Full Width, or Right aligned.

When to use

  • Use Modals when the user has to input data to populate a portion of the primary page.
  • When alert content and text are too large for a standard Toast or Pop-up notification.
  • To separate portions of data input in a user flow.
  • For step based flows, use the right aligned action bar to move through content within the modal.
  • To surface forms that users may need to fill out more than once.

When to Use Something Else

  • Do not use Modals to serve up easily accessible links or simple messages that can be dismissed quickly (use Toasts or Popups for this).
  • Do not use Modals to display dense information, such as Tables or Multi-View Containers.
  • Consider a Toast if you are communicating status or confirmation of the application process to the user.
  • Consider a Popup if you are simply confirming or checking for validation of inputs or user actions.
  • Consider a Menu if the input is a single selection of options.

Responsive View

Modal components adjust width and content presentation based on screen size. When content exceeds the length of the screen, the modal content will become scrollable in the body section of the modal. For long content on a small screen, action bar buttons are sticky and will persist at the bottom of the modal container view, while inline buttons will continue to scroll with the content.

Touch Based Behavior

The overlay on modals are not click or touch enabled to close the modal component view on small screens between 320-767px. This accounts for accidental touch on mobile devices. Background overlays will close the modal when clicked on larger devices when the screen reaches the minimum width.

Examples

Basic

The basic behavior of a modal is to hide all content from all users that is "behind" the modal dialog.

Without Close Icon

If you wish to remove the close icon button, you can simply omit the Modal.CloseButton subcomponent. If you have a modal dialog that requires the user to accept instead of dismiss though an escape key or clicking outside the modal, you must create a new PopupModel without those behaviors and hand that model to the Modal dialog component.

Custom Focus

By default, the Modal makes sure the first focusable element receives focus when the Modal is opened. Most of the time, this is the Modal.CloseIcon button. If that element isn't present, the Modal will use the Modal Heading to make sure screen reader users have focus near the start of the Modal's content. This allows screen reader users to discover the Modal's content more naturally without having to navigate back up again. Sometimes, it is a better user experience to focus on a different element. The following example shows how initialFocusRef can be used to change which element receives focus when the modal opens.

Return Focus

By default, the Modal will return focus to the Modal.Target element, but it is possible the Modal was triggered by an element that won't exist when the modal is closed. An example might be a Modal that was opened from an Menu item and the act of opening the Modal also closes the Menu, meaning the Menu item can no longer receive focus. The also probably means the Modal.Target component might not suite your needs. The Modal.Target adds both a ref and an onClick. If you provide a returnFocusRef, you only need to worry about the onClick. If you're using a menu, you might need to use a different callback. Calling model.events.show() will show the Modal.

Custom Target

It is common to have a custom target for your modal. Use the as prop to use your custom component. The Modal.Target element will add onClick and ref to the provided component. Your provided target component must forward the onClick to an element for the Modal to open. The as will cause Modal.Target to inherit the interface of your custom target component. This means any props your target requires, Modal.Target now also requires. The example below has a MyTarget component that requires a label prop.

Note: If your application needs to programmatically open a Modal without the user interacting with the target button first, you'll also need to use React.forwardRef in your target component. Without this, the Modal will open at the top-left of the window instead of around the target.

Body Content Overflow

The Modal automatically handles overflowing content inside the Modal.Body element. If contents are larger than the browser's height will allow, the content will overflow with a scrollbar. You may need to restrict the height of your browser to observe the overflow.

Full overlay scrolling

If content is large, scrolling the entire overlay container is an option. Use the Modal.OverflowOverlay component instead of the Modal.Overlay component. The Modal.Card's maxHeight and height will need to be reset to inherit to prevent any internal overflow.

This has the effect of scrolling the heading, close button, and any action buttons. If this type of scrolling behavior is not desired, try the Body Content Overflow method.

Form Modal

The Modal.Card can be turned into a form element to make a form modal. The model should be hoisted to allow for form validation and allow you to control when the modal closes.

Component API

This component is the container component and does not render any semantic elements. It provides a React Context model for the Modal subcomponents. If you manually pass a model to all subcomponents, this container component isn't needed. If you do not pass a model, the Modal container component will build a default one using useModalModel. Modal is a composition of a Popup component and has a similar structure to Popup.

NameTypeDefaultDescription
children*ReactNodeThe contents of the Dialog. Can be `Dialog` children or any valid elements.
returnFocusRefRefObject<any> | undefinedOptional reference to an element that should receive focus when a popup is hidden. If left blank, focus will return to the `targetRef`
initialFocusRefRefObject<any> | undefinedOptional reference to an element that should receive focus when a popup is shown. If left blank, focus will be moved to the first focusable element inside the popup.
idstring | undefined
initialVisibilityVisibility | undefined
onUpdatePlacement(((data: { placement: Placement; }, prevState: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; ... 4 more ...; visibility: Visibility; }) => void) & ((data: { ...; }, prevState: { ...; }) => void)) | undefinedCalled whenever a popup placement changes around a target. This is useful for animations that depend on the placement chosen.
onShow(((data: Event | SyntheticEvent<Element, Event> | undefined, prevState: { stackRef: RefObject<HTMLDivElement>; ... 5 more ...; visibility: Visibility; }) => void) & ((data: Event | ... 1 more ... | undefined, prevState: { ...; }) => void)) | undefined
onHide(((data: Event | SyntheticEvent<Element, Event> | undefined, prevState: { stackRef: RefObject<HTMLDivElement>; ... 5 more ...; visibility: Visibility; }) => void) & ((data: Event | ... 1 more ... | undefined, prevState: { ...; }) => void)) | undefined
shouldUpdatePlacement(((data: { placement: Placement; }, state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; ... 4 more ...; visibility: Visibility; }) => boolean) & ((data: { ...; }, state: { ...; }) => boolean)) | undefinedCalled whenever a popup placement changes around a target. This is useful for animations that depend on the placement chosen.
shouldShow(((data: Event | SyntheticEvent<Element, Event> | undefined, state: { stackRef: RefObject<HTMLDivElement>; ... 5 more ...; visibility: Visibility; }) => boolean) & ((data: Event | ... 1 more ... | undefined, state: { ...; }) => boolean)) | undefined
shouldHide(((data: Event | SyntheticEvent<Element, Event> | undefined, state: { stackRef: RefObject<HTMLDivElement>; ... 5 more ...; visibility: Visibility; }) => boolean) & ((data: Event | ... 1 more ... | undefined, state: { ...; }) => boolean)) | undefined
model({ state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; } & { ...; }) | undefinedOptional 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((<TProps>(model: { state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; }, elemProps: TProps) => any) & (<TProps>(...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.

Modal.Target

The Modal.Target is any element that is meant to show the Modal. The default component rendered by this component is a SecondaryButton element. You can override this by passing the desired component via as. Many examples above use as={DeleteButton}. If you want to render an icon button instead, pass an icon to the the icon prop and pass no children to the button. The Modal.Target is an alias for Popup.Target and uses the usePopupTarget hook, which provides a ref and an onClick. The provided ref will be used to return focus to this element when the Modal is closed. If the provided component does not forward the ref to an element, the fallback is to capture an element in the onClick. This can be overridden by providing a returnFocusRef to the model.

NameTypeDefaultDescription
refReact.Ref<any>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{ state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; } | undefinedOptional 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(<TProps>(model: { state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; }, elemProps: TProps) => any) | undefinedOptional 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.
as"symbol" | "object" | "small" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 156 more ... | React.ComponentType<any>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.forwardRef` and spread extra props to a root element.

Modal.Overlay

The Modal.Overlay is the component that hooks a Modal up to the PopupStack as well as the semi-transparent overlay commonly used with modals. Internally, the Modal.Overlay component uses two div elements to ensure proper rendering of the Modal content. The default element is a div element and can be changed via the as prop.

NameTypeDefaultDescription
refReact.Ref<any>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{ state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; } | undefinedOptional 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(<TProps>(model: { state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; }, elemProps: TProps) => any) | undefinedOptional 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.
as"symbol" | "object" | "small" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 156 more ... | React.ComponentType<any>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.forwardRef` and spread extra props to a root element.

Modal.Card

The Modal.Card is wraps a Popup.Card which wraps a Card. It is the role="dialog" element and is uses useModalCard behavior hook which sets aria-modal="true" and sets the aria-labelledby that points to the id of the Modal.Heading. If you don't use a Modal.Heading, add an aria-label instead. The default element is a div and can be changed via the as prop.

NameTypeDefaultDescription
childrenReactNodeChildren of the Card. Should contain a `<Card.Body>` and an optional `<Card.Heading>`
model({ state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; } & { ...; }) | undefinedOptional 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((<TProps>(model: { state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; }, elemProps: TProps) => any) & (<TProps>(...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.
refReact.Ref<any>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`).
as"symbol" | "object" | "small" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 156 more ... | React.ComponentType<any>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.forwardRef` and spread extra props to a root element.

Modal.Heading

The Modal.Heading semantically labels the Modal via adding an id that the Modal.Card points to via aria-labelledby. If this component is not used, you must add an aria-label to the Modal.Card to label the Modal for screen reader users. This component uses the useModalHeading behavior hook which sets an id and also does some focus management logic for situations where there is no Modal.CloseIcon component used. Please use Modal.Heading and don't use your own unless you also use the useModalHeading hook in your component. Consult accessibility if you cannot use this component. The default element is an h2 and can be changed via the as prop.

NameTypeDefaultDescription
idstring | undefinedThe id of the Card heading. Tie this to an `aria-labelledby` for accessibility.
model({ state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; } & { ...; }) | undefinedOptional 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((<TProps>(model: { state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; }, elemProps: TProps) => any) & (<TProps>(...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.
refReact.Ref<any>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`).
as"symbol" | "object" | "small" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 156 more ... | React.ComponentType<any>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.forwardRef` and spread extra props to a root element.

Modal.CloseIcon

The Modal.CloseIcon is the 'X' icon in the top corner of a Modal. It always requires an aria-label which must be translated. It uses the usePopupCloseIcon which adds an onClick that will close the Modal. The default component rendered is an TertiaryButton with just an icon that can be changed via the as. All props that TertiaryButton takes are also available by default.

NameTypeDefaultDescription
variant"inverse" | undefinedundefinedThe variant of the TertiaryButton.
sizeButtonSizes | undefined'medium'There are three button sizes: `extraSmall`, `small`, and `medium`. If no size is provided, it will default to `medium`.
iconPositionIconPositions | undefined'start'Button icon positions can either be `start` or `end`. If no value is provided, it defaults to `start`.
iconCanvasSystemIcon | undefinedThe icon of the TertiaryButton.
shouldMirrorIconboolean | undefinedfalseIf set to `true`, transform the icon's x-axis to mirror the graphic
allCapsboolean | undefinedundefinedIf set to `true`, transform text to all letters uppercase
isThemeableboolean | undefinedfalseIf set to `true`, make icon button available to use theme colors instead of default
themeEmotionCanvasTheme | undefined
growboolean | undefinedTrue if the component should grow to its container's width. False otherwise.
colorsButtonColors | undefined
fillIconboolean | undefinedWhether the icon should received filled (colored background layer) or regular styles. Corresponds to `toggled` in ToolbarIconButton
refReact.Ref<any>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{ state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; } | undefinedOptional 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(<TProps>(model: { state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; }, elemProps: TProps) => any) | undefinedOptional 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.
as"symbol" | "object" | "small" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 156 more ... | React.ComponentType<any>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.forwardRef` and spread extra props to a root element.

Modal.CloseButton

The Modal.CloseButton is a convenience component that attaches an onClick listener to close the Modal. It uses the usePopupCloseButton behavior hook which adds an onClick that calls model.events.hide(). If you don't use this component, you'll have to add your own onClick and you'll have to hoist the model. The default component rendered is a SecondaryButton and can be changed via the as prop. This component doesn't contain any styles and will take on the styles of the component given to it. For example, as={DeleteButton} will render a delete button. as={TertiaryButton} with no children and an icon will render a TertiaryButton styled icon button. If you give it a base element like as="button", you are responsible for styling the element. You can add your own onClick to perform side effects. Your callback will be merged with the onClick that closes the Modal.

NameTypeDefaultDescription
refReact.Ref<any>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{ state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; } | undefinedOptional 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(<TProps>(model: { state: { stackRef: RefObject<HTMLDivElement>; targetRef: RefObject<HTMLButtonElement>; initialFocusRef: RefObject<any> | undefined; returnFocusRef: RefObject<...> | undefined; placement: Placement; id: string; visibility: Visibility; }; events: { ...; }; }, elemProps: TProps) => any) | undefinedOptional 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.
as"symbol" | "object" | "small" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | ... 156 more ... | React.ComponentType<any>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.forwardRef` and spread extra props to a root element.

Specifications

GivenWhenThen
the Basic story is rendered
    • it should not have any axe errors
    the Basic story is rendered
    • button is focused
    • it should be the focused item on the page
    the Basic story is rendered
    • the target button is clicked
    • it should open the modal
    the Basic story is rendered
    • the target button is clicked
    • it should place the portal as a child of the body element
    the Basic story is rendered
    • the target button is clicked
    • it should hide non-modal content from assistive technology
    the Basic story is rendered
    • the target button is clicked
    • it should not have any axe errors
    the Basic story is rendered
    • the target button is clicked
    • the modal should have a the role of dialog
    the Basic story is rendered
    • the target button is clicked
    • the modal should have an aria-labelledby attribute
    the Basic story is rendered
    • the target button is clicked
    • the modal should have an aria-modal=true
    the Basic story is rendered
    • the target button is clicked
    • the modal should contain the title
    the Basic story is rendered
    • the target button is clicked
    • the modal should be labelled by the title element
    the Basic story is rendered
    • the target button is clicked
    • the modal should transfer focus to the x icon element
    the Basic story is rendered
    • the target button is clicked
    • the modal should trap focus inside the modal element
    the Basic story is rendered
    • the target button is clicked
    • AND THEN clicking inside the modal
    • it should not close the modal
    the Basic story is rendered
    • the target button is clicked
    • AND THEN the close button is clicked
    • it should close the modal
    the Basic story is rendered
    • the target button is clicked
    • AND THEN the close button is clicked
    • it should transfer focus back to the target button
    the Basic story is rendered
    • the target button is clicked
    • AND THEN the Escape key is pressed
    • it should close the modal
    the Basic story is rendered
    • the target button is clicked
    • AND THEN clicking outside the modal
    • it should close the modal
    the With Tooltips story is rendered
    • the modal is open
    • it should open the modal
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Cancel' button is focused
    • it should open the 'Cancel' tooltip
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Cancel' button is focused
    • AND THEN clicking outside the modal
    • it should close the 'Cancel' tooltip
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Cancel' button is focused
    • AND THEN clicking outside the modal
    • it should close the modal
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Hidable Popup' button is clicked
    • it should open the 'Hidable Popup' popup
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Hidable Popup' button is clicked
    • AND THEN the 'OK' button is focused
    • it should open the 'OK' tooltip
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Hidable Popup' button is clicked
    • AND THEN the 'OK' button is focused
    • AND THEN clicking outside the modal
    • it should close the 'OK' tooltip
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Hidable Popup' button is clicked
    • AND THEN the 'OK' button is focused
    • AND THEN clicking outside the modal
    • it should close the 'Hidable Popup' popup
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Hidable Popup' button is clicked
    • AND THEN the 'OK' button is focused
    • AND THEN clicking outside the modal
    • it should keep the modal open
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Non-hidable Popup' button is clicked
    • it should open the 'Non-hidable Popup' popup
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Non-hidable Popup' button is clicked
    • AND THEN the 'OK' button is focused
    • it should open the 'OK' tooltip
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Non-hidable Popup' button is clicked
    • AND THEN the 'OK' button is focused
    • AND THEN clicking outside the modal
    • it should not close the 'Non-hidable Popup' popup
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Non-hidable Popup' button is clicked
    • AND THEN the 'OK' button is focused
    • AND THEN clicking outside the modal
    • it should close the modal
    the With Tooltips story is rendered
    • the modal is open
    • AND THEN the 'Non-hidable Popup' button is clicked
    • AND THEN the 'OK' button is focused
    • AND THEN clicking outside the modal
    • it should close the 'OK' tooltip
    the With Radio buttons story is rendered
      • it should not have any axe errors
      the With Radio buttons story is rendered
        • test trap focus should trap focus inside the modal element
        the Without close icon story is rendered
          • it should not have any axe errors
          the Without close icon story is rendered
          • button is focused
          • it should be the focused item on the page
          the Without close icon story is rendered
          • the target button is clicked
          • it should open the modal
          the Without close icon story is rendered
          • the target button is clicked
          • it should place the portal as a child of the body element
          the Without close icon story is rendered
          • the target button is clicked
          • it should hide non-modal content from assistive technology
          the Without close icon story is rendered
          • the target button is clicked
          • it should not have any axe errors
          the Without close icon story is rendered
          • the target button is clicked
          • it should transfer focus to the header element
          the Without close icon story is rendered
          • the target button is clicked
          • the modal should have a the role of dialog
          the Without close icon story is rendered
          • the target button is clicked
          • the modal should have an aria-labelledby attribute
          the Without close icon story is rendered
          • the target button is clicked
          • the modal should have an aria-modal=true
          the Without close icon story is rendered
          • the target button is clicked
          • the modal should contain the title
          the Without close icon story is rendered
          • the target button is clicked
          • the modal should be labelled by the title element
          the Without close icon story is rendered
          • the target button is clicked
          • the modal should transfer focus to the header element
          the Without close icon story is rendered
          • the target button is clicked
          • the modal should trap focus inside the modal element
          the Without close icon story is rendered
          • the target button is clicked
          • AND THEN the Escape key is pressed
          • it should not close the modal
          the Without close icon story is rendered
          • the target button is clicked
          • AND THEN clicking outside the modal
          • it should not close the modal
          the Custom focus story is rendered
          • button is focused
          • it should be the focused item on the page
          the Custom focus story is rendered
          • the target button is clicked
          • it should open the modal
          the Custom focus story is rendered
          • the target button is clicked
          • the modal should have a the role of dialog
          the Custom focus story is rendered
          • the target button is clicked
          • the modal should have an aria-labelledby attribute
          the Custom focus story is rendered
          • the target button is clicked
          • the modal should have an aria-modal=true
          the Custom focus story is rendered
          • the target button is clicked
          • the modal should contain the title
          the Custom focus story is rendered
          • the target button is clicked
          • the modal should be labelled by the title element
          the Custom focus story is rendered
          • the target button is clicked
          • the modal should transfer focus to the Acknowledge button element
          the Custom focus story is rendered
          • the target button is clicked
          • the modal should trap focus inside the modal element
          the Custom focus story is rendered
          • the target button is clicked
          • AND THEN the Escape key is pressed
          • it should close the modal
          the Custom focus story is rendered
          • the target button is clicked
          • AND THEN clicking outside the modal
          • it should close the modal
          the StackedModals story is rendered
          • both modals are opened
          • it should open the second modal
          the StackedModals story is rendered
          • both modals are opened
          • AND THEN the Escape key is pressed
          • it should close the second modal
          the StackedModals story is rendered
          • both modals are opened
          • AND THEN the Escape key is pressed
          • it should not close the first modal
          the StackedModals story is rendered
          • both modals are opened
          • AND THEN clicking outside the modal
          • it should close the second modal
          the StackedModals story is rendered
          • both modals are opened
          • AND THEN clicking outside the modal
          • it should not close the first modal
          the ModalWithPopup story is rendered
          • both modal and popup are opened
          • it should open the second modal
          the ModalWithPopup story is rendered
          • both modal and popup are opened
          • AND THEN clicking outside the modal
          • it should close the popup
          the ModalWithPopup story is rendered
          • both modal and popup are opened
          • AND THEN clicking outside the modal
          • it should not close the modal
          the CustomTarget example is rendered
          • the "Open" button is clicked
          • it should show the modal
          the CustomTarget example is rendered
          • the "Open" button is clicked
          • AND THEN the "Close" button is clicked
          • it should hide the modal
          the CustomTarget example is rendered
          • the "Open" button is clicked
          • AND THEN the "Close" button is clicked
          • it should move focus back to the "Open" button
          given the 'Iframe Test' story is rendered
          • the modal is opened
          • AND THEN Shift + Tab key is pressed
          • it should focus in the iframe
          given the 'Iframe Test' story is rendered
          • the modal is opened
          • AND THEN Shift + Tab key is pressed
          • it should focus on the last button in the iframe
          Source: Modal.spec.ts

          Content Guidelines

          Can't Find What You Need?

          Check out our FAQ section which may help you find the information you're looking for.

          FAQ Section