---
title: 'ModalDialog'
type: 'component'
components:
- ModalDialog
- ModalDialogTitle
- ModalDialogHeader
- ModalDialogHero
- ModalDialogBody
- ModalDialogFooter
- ModalDialogCloseButton
categories:
- Overlays
status: 'New'
designStatus: 'Done'
devStatus: 'Done'
notes: |

---

A set of components for making all kinds of modal dialogs. Remember to supply
the required `title` prop to `ModalDialog` in order ensure there is an accessible
label for the dialog element.

## Basic Usage

```jsx live
() => {
  const [isOpen, open, close] = useToggle(false);
  const sizes = ['sm', 'md', 'lg', 'xl', 'fullscreen'];
  const variants = ['default', 'warning', 'danger', 'success', 'dark'];
  const [modalSize, setModalSize] = useState('md');
  const [modalVariant, setModalVariant] = useState('default');

  return (
    <>
      <div className="d-flex">
        <Button variant="outline-primary" onClick={open}>
          Open standard modal dialog
        </Button>
      </div>
      <ModalDialog
        title="My dialog"
        isOpen={isOpen}
        onClose={close}
        size={modalSize}
        variant={modalVariant}
        hasCloseButton
        isFullscreenOnMobile
        isOverflowVisible={false}
      >
        <ModalDialog.Header>
          <ModalDialog.Title>
            I'm a dialog box
          </ModalDialog.Title>
        </ModalDialog.Header>

        <ModalDialog.Body>
          <Form.Group>
            <Form.Label>Size</Form.Label>
            <Form.RadioSet
              name="size"
              value={modalSize}
              onChange={(e) => setModalSize(e.target.value)}
            >
              {sizes.map(s => <Form.Radio key={s} value={s}>{s}</Form.Radio>)}
            </Form.RadioSet>
          </Form.Group>
          <Form.Group>
            <Form.Label>Variant</Form.Label>
            <Form.RadioSet
              name="variant"
              value={modalVariant}
              onChange={(e) => setModalVariant(e.target.value)}
            >
              {variants.map(v => <Form.Radio key={v} value={v}>{v}</Form.Radio>)}
            </Form.RadioSet>
          </Form.Group>
          <p>
            I'm baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever.
            Beard man braid migas single-origin coffee forage ramps. Tumeric messenger
            bag bicycle rights wayfarers, try-hard cronut blue bottle health goth.
            Sriracha tumblr cardigan, cloud bread succulents tumeric copper mug marfa
            semiotics woke next level organic roof party +1 try-hard.
          </p>
        </ModalDialog.Body>

        <ModalDialog.Footer>
          <ActionRow>
            <ModalDialog.CloseButton variant="tertiary">
              Cancel
            </ModalDialog.CloseButton>
            <Button>
              A button
            </Button>
          </ActionRow>
        </ModalDialog.Footer>
      </ModalDialog>
    </>
  )
}
```

## With header content

```jsx live
() => {
  const [isOpen, open, close] = useToggle(false);
  const sizes = ['sm', 'md', 'lg', 'xl', 'fullscreen'];
  const variants = ['default', 'warning', 'danger', 'success', 'dark'];
  const [modalSize, setModalSize] = useState('md');
  const [modalVariant, setModalVariant] = useState('dark');

  return (
    <>
      <div className="d-flex">
        <Button variant="outline-primary" onClick={open}>
          Open marketing modal dialog
        </Button>
      </div>
      <ModalDialog
        title="My dialog"
        isOpen={isOpen}
        onClose={close}
        size={modalSize}
        variant={modalVariant}
        hasCloseButton
        isOverflowVisible={false}
      >
        <ModalDialog.Hero>
          <ModalDialog.Hero.Background
            backgroundSrc="https://picsum.photos/1600/800/"
          />
          <ModalDialog.Hero.Content style={{ maxWidth: '15rem' }}>
            <ModalDialog.Title as="h1">
              I'm a dialog box
            </ModalDialog.Title>
          </ModalDialog.Hero.Content>
        </ModalDialog.Hero>

        <ModalDialog.Body>
          <Form.Group>
            <Form.Label>Size</Form.Label>
            <Form.RadioSet name="size" value={modalSize} onChange={(e) => setModalSize(e.target.value)}>
              {sizes.map(size => (
                <Form.Radio key={size} value={size}>{size}</Form.Radio>
              ))}
            </Form.RadioSet>
          </Form.Group>
          <Form.Group>
            <Form.Label>Variant</Form.Label>
            <Form.RadioSet name="variant" value={modalVariant} onChange={(e) => setModalVariant(e.target.value)}>
              {['default', 'dark'].map(variant => (
                <Form.Radio key={variant} value={variant}>{variant}</Form.Radio>
              ))}
            </Form.RadioSet>
          </Form.Group>
          <p>
            I'm baby palo santo ugh celiac fashion axe. La croix lo-fi venmo whatever.
            Beard man braid migas single-origin coffee forage ramps. Tumeric messenger
            bag bicycle rights wayfarers, try-hard cronut blue bottle health goth.
            Sriracha tumblr cardigan, cloud bread succulents tumeric copper mug marfa
            semiotics woke next level organic roof party +1 try-hard.
          </p>
        </ModalDialog.Body>

        <ModalDialog.Footer>
          <ActionRow isStacked>
            <ModalDialog.CloseButton variant="tertiary">
              Cancel
            </ModalDialog.CloseButton>
            <Button>
              A button
            </Button>
          </ActionRow>
        </ModalDialog.Footer>
      </ModalDialog>
    </>
  )
}
```

## Overflow visibility handling

The `isOverflowVisible` toggle controls whether content that extends beyond the modal's viewport boundaries is visible.
When enabled (`isOverflowVisible` is set to `true`), any overflow content, such as dropdowns or tooltips,
will be displayed outside the modal's main area instead of being clipped.

In this example, switching `isOverflowVisible` on and off affects the visibility of the dropdown options in
the autosuggest field, showing how overflow handling impacts content display within a modal.

```jsx live
() => {
  const [isOpen, open, close] = useToggle(false);
  const [isOn, setOn, setOff, toggle] = useToggle(false);

  return (
    <>
      <div className="d-flex">
        <Button variant="outline-primary" onClick={open}>
          Open standard modal dialog
        </Button>
      </div>
      <ModalDialog
        title="My dialog"
        isOpen={isOpen}
        onClose={close}
        hasCloseButton
        isFullscreenOnMobile
        isOverflowVisible={isOn}
      >
        <ModalDialog.Header>
          <ModalDialog.Title>
            I'm a dialog box
          </ModalDialog.Title>
        </ModalDialog.Header>

        <ModalDialog.Body>
          <Stack className="mb-3" direction="horizontal" gap={2}>
            <Form.Switch checked={isOn} onChange={toggle}>
              isOverflowVisible
            </Form.Switch>
            {isOn
              ? <Badge variant="success">{JSON.stringify(isOn)}</Badge>
              : <Badge variant="light">{JSON.stringify(isOn)}</Badge>
            }
          </Stack>
          <Form.Autosuggest
            aria-label="form autosuggest"
            helpMessage="Select language"
            placeholder="Open autosuggest dropdown"
          >
            <Form.AutosuggestOption id="javascript-option-id">JavaScript</Form.AutosuggestOption>
            <Form.AutosuggestOption id="python-option-id">Python</Form.AutosuggestOption>
            <Form.AutosuggestOption id="ruby-option-id">Ruby</Form.AutosuggestOption>
            <Form.AutosuggestOption id="c-option-id">C</Form.AutosuggestOption>
          </Form.Autosuggest>
        </ModalDialog.Body>

        <ModalDialog.Footer>
          <ActionRow>
            <ModalDialog.CloseButton variant="tertiary">
              Cancel
            </ModalDialog.CloseButton>
            <Button>
              A button
            </Button>
          </ActionRow>
        </ModalDialog.Footer>
      </ModalDialog>
    </>
  )
}
```
