Components

Dialog

Dialog displays content in a layer above the app and requires user interaction to dismiss it. It may appear contextually or as a modal.

Examples #

Import Syntax #

import Dialog from 'mineral-ui/Dialog';

Note

Dialogs normally exist in a layer above the app. All of the following examples except Trigger, Modeless, and Composition are static (they display inline, focus is never set nor trapped, and closing functions are disabled) for illustration purposes.

Basic Usage #

Dialogs should have a brief and descriptive title, present contextual information, and require a user decision or acknowledgment through actions.

<DemoLayout>
  <Dialog
    title="Lorem ipsum dolor sit amet"
    actions={[
      { text: 'Cancel' },
      { text: 'Action' }
    ]}>
    <Text>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
      eiusmod tempor incididunt ut labore et dolore magna aliqua.
    </Text>
  </Dialog>
</DemoLayout>

Alternate Syntax #

Dialogs can contain any children, but are best used with DialogHeader, DialogBody, DialogFooter, DialogTitle, and DialogActions.

Note

If DialogBody is not explicitly defined, all content not wrapped by DialogHeader or DialogFooter will be automatically wrapped by DialogBody. If DialogBody is defined, content not wrapped by DialogHeader or DialogFooter will be ignored.

Additionally, Dialog props, such as title oractions, will take precedence over children.

<DemoLayout>
  <Dialog>
    <DialogHeader>
      <DialogTitle>
        Lorem ipsum dolor sit amet
      </DialogTitle>
    </DialogHeader>
    <DialogBody>
      <Text>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
        eiusmod tempor incididunt ut labore et dolore magna aliqua.
      </Text>
    </DialogBody>
    <DialogFooter>
      <DialogActions>
        <Button size="medium">Cancel</Button>
        <Button size="medium">Action</Button>
      </DialogActions>
    </DialogFooter>
  </Dialog>
</DemoLayout>

Trigger #

Toggle the display of a Dialog with the isOpen prop.

() => {
  class Demo extends Component {
    constructor(props) {
      super(props);

      this.state = {
        isOpen: false
      };

      this.toggleDialog = this.toggleDialog.bind(this);
      this.handleClose = this.handleClose.bind(this);
    }

    toggleDialog() {
      this.setState(prevState => ({
        isOpen: !prevState.isOpen
      }));
    }

    handleClose() {
      this.setState(prevState => ({
        isOpen: false
      }));
    }

    render() {
      const { isOpen } = this.state;

      return (
        <div>
          <Button onClick={this.toggleDialog}>{isOpen ? 'Close' : 'Open' } Dialog</Button>
          <Dialog
            appSelector="#app"
            title="Lorem ipsum dolor sit amet"
            actions={[
              { onClick: this.toggleDialog, text: 'Cancel' },
              { onClick: this.toggleDialog, text: 'Action' }
            ]}
            isOpen={isOpen}
            onClose={this.handleClose}>
            <Text>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </Text>
          </Dialog>
        </div>
      )
    }
  }

  return <Demo />;
}

Title #

Dialog's title can be a simple string or you can pass a DialogTitle to apply a different appearance or element or render non-string content. Note that Dialog automatically passes some props, such as id & variant, to DialogTitle.

<div>
  <DemoLayout>
    <Dialog
      title={<DialogTitle appearance="h3" as="h2">Lorem <em>ipsum</em> dolor sit amet</DialogTitle>}
      actions={[
        { text: 'Cancel' },
        { text: 'Action' }
      ]}>
      <Text>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
        eiusmod tempor incididunt ut labore et dolore magna aliqua.
      </Text>
    </Dialog>
  </DemoLayout>
</div>

Actions #

Dialog's actions prop accepts an array of objects to configure the rendered Buttons. Each object contains the text of the Button as well as any props to apply to that Button.

<DemoLayout>
  <Dialog
    title="Lorem ipsum dolor sit amet"
    actions={[
      { text: 'Cancel' },
      { text: 'Continue', variant: 'success', disabled: true }
    ]}>
    <FormField label="Lorem ipsum" input={TextInput} required />
  </Dialog>
</DemoLayout>

Close Button #

The showCloseButton prop adds a button to the end of DialogHeader which closes the Dialog on click.

<DemoLayout>
  <Dialog
    showCloseButton
    title="Lorem ipsum dolor sit amet"
    actions={[
      { text: 'Cancel' },
      { text: 'Action' }
    ]}>
    <Text>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
      eiusmod tempor incididunt ut labore et dolore magna aliqua.
    </Text>
  </Dialog>
</DemoLayout>

Sizes #

Dialog can be rendered in various sizes (max-height, max-width, & width) with the size prop.

() =>
['small', 'medium', 'large'].map(size => (
  <DemoLayout key={size}>
    <Dialog
      size={size}
      title="Lorem ipsum dolor sit amet"
      actions={[
        { text: 'Cancel' },
        { text: 'Action' }
      ]}>
      <Text>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
        eiusmod tempor incididunt ut labore et dolore magna aliqua.
      </Text>
    </Dialog>
  </DemoLayout>
));

Variants #

Use the variant prop to help communicate intent. Note that the variant is automatically applied to the title and primary action.

() => {
  return ['success', 'warning', 'danger'].map(variant => {
    return (
      <DemoLayout key={variant}>
        <Dialog
          variant={variant}
          title={capitalize(variant) + ' ipsum dolor sit amet'}
          actions={[
            { text: 'Cancel' },
            { text: 'Action' }
          ]}>
          <Text>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
            eiusmod tempor incididunt ut labore et dolore magna aliqua.
          </Text>
        </Dialog>
      </DemoLayout>
    );
  });
}

Modeless #

Dialog has modal behavior by default, which will not allow users to interact with other portions of an app while it is open. You can disable this behavior with the modeless prop.

() => {
  class Demo extends Component {
    constructor(props) {
      super(props);

      this.state = {
        isOpen: false
      };

      this.toggleDialog = this.toggleDialog.bind(this);
      this.handleClose = this.handleClose.bind(this);
    }

    toggleDialog() {
      this.setState(prevState => ({
        isOpen: !prevState.isOpen
      }));
    }

    handleClose() {
      this.setState(prevState => ({
        isOpen: false
      }));
    }

    render() {
      const { isOpen } = this.state;

      return (
        <div>
          <Button onClick={this.toggleDialog}>{isOpen ? 'Close' : 'Open' } Dialog</Button>
          <Dialog
            modeless
            title="Lorem ipsum dolor sit amet"
            actions={[
              { onClick: this.toggleDialog, text: 'Cancel' },
              { onClick: this.toggleDialog, text: 'Action' }
            ]}
            isOpen={isOpen}
            onClose={this.handleClose}>
            <Text>
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </Text>
          </Dialog>
        </div>
      )
    }
  }

  return <Demo />;
}

Bidirectionality #

Dialog reverses its alignment when the direction theme variable is set to rtl (right-to-left).

<div dir="rtl">
  <ThemeProvider theme={{ direction: 'rtl' }}>
    <DemoLayout>
      <Dialog
        title="الأحكام والشروط"
        actions={[
          { text: 'إلغاء' },
          { text: 'قبول الشروط' }
        ]}>
        <Text>
          ان يبق إستعمل بأضرار الإحتفاظ, هذا إذ ا وبالرغم. أوسع الشهيرة ٣٠ تلك, بحث ثم أوسع أجزاء, مع فصل ودول وسوء الحيلولة. عن مكن المارق واتّجه الإقتصادي, رئيس يعادل الأسيوي كان من, المحيط بتحدّي إذ جُل. تم يتم فرنسا العالم. فقد قد تمهيد الأرواح. ليركز تغييرات أخذ ما, عن جعل بمباركة الولايات.
        </Text>
      </Dialog>
    </DemoLayout>
  </ThemeProvider>
</div>

API & Theme #

Dialog Props #

The Dialog component takes the following React props.

NameTypeDefaultDescription
actions

Configuration for the Buttons rendered at the bottom of Dialog; accepts all Button props

appSelectorstring

CSS selector matching the node(s) which will be accessibly hidden (unless modeless)

childrenReact$Node

Content of Dialog (see the Basic and Alternate Syntax examples)

closeButtonLabelstring'close'

Accessible label for the close button

closeOnClickOutsidebooleantrue

Close Dialog by clicking outside of its content

closeOnEscapebooleantrue

Close Dialog with the 'Escape' key

disableFocusOnOpenboolean

Disable focus being placed on Dialog upon opening

disableFocusTrapboolean

Disable focus being trapped within the Dialog when open

hideOverlayboolean

Hide the overlay underneath Dialog

idstring

Id of the Dialog

isOpenboolean

Dialog only renders its content when true

modelessboolean

Renders Dialog without modal behavior (see example)

onClose() => void

Called when Dialog is closed

onOpen() => void

Called when Dialog is opened

showCloseButtonboolean

Render a close button for Dialog

size'small' | 'medium' | 'large''medium'

Available sizes

titlestring | React$Element<*>

Title of the dialog; must be a string or DialogTitle

variant'danger' | 'success' | 'warning'

Available variants

Undocumented properties, including as and css, will be applied to the root element.

Dialog Theme Variables #

These variables can be used as hooks to override this component's style at either a local or global level. The theme referenced below is whatever theme is available from props to the instance of this component.

VariableValue
Dialog_transitionDuration250ms
Dialog_zIndextheme.zIndex_1600
DialogCloseButton_margintheme.space_inline_sm
DialogContent_backgroundColortheme.panel_backgroundColor
DialogContent_borderColortheme.panel_borderColor
DialogContent_borderRadiustheme.borderRadius_1
DialogContent_boxShadowtheme.boxShadow_5
DialogContent_maxHeight80vh
DialogContent_maxHeight_small35em
DialogContent_maxHeight_medium35em
DialogContent_maxHeight_large45em
DialogContent_maxWidth_small25em
DialogContent_maxWidth_medium40em
DialogContent_maxWidth_large75em
DialogContent_minWidth22.5em
DialogContent_offsetVerticaltheme.space_stack_xxl
DialogContent_width_small35vw
DialogContent_width_medium50vw
DialogContent_width_large80vw
DialogOverlay_backgroundColorrgba(0, 0, 0, 0.6)
DialogRow_fontSizetheme.fontSize_ui
DialogRow_paddingHorizontaltheme.space_inline_lg
DialogRow_marginVerticaltheme.space_stack_lg

Usage #

When/How to Use #

Use Dialog when you require a user confirmation or decision, need to reveal critical information, or need to show information without losing the overall context of the page. Modal Dialogs eliminate interactions with the rest of the app and completely trap user focus until they are dismissed or otherwise closed. Modeless Dialogs do not interrupt workflow, but may not be dismissed without triggering a close action. Both of these approaches are disruptive, so use thoughtfully and sparingly.

Note that an accessible label is required—one is automatically created if you provide a title via the title prop or supply a DialogTitle. Otherwise you must pass an aria-label to Dialog.

Best Practices #

Use clear and concise language for titles and actions. The title should avoid apologies (Sorry to interrupt), alarm (WARNING), and ambiguity (Are you sure?). Actions should clearly indicate the outcome and should be in verb-noun form except for common cases (Create, Save, Send, Share, Cancel, etc.)

Provide at least two actions (one dismissing and one confirming), but no more than three actions for user decisions. Provide one action for user acknowledgements.

Use the right Dialog size based on your content and supported screen sizes; consider alternative components if the content is too long or too complex within a Dialog.

Don't include links that navigate away from Dialog; this leaves the task at-hand unfinished.

Don't use Dialog for non-critical, non-actionable, contextual information; use Tooltip or Popover instead.