Modal Dialog
A Modal Dialog is a secondary window that appears in a layer above the application, to display content that demands user action.
Playground
API Update for visage-core 4.16 and react-visage 4.25:
Modal Dialog has a new, updated API to support our new modal dialog designs. This change is backwards-compatible, and the older API still works -- but it is now deprecated, so please update your Modal Dialogs:
If you are using the React API, there is a new
ModalDialogNav
element that should wrap yourModalDialogCloseButton
(as well as any other elements in the dialog's "top nav", such as a "back" button on a panel).You need to place localized text inside the
ModalDialogCloseButton
that explains what the button does, e.g. "Close". This text will not be visible on screens, but supports accessibility.Any
ModalDialogButtons
should go inside theModalDialogFooter
and not theModalDialogBody.
There is a new option that makes a panel's body be "capped", giving it a maximum width. (In React, this is
bodyWidth="capped"
.) Most panel dialogs should use this option; Gallery and PDC are notable exceptions, since their panels need extra width.All "panel" and "menu" dialogs should use the "pinned" option that pins their footers to the bottom of the panel. In React, this is
<ModalDialogFooter pinned>
.If you are using the vanilla JS API, you now need an empty
stylized-dialog-nav
at the top of the dialog, your dialog's main content should be wrapped instylized-dialog-body
, and your buttons should be wrapped instylized-dialog-footer.
Usage
React
The React ModalDialog
requires 2 props:
isOpen
- whether or not theModalDialog
should be openonRequestDismiss
- a callback function which will be invoked when theModalDialog
wants to be dismissed. This can happen in a number of different ways e.g. user clicked on theModalDialogCloseButton
, user pressed the escape key, user "clicked away"
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialog isOpen={isOpen} onRequestDismiss={() => setIsOpen(false)}><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>My Modal Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Some content inside of the ModalDialog</ModalDialogBody><ModalDialogFooter>Footer is an optional element (usually a "buttons" element withTextbuttons in it)</ModalDialogFooter></ModalDialogContent></ModalDialog></>)}
vanilla
The dialog itself is a <dialog>
tag with the appropriate attributes set on it. It can sit anywhere in the HTML when the page loads; the dialog's code will move it to be a direct child of the <body>
tag when it opens.
The element that launches the dialog must have a data-dialog-show
attribute whose value is the id
of the dialog.
<dialogclass="stylized-dialog"role="dialog"aria-modal="true"aria-labelledby="myExampleTitle"id="myExampleStylizedDialog"><div class="stylized-dialog-nav"></div><div class="stylized-dialog-header"><!-- header is an optional element --><h2 class="stylized-dialog-title" id="myExampleTitle">Dialog Title</h2></div><div class="stylized-dialog-body">Dialog body goes here</div><div class="stylized-dialog-footer"><!-- footer is an optional element -->Footer is an optional element (usually a "buttons" element with Textbuttonsin it)</div></dialog><!-- the element that launches the dialog can be any tag, not just a <button> tag --><button data-dialog-show="myExampleStylizedDialog">Open the dialog</button>
Dialog Buttons
Many Modal Dialogs will have a button or two at the bottom, e.g. "Cancel"/"Confirm". You should render these buttons inside of a Modal Dialog Buttons component, itself inside a Modal Dialog Footer component. This assures that the buttons have the proper amount of space around them.
Most dialogs should use Textbuttons with the "mini" height. Only dialogs that sit at the left or right sides of the window ("panel" or "menu" dialogs) should use standard-height buttons.
Buttons can use whatever width is appropriate for your design; they can use the "full-width" option that makes Textbuttons fill their available width.
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialog isOpen={isOpen} onRequestDismiss={() => setIsOpen(false)}><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>My Modal Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Some content inside of the ModalDialog</ModalDialogBody><ModalDialogFooter><ModalDialogButtons><TextButtonskin="secondary"sizeVariant="mini"onClick={() => setIsOpen(false)}>Cancel</TextButton><TextButton skin="primary" sizeVariant="mini">Confirm</TextButton></ModalDialogButtons></ModalDialogFooter></ModalDialogContent></ModalDialog></>)}
<dialogclass="stylized-dialog"role="dialog"aria-modal="true"aria-labelledby="exampleStylizedDialog1Title"><div class="stylized-dialog-header"><h2 class="stylized-dialog-title" id="exampleStylizedDialog1Title">My Modal Dialog</h2></div><div class="stylized-dialog-body"><p>Some content inside of the Modal Dialog</p></div><div class="stylized-dialog-footer"><div class="stylized-dialog-buttons"><buttonclass="textbutton textbutton-skin-secondary stylized-dialog-close">Cancel</button><button class="textbutton textbutton-skin-primary stylized-dialog-close">OK</button></div></div></dialog>
You can also place labeling text to the left of a textbutton using the "Modal Dialog Buttons Text" sub-component. This sub-component can contain any typography you want, and even a link:
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialog isOpen={isOpen} onRequestDismiss={() => setIsOpen(false)}><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>My Modal Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Some content inside of the ModalDialog</ModalDialogBody><ModalDialogFooter><ModalDialogButtons><ModalDialogButtonsText><Link href="#">Need design help?</Link></ModalDialogButtonsText><TextButton skin="primary" sizeVariant="mini">Save</TextButton></ModalDialogButtons></ModalDialogFooter></ModalDialogContent></ModalDialog></>)}
Panel
The "panel" option turns the dialog into a panel that slides out from the side of the screen.
"panel-right" dialogs slide out from the right side, and will be as tall as the screen. They are used to provide additional detail and/or choices.
"panel-bottom" dialogs slide up from the bottom, and will be as wide as the screen. They are used for messaging, in applications such as Studio and Cart/Checkout.
"panel-top" dialogs slide down from the top, and will be as wide as the screen. They are used for navigation content such as a hidden search form.
Most panel dialogs should use the "pinned" footer (see below) and "capped" width (also see below).
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialogvariant="panel-right"bodyWidth="capped"isOpen={isOpen}onRequestDismiss={() => {setIsOpen(false)}}><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>My Panel Modal Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Content</ModalDialogBody><ModalDialogFooter pinned>Footer</ModalDialogFooter></ModalDialogContent></ModalDialog></>)}
<ModalDialog variant="panel-right">...</ModalDialog>
<dialogclass="stylized-dialog stylized-dialog-panel"role="dialog"aria-modal="true">...</dialog>
Menu
The "menu" option is for left-hand flyout menus, such as the site navigation on mobile devices.
Note that even though the
"menu"
variant currently looks a lot like the"panel-left"
variant, you should prefer to use the"menu"
variant for menu-like content, in case our menu styling diverges from our panel styling in the future.
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialogvariant="menu"bodyWidth="capped"isOpen={isOpen}onRequestDismiss={() => {setIsOpen(false)}}><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>My Menu Modal Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Content</ModalDialogBody><ModalDialogFooter pinned><ModalDialogButtons>Buttons</ModalDialogButtons></ModalDialogFooter></ModalDialogContent></ModalDialog></>)}
<ModalDialog variant="menu">...</ModalDialog>
<dialogclass="stylized-dialogstylized-dialog-panelstylized-dialog-panel-leftstylized-dialog-panel-menu"role="dialog"aria-modal="true">...</dialog>
"Pinned" footer
"Panel" and "Menu" dialogs allow a Modal Dialog Footer to be "pinned" to the bottom of the dialog, always staying visible as the user scrolls through the dialog content. While technically optional, this is now the recommended layout for any panel or menu dialog with a footer.
(Note: some browsers such as Firefox can't support this feature. They will show the footer right below the dialog body, as normal.)
() => {const [isOpen, setIsOpen] = React.useState(false)const tallDivStyles = {height: '120vh',minHeight: '120vh',margin: '10px 0',padding: '2em',background: '#fffafa',border: '2px dashed pink',}return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialogvariant="menu"bodyWidth="capped"isOpen={isOpen}onRequestDismiss={() => {setIsOpen(false)}}><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>My Menu Modal Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogBody><div style={tallDivStyles}>This is a really tall image or something</div><p>And this is a closing paragraph</p></ModalDialogBody><ModalDialogFooter pinned><ModalDialogButtons><TextButton skin="secondary">Cancel</TextButton><TextButton skin="primary">Confirm</TextButton></ModalDialogButtons></ModalDialogFooter></ModalDialogContent></ModalDialog></>)}
<ModalDialogFooter pinned></ModalDialogFooter>
<dialogclass="stylized-dialog stylized-dialog-panel stylized-dialog-panel-pinned"role="dialog"aria-modal="true"><div class="stylized-dialog-footer">...</div></dialog>
"Capped" panels
"Panel" dialogs can set their body width to be capped, limiting how wide they can get. Most panel dialogs will want to use this option, save for those exceptions (as in Gallery or PDC) that have panels with especially wide content.
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialogvariant="panel-right"bodyWidth="capped"isOpen={isOpen}onRequestDismiss={() => {setIsOpen(false)}}><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>My capped Modal Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogBody><p>This is dialog content.</p></ModalDialogBody><ModalDialogFooter pinned><ModalDialogButtons><TextButton skin="secondary">Cancel</TextButton><TextButton skin="primary">Confirm</TextButton></ModalDialogButtons></ModalDialogFooter></ModalDialogContent></ModalDialog></>)}
<dialogclass="stylized-dialogstylized-dialog-panelstylized-dialog-panel-cappedstylized-dialog-panel-pinned"role="dialog"aria-modal="true"aria-labelledby="myExampleHeaderPanelTitle"></dialog>
Panel with a custom nav
A panel dialog may wish to have a custom nav at the top of the panel. This can be done by adding additional elements to the <ModalDialogNav>
element. This can even include placing the dialog's <ModalDialogHeader>
inside the <ModalDialogNav>
.
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialogvariant="panel-right"bodyWidth="capped"isOpen={isOpen}onRequestDismiss={() => setIsOpen(false)}><ModalDialogContent><ModalDialogNav><ControlIcon iconType="arrow-l" /><ModalDialogHeader><ModalDialogTitle>My Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogBody>Some content inside of the ModalDialog</ModalDialogBody><ModalDialogFooter>Footer is an optional element (usually a "buttons" element withTextbuttons in it)</ModalDialogFooter></ModalDialogContent></ModalDialog></>)}
Full Bleed
The "full bleed" option makes the dialog's content touch the dialog's edges by removing the padding around the dialog content.
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialogisOpen={isOpen}onRequestDismiss={() => {setIsOpen(false)}}><ModalDialogContent fullBleed><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>Title</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Body</ModalDialogBody></ModalDialogContent></ModalDialog></>)}
<ModalDialogContent fullBleed>...</ModalDialogContent>
<dialogclass="stylized-dialog stylized-dialog-skin-full-bleed"role="dialog"aria-modal="true">...</dialog>
Takeover
Setting the "takeover" option will cause the dialog to fill the full screen.
Note that the React component spells this "
takeOver
" with a capital "O", as if "takeover" were two words. We're sorry about this; it was an oversight.
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialogisOpen={isOpen}onRequestDismiss={() => {setIsOpen(false)}}takeOver><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>Title</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Body</ModalDialogBody></ModalDialogContent></ModalDialog></>)}
<ModalDialog takeOver>...</ModalDialog>
<dialogclass="stylized-dialog stylized-dialog-takeover"role="dialog"aria-modal="true">...</dialog>
Takeover dialogs can also use the translucent
option, which changes the background color of the dialog to a semi-transparent blue color.
() => {const [isOpen, setIsOpen] = React.useState(false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialogisOpen={isOpen}onRequestDismiss={() => {setIsOpen(false)}}takeOvertranslucent><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>Title</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Body</ModalDialogBody></ModalDialogContent></ModalDialog></>)}
<ModalDialog takeOver translucent>...</ModalDialog>
<dialogclass="stylized-dialogstylized-dialog-takeoverstylized-dialog-takeover-translucent"role="dialog"aria-modal="true">...</dialog>
No close button
The "no close button" option will suppress the "X" close button in the dialog. Your dialog will have to provide some other visible way to close it.
<>{/*{just leave out the <ModalDialogCloseButton /> element}*/}</>
<!-- the vanilla API adds the close button automatically, so you need to explicitly suppress it --><dialogclass="stylized-dialog stylized-dialog-no-close-button"role="dialog"aria-modal="true"></dialog>
Browser History
Sometimes, we want our Modal Dialog to close when the user clicks the browser's "back" button. This is especially important on Android devices where the "back" button is globally available across all apps.
On a mobile device, when a Modal Dialog opens, it may appear to the user as if they've navigated to a new page, because the dialog covers all or most of the screen. In this context, it is natural to assume that the back button will close the dialog.
Therefore, we support a Browser History feature that lets the "back" button close the dialog:
React
We provide a useBrowserHistoryState
hook which is capable of syncing React state-changes with the browsers history stack.
It relies on the fact that you can actually push arbitrary (serializable) data on to the browser's history stack without changing the URL.
So, we're able to serialize and store your state as part of the history stack whenever it changes. Then, when the user interacts with the back/forward/refresh buttons, we can get the new value from the history stack and update it the local React state accordingly.
The usage/signature is very similar to React.useState
. The main difference is that we require a key
in order to identify your state in the browser's history stack.
function useBrowserHistoryState<T>(key: string,defaultValue: T,): [T, React.Dispatch<React.SetStateAction<T>>]
Use it just like you'd use React.useState
and your state-changes will automatically become undo/redo-able via the back/forward buttons and the state will be persisted across refreshes as an added bonus.
Be mindful of where you use this hook. Pushing loads of entries onto the browser's history stack could result in a bad UX if the user wants to make their way back to a previous page and needs to run through all of your states as they repeatedly click the
back
button. In general, only use this hook if your state-changes feel like navigation events.
() => {const [isOpen, setIsOpen] = useBrowserHistoryState('modal-dialog-open', false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialog isOpen={isOpen} onRequestDismiss={() => setIsOpen(false)}><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>My Modal Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Some content inside of the ModalDialog</ModalDialogBody></ModalDialogContent></ModalDialog></>)}
With this code, we will see the following behavior:
<button>
is clicked,setIsOpen(true)
, browser history entry is created with{ 'modal-dialog-open': true }
.back
button is clicked, browser history is updated and there is nomodal-dialog-open
state associated with the now-current history entry, soisOpen
is set tofalse
(the default value).
() => {const [isOpen, setIsOpen] = useBrowserHistoryState('modal-dialog-open', false)return (<><TextButton onClick={() => setIsOpen(true)}>Open</TextButton><ModalDialog isOpen={isOpen} onRequestDismiss={() => setIsOpen(false)}><ModalDialogContent><ModalDialogNav><ModalDialogCloseButton visuallyHiddenLabel="Close" />{/* Close Button label text must be localized! */}</ModalDialogNav><ModalDialogHeader><ModalDialogTitle>My Modal Dialog</ModalDialogTitle></ModalDialogHeader><ModalDialogBody>Some content inside of the ModalDialog</ModalDialogBody></ModalDialogContent></ModalDialog></>)}
vanilla JS
The "data-dialog-enable-browser-history"
attribute allows modal dialogs to be closed with the browser's back button:
<dialogclass="stylized-dialog"role="dialog"aria-modal="true"data-dialog-enable-browser-history="all"></dialog>
Components
ModalDialog
Prop | Type | Default | Description |
---|---|---|---|
isOpen | boolean | required | Whether or not the ModalDialog is open |
onRequestDismiss | () => void | required | Callback invoked when the ModalDialog wants to be dismissed Could happen via Esc key, clicking on the backdrop, clicking on close button, ... |
variant | "menu" | "standard" | "panel-right" | "panel-left" | "panel-bottom" | "panel-top" | "standard" | The visual style of the ModalDialog |
takeOver | boolean | false | Optionally allow the dialog to fill the full screen |
translucent | boolean | false | Makes the background translucent. Should only be used with |
bodyWidth | "standard" | "capped" | "standard" | Width of the dialog body. Some dialog variants allow the body width to be limited (capped) |
allowPinchZoom | boolean | true | Handle zoom/pinch gestures on devices when scroll locking is enabled. |
All other props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
ModalDialogContent
Prop | Type | Default | Description |
---|---|---|---|
fullBleed | boolean | false | Whether or not the content of the ModalDialog should fill all available space |
All other props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
ModalDialogCloseButton
Prop | Type | Default | Description |
---|---|---|---|
visuallyHiddenLabel | ReactNode | required | A localized label which describes the close button to screen-reader users Typically it is a string like "Close" |
All other props are forwarded to the element specified in thecomponent
prop(default: <button/>
)
ModalDialogHeader
ModalDialogHeader
has no props of its own
All props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
ModalDialogTitle
ModalDialogTitle
has no props of its own
All props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
ModalDialogBody
ModalDialogBody
has no props of its own
All props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
ModalDialogButtons
ModalDialogButtons
has no props of its own
All props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
ModalDialogFooter
Prop | Type | Default | Description |
---|---|---|---|
pinned | boolean | false | Whether or not the footer should be pinned to the bottom of the ModalDialog (Only compatible with variant="menu" ModalDialogs) |
All other props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
Guidelines
Designer Guidelines
Avoid dialogs that are so tall that they require scrolling. They make for a poor user experience on small screens such as phones. If the content of the dialog is tall, consider a form of progressive disclosure, such as tabs, or an accordion, or a nested scrollable container. Also consider re-formulating the content so it doesn't need to be so large, or that it can be split across a wizard flow.
Avoid any UX that involves having two modal dialogs open at once, such as a modal dialog that opens another modal dialog. This is a UX anti-pattern, and our modal dialog component was not designed to support it.
Because a modal dialog disables the application beneath it and may interrupt the user's workflow, use it for very important information -- information that when provided could lessen the user's effort, or if it maintains the context of a task, such as editing.
Do not place any SEO-relevant information in a modal dialog, since search engines can't see any information that requires user interaction to view. (Please consult the Organic Search team with any questions.)
Place the primary action button to the right of secondary actions, using primary and secondary button styling (see textbutton guidelines).
Use "mini" buttons on most dialogs. Only use standard-size buttons on "panel" or "menu" dialogs that slide out from the sides.
When adding more than one action button, follow this order: destructive (delete, sign out), dismissive (cancel), affirmative (confirm, sign in).
Best practices state that you should not use a modal dialog in the checkout flow.
Modal dialog content should be focused, and should not involve complex decision-making effort.
Developer Guidelines
The dialog defaults to a max width of 600px (on Medium screens) or 95% of screen width (on smaller screens), but will attempt to stretch to fit its contents.
The dialog's JavaScript code will move the location of the dialog node within the DOM tree, in order to position it properly on the screen and to provide accessibility support. Therefore, you shouldn't rely upon the dialog being able to inherit any CSS from any given ancestor, and you shouldn't use an ancestor selector in your CSS that expects the dialog to have a certain ancestor. Any CSS selectors for the dialog content should only refer to elements within the dialog itself.
Developer Guidelines specific to the vanilla API
The JavaScript file for the dialog should go at the end of the
body
tag, and not in thehead
tag. This will ensure that it smoothly loads its polyfill as needed.All dialogs must have an id attribute on them.
You can specify a different max-width by putting a
data-dialog-max-width
attribute on the dialog, e.g.data-dialog-max-width="1000"
The dialog will be hidden by default. It will be shown when there is a click on an element with a
data-dialog-show
attribute whose value is the id of the dialog. You can also show it by calling the methodshowStylizedDialog()
with the dialog's DOM node as the argument. Once the dialog has been shown, it will trigger ashowStylizedDialog
event. Do not use the nativeshowModal()
orshow()
methods, as these will cause display and functionality errors.The dialog will close when there is a click on any internal element that has class
stylized-dialog-close
on it. You can also close it by calling the methodcloseStylizedDialog()
with the dialog's DOM node as the argument. Do not use the nativeclose()
method. Once the dialog has been closed, it will trigger aclose
event.The dialog does not allow you to change its options or configuration after the dialog has been instantiated.
To have the dialog create an iframe inside it, place three attributes on the dialog:
data-dialog-iframe-url
(the URL of the iframe),data-dialog-iframe-id
(the id of the iframe), anddata-dialog-iframe-title
(the title of the iframe).The iframe will be appended to the end of the dialog's content, so you will likely want to have any of the dialog's buttons be inside the iframe.
While the iframe is loading, the user will see a preloader graphic, replaced by the full dialog once the iframe is ready.
Accessibility Guidelines
If the dialog has an internal title, then the dialog's outermost tag should have an attribute
aria-labelledby
whose value is the id of the title; the React component will do this automatically if there is aModalDialogTitle
component. If the dialog does not have an element that can act as its title, then the outermost tag needs anaria-label
attribute whose value acts as a title for the dialog; the text for this value must be localized, since some browsers will read it to the user.If the dialog has a piece of content that can act as a description of the dialog's contents, then the outermost tag should have an attribute
aria-describedby
whose value is the id of that descriptor element.If you are using the React API, you need to place localized text inside the
ModalDialogCloseButton
that indicates the function of the close button, e.g. "Close". This text will not be visible on screens, but supports accessibility.The dialog will normally place focus onto the close button once the dialog opens. If you are using the "no close button" option, the dialog may attempt to put focus on the first interactive element (button, input field, etc) inside the dialog. If no such element exists at the time the dialog opens, you will need to move focus yourself onto the first interactive element, once one becomes available.
SEO Considerations
Panel dialogs must be rendered on the server, and part of the page's source HTML, to be readable by Googlebot.
Panel dialogs should contain less important content. Since they require an additional click to be seen by users and bots, the content appearing inside them may have less importance for ranking (especially on desktop).