Beta Preview

Modal

A modal is an overlay element which blocks interaction with elements outside it.

Theme
isDismissable 
isKeyboardDismissDisabled 
Example
Modal.tsx
Modal.css
import {DialogTrigger, Heading} from 'react-aria-components';
import {Modal} from './Modal';
import {Dialog} from './Dialog';
import {Form} from './Form';
import {TextField} from './TextField';
import {Button} from './Button';

function Example(props) {
  return (
    <DialogTrigger>
      <Button>Sign up…</Button>
      <Modal {...props}>
        <Dialog>
          <Heading slot="title">Subscribe to our newsletter</Heading>
          <p>Enter your information to subscribe to our newsletter and receive updates about new features and announcements.</p>
          <Form>
            <TextField autoFocus label="Name" placeholder="Enter your full name" />
            <TextField label="Email" placeholder="Enter your email" />
            <div style={{display: 'flex', gap: 8, alignSelf: 'end'}}>
              <Button slot="close" variant="secondary">Cancel</Button>
              <Button slot="close">Subscribe</Button>
            </div>
          </Form>
        </Dialog>
      </Modal>
    </DialogTrigger>
  );
}

Sheet

Overlays such as trays, drawers, and sheets can be built using a Modal with custom entry and exit animations.

Example
Sheet.tsx
Sheet.css
import {DialogTrigger, Heading} from 'react-aria-components';
import {Sheet} from './Sheet';
import {Button} from './Button';

<DialogTrigger>
  <Button>Open sheet</Button>
  <Sheet>
    <Heading slot="title">Notice</Heading>
    <p>This is a modal with a custom modal overlay.</p>
    <Button slot="close">Close</Button>
  </Sheet>
</DialogTrigger>

Controlled

Use the isOpen prop to show a modal programmatically or mount in a different part of the JSX tree (e.g. outside a menu).

import {useState} from 'react';
import {Heading} from 'react-aria-components';
import {MenuButton, MenuItem} from './Menu';
import {Modal} from './Modal';
import {Dialog} from './Dialog';
import {Button} from './Button';

function Example() {
  let [isOpen, setOpen] = useState(false);

  return (
    <>
      <MenuButton label="Menu">
        <MenuItem onAction={() => setOpen(true)}>Open dialog…</MenuItem>
      </MenuButton>
      <Modal isDismissable isOpen={isOpen} onOpenChange={setOpen}>
        <Dialog>
          <Heading slot="title">Notice</Heading>
          <p>Click outside or press Escape to close this dialog.</p>
        </Dialog>
      </Modal>
    </>
  );
}

Custom trigger

DialogTrigger works with any pressable React Aria component (e.g. Button, Link, etc.). Use the <Pressable> component or usePress hook to wrap a custom trigger element such as a third party component or DOM element.

import {Pressable, DialogTrigger, Heading} from 'react-aria-components';
import {Modal} from './Modal';
import {Dialog} from './Dialog';
import {Button} from './Button';

<DialogTrigger>
  <Pressable>
    <span role="button">Custom trigger</span>
  </Pressable>
  <Modal>
    <Dialog>
      <Heading slot="title">Dialog</Heading>
      <p>This dialog was triggered by a custom button.</p>
      <Button slot="close">Close</Button>
    </Dialog>
  </Modal>
</DialogTrigger>
const CustomTrigger = React.forwardRef((props, ref) => (
  <button {...props} ref={ref} />
));

API

UnderlayModal