Dialog

The purpose of a Dialog is to provide actionable messaging and may appear contextually or as a modal. The Dialog adapts to various amounts and types of content. For contextual, non-actionable messaging, consider the Tooltip instead.

  • Install
    npm install @pluralsight/ps-design-system-dialog
  • Import
    import Dialog from '@pluralsight/ps-design-system-dialog'

Examples

In-app example

Dialogs can appear automatically, or be triggered by hover, focus, tap or click.

import Button from '@pluralsight/ps-design-system-button'
import Dialog from '@pluralsight/ps-design-system-dialog'
import { Below } from '@pluralsight/ps-design-system-position'
import React from 'react'
function Example() {
const [isHovered, setHovered] = React.useState(false)
const [isClicked, setClicked] = React.useState(false)
return (
<div className="example-grid--col-3" style={{ height: '150px' }}>
<Below
show={
<Dialog tailPosition={Dialog.tailPositions.topCenter}>Dialog</Dialog>
}
when
>
<Button appearance={Button.appearances.secondary}>Look at me</Button>
</Below>
<Below
show={
<Dialog tailPosition={Dialog.tailPositions.topCenter}>Dialog</Dialog>
}
when={isHovered}
>
<Button
appearance={Button.appearances.secondary}
onMouseEnter={_ => setHovered(true)}
onMouseOut={_ => setHovered(false)}
>
Hover me
</Button>
</Below>
<Below
show={
<Dialog tailPosition={Dialog.tailPositions.topCenter}>Dialog</Dialog>
}
when={isClicked}
>
<Button
appearance={Button.appearances.secondary}
onClick={_ => setClicked(!isClicked)}
>
Click me
</Button>
</Below>
</div>
)
}
export default Example

Tail

Dialogs can be shown with or without a tail (a directional indicator). To make the tail appear, use a Dialog.tailPositions option.

import Button from '@pluralsight/ps-design-system-button'
import Dialog from '@pluralsight/ps-design-system-dialog'
import { P } from '@pluralsight/ps-design-system-text'
import React from 'react'
function Example() {
return (
<div className="example-grid--col-2">
<Dialog disableFocusOnMount>
<ExampleContent />
</Dialog>
<Dialog tailPosition={Dialog.tailPositions.topCenter} disableFocusOnMount>
<ExampleContent />
</Dialog>
</div>
)
}
export default Example
const ExampleContent = _ => (
<div style={{ maxWidth: '300px' }}>
<P>
Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
</P>
<div style={{ textAlign: 'right' }}>
<Button>Primary button</Button>
</div>
</div>
)

Closing

Dialogs may be closed using one of a number of methods: clicking the close button, clicking the overlay (in the case of a modal Dialog), and pressing the escape key. One or all of these methods, if available, will call the onClose function when triggered.

import Button from '@pluralsight/ps-design-system-button'
import Dialog from '@pluralsight/ps-design-system-dialog'
import { P } from '@pluralsight/ps-design-system-text'
import React from 'react'
function Example() {
return (
<div className="example-grid--col-2">
<Dialog disableFocusOnMount>
<ExampleContent />
</Dialog>
<Dialog onClose={_ => alert('Closing')} disableFocusOnMount>
<ExampleContent />
</Dialog>
</div>
)
}
export default Example
const ExampleContent = _ => (
<div style={{ maxWidth: '300px' }}>
<P>
Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore
</P>
<div style={{ textAlign: 'right' }}>
<Button>Primary button</Button>
</div>
</div>
)

A modal Dialog will be shown fullscreen with an overlay behind and positioned in the center of the viewport.

When a modal Dialog (or non-modal Dialog) are shown on the screen, it will take browser focus. In the case of a modal Dialog, the rest of the body of the application will continue to be visible through the translucent overlay. But it should be hidden. To hide it from screenreaders, add an aria-hidden=true attribute to your application's containing node, and make sure Dialog is mounted outside of that node. To hide it from keyboard users, add a tabindex="-1" to that same application node.

import Button from '@pluralsight/ps-design-system-button'
import { colorsBackgroundLight, layout } from '@pluralsight/ps-design-system-core'
import Dialog from '@pluralsight/ps-design-system-dialog'
import { Heading } from '@pluralsight/ps-design-system-text'
import React from 'react'
function Example() {
const [isOpen, setOpen] = React.useState(false)
return (
<>
<div className="app" aria-hidden={isOpen}>
<Button onClick={() => setOpen(!isOpen)}>Open Modal</Button>
</div>
{isOpen && (
<Dialog
modal
onClose={() => setOpen(false)}
aria-label="example dialog"
style={{ zIndex: 1 }}
>
<Heading>
<h2>Lorem ipsum dolor sit amet.</h2>
</Heading>
<div
style={{
background: colorsBackgroundLight[2],
height: '176px'
}}
/>
<div className="buttons">
<Button appearance={Button.appearances.stroke}>Secondary</Button>
<Button>Primary button</Button>
</div>
</Dialog>
)}
<style jsx>{`
.buttons {
display: flex;
justify-content: flex-end;
margin-top: ${layout.spacingLarge};
}
.buttons > button:not(:last-child) {
margin-right: ${layout.spacingMedium};
}
`}</style>
</>
)
}
export default Example

Guidelines

In most cases, dialogs can assume the user to digest the content following a Z-Pattern. Readers will start in the top/left, move horizontally to the top/right and then diagonally to the bottom/left before finishing with another horizontal movement to the bottom/right. By that measure, place your actions at the bottom/right, with the primary action on the right.

Title

Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation

Do

Title

Consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation

Don't

Don’t use modal dialogs when displaying non-critical information that doesn’t need to interrupt a workflow. Consider a dialog interaction which would be less intrusive.

Bookmark added. Undo?
Do

Bookmark added

Oh joy! You have successfully added a new bookmark.

Don't

Be explicit as possible when writing dialog buttons. Use affirmative action text to clearly indicate the outcome of the decision. Material Design

Delete record?

This action cannot be reversed. Are you sure you want to delete this record?

Do

Delete record?

This action cannot be reversed. Are you sure you want to delete this record?

Don't

Accessibility

WCAG 2.1 AA Compliance

100% axe-core tests
Manual audit

WAI-ARIA Patterns: Dialog

Props

Name
Type
Description
Default
aria-label
Required
stringdescription of dialog purpose
disableCloseButtonbooleanremoves close button UIfalse
disableCloseOnEscapebooleanprevents closing Dialog with escape keyfalse
disableCloseOnOverlayClickbooleanprevents clicking modal overlay to close Dialogfalse
disableFocusOnMountbooleanprevents focus the Dialog on renderfalse
modalbooleanmakes Dialog modalfalse
onCloseEvent => voidcallback to be called by various close methods
tailPosition
topLeft | topCenter | topRight | bottomLeft | bottomCenter | bottomRight
positions a tail pointer (from Dialog.tailPositions)
returnFocusbooleanmanage focus; set focus on call where closedtrue