Skip to main content
On this page

A modal interrupts the user with a focused overlay that requires them to act or dismiss before continuing.

When to use​

  • To ask the user to confirm or cancel a consequential action, such as deleting a record
  • To collect a small amount of information before the user can continue, where navigating to a new page would break context
  • To notify the user of something urgent that requires an immediate response

When not to use​

  • For complex or multi-page forms - navigate to a dedicated page instead.
  • For non-urgent information - use a Notification instead. Modals block the page and should only be used when the interruption is justified.
  • Nested inside another modal - a modal must not open another modal. If the user journey requires it, redesign the flow.

Anatomy​

  1. Overlay (the semi-transparent backdrop that obscures and blocks interaction with the page behind)
  2. Dialog (the card container holding all modal content)
  3. Title (a required heading that names the action or topic)
  4. Content (the body of the modal; can contain any content including forms and notifications)
  5. Dismiss button (an icon button that closes the modal; present when isDismissable is true)

Keyboard support​

Keyboard functions​

  • Tab: moves focus forward through interactive elements within the modal; focus is trapped inside the dialog
  • Shift + Tab: moves focus backward through interactive elements within the modal
  • Escape: closes the modal (when isDismissable is true)

Basic usage​

The isOpen prop controls visibility. The title prop is required. Provide an onClose handler to manage state.

Loading...
Edit live code
() => { // ignore - for live code example only.
  const Example = () => {
    const [isOpen, setIsOpen] = useState(false);

    return (
      <>
        <PrimaryCTAButton onClick={() => setIsOpen(true)}>Open modal</PrimaryCTAButton>
        <Modal
          title="Offshore Wind"
          isOpen={isOpen}
          onClose={() => setIsOpen(false)}
        >
          <P>
            Offshore wind power or offshore wind energy is the use of wind farms constructed in bodies of water, usually in the ocean, to harvest wind energy to generate electricity.
          </P>
        </Modal>
      </>
    );
  }

  return <Example />;
}

Variants and features​

Non-dismissable​

Set isDismissable={false} to remove the dismiss button and prevent closing by clicking the overlay or pressing Escape. Use this only when the user must make an explicit choice to continue, for example in a critical confirmation step where accidental dismissal could cause problems.

Always provide an explicit way to close the modal when using this variant, such as a Cancel button.

Loading...
Edit live code
() => { // ignore - for live code example only.
  const Example = () => {
    const [isOpen, setIsOpen] = useState(false);

    return (
      <>
        <PrimaryCTAButton onClick={() => setIsOpen(true)}>Open non-dismissable modal</PrimaryCTAButton>
        <Modal
          title="Offshore Wind"
          isOpen={isOpen}
          onClose={() => setIsOpen(false)}
          isDismissable={false}
        >
          <P>
            Offshore wind is a great addition to the renewable energy mix. Please confirm to continue.
          </P>
          <PrimaryCTAButton onClick={() => setIsOpen(false)}>
            I agree
          </PrimaryCTAButton>
        </Modal>
      </>
    );
  }

  return <Example />;
}

Custom heading level​

By default, the modal title renders as an h2. Use the headingComponent prop to override this when the semantic heading level needs to change to fit the page structure.

Loading...
Edit live code
() => { // ignore - for live code example only.
  const Example = () => {
    const [isOpen, setIsOpen] = useState(false);

    return (
      <>
        <PrimaryCTAButton onClick={() => setIsOpen(true)}>Open h4 modal</PrimaryCTAButton>
        <Modal
          title="Offshore Wind"
          isOpen={isOpen}
          onClose={() => setIsOpen(false)}
          headingComponent={Heading4}
        >
          <P>
            Offshore wind power or offshore wind energy is the use of wind farms constructed in bodies of water, usually in the ocean, to harvest wind energy to generate electricity.
          </P>
        </Modal>
      </>
    );
  }

  return <Example />;
}

Auto focus​

By default, focus moves to the dialog container when the modal opens. Set autoFocus to move focus to the first focusable element inside the modal instead. Use this when the modal opens directly into a form and the user should begin typing immediately.

Do not use autoFocus when important content or instructions appear before the first input, as the user will miss them.

Loading...
Edit live code
() => { // ignore - for live code example only.
  const Example = () => {
    const [isOpen, setIsOpen] = useState(false);

    return (
      <>
        <PrimaryCTAButton onClick={() => setIsOpen(true)}>Open autofocus modal</PrimaryCTAButton>
        <Modal
          title="Add a meter reading"
          isOpen={isOpen}
          onClose={() => setIsOpen(false)}
          autoFocus
        >
          <FormFields>
            <NumberField
              id="modal-reading"
              label="Meter reading"
              characters={10}
            />
          </FormFields>
        </Modal>
      </>
    );
  }

  return <Example />;
}

Scrollable content​

The modal does not scroll internally. If the content is taller than the viewport, the page scrolls to reveal the full modal. Keep modal content concise to avoid this. If content regularly overflows the viewport, it is a signal the content should move to a dedicated page.