Skip to main navigationSkip to main content
Return to Sky UI homepage
import { Modal } from '@sky-uk/ui-core';

Modal offers a more focused view on something that the user may need to action. It can also offer further information that may be important, or relevant, to something in-page.

The component consists of Modal.Content and optional Modal.CloseButton.

function Example() {
  const [open, setOpen] = React.useState(false);

  const toggleOpen = (event) => {
    event.stopPropagation();
    setOpen(!open);
  }

  return (
    <>
      {open && (
        <Modal onClose={toggleOpen}>
          <Modal.CloseButton />

          <Modal.Content>
            <img src="https://placehold.co/800x600" />
          </Modal.Content>
        </Modal>
      )}

      <Button aria-label="Open default modal example" onClick={toggleOpen}>Open</Button>
    </>
  );
}

Props

$fullScreen

$fullScreen can be used to render a full-page modal. This can be used if you have a need for more copy or want to display media-driven content.

function Example() {
  const [open, setOpen] = React.useState(false);

  const toggleOpen = (event) => {
    event.stopPropagation();
    setOpen(!open);
  }

  return (
    <>
      {open && (
        <Modal $fullScreen onClose={toggleOpen}>
          <Modal.CloseButton />

          <Modal.Content>
            <img src="https://placehold.co/2000x1000" />
          </Modal.Content>
        </Modal>
      )}

      <Button aria-label="Open $fullscreen prop example" onClick={toggleOpen}>Open</Button>
    </>
  );
}

stopEventPropagation

The stopEventPropagation prop can be used to prevent the events from the Modal progating to the parent element.

function Example() {
  const [open, setOpen] = React.useState(false);
  const buttonRef = React.useRef();

  const handleInternalButton = (event) => {
    alert('Internal button clicked');
  }

  const toggleOpen = (event) => {
    event.stopPropagation();
    setOpen(!open);
  }

  return (
    <>
      {open && (
        <Modal onClose={toggleOpen} stopEventPropagation>
          <Modal.CloseButton />

          <Modal.Content>
            <Button onClick={handleInternalButton} $marginTop={8}>I shouldn't work</Button>
          </Modal.Content>
        </Modal>
      )}

      <Button aria-label="Open modal" onClick={toggleOpen}>Open</Button>
    </>
  );
}

Sub Components

Close button

Default appearance of the Close button floating over the content.

$inline property would push the content section under the Close button section.

function Example() {
  const [open, setOpen] = React.useState(false);

  const toggleOpen = (event) => {
    event.stopPropagation();
    setOpen(!open);
  }

  return (
    <>
      {open && (
        <Modal onClose={toggleOpen}>
          <Modal.CloseButton $inline />

          <Modal.Content $padding={5}>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis aliquet diam mi, ut condimentum turpis sodales varius. Aliquam vitae quam sed augue tempor euismod. Praesent quis cursus lorem. Etiam lobortis luctus commodo. Nulla porta justo sed quam gravida finibus. Nullam scelerisque lorem in vehicula tristique. Etiam ut nibh non urna sagittis accumsan. Nunc eget felis pellentesque nunc vulputate convallis vel maximus magna.
          </Modal.Content>
        </Modal>
      )}

      <Button aria-label="Open modal with Close button example" onClick={toggleOpen}>Open</Button>
    </>
  );
}

Accessibility

The Modal component will force focus to its close button when first opened.

This ensures keyboard-only and screenreader users can access it. If used without the close button, focus will be forced onto the first interactive element within it.

There are some use-cases where this may not be appropriate. Please refer to the W3C Dialog Modal Design Pattern for more details.

Returning Focus

Returning focus to a Button used to open the Modal is left to the concern of the consumer. Below is an example of how to achieve this desired outcome.

function Example() {
  const [open, setOpen] = React.useState(false);
  const buttonRef = React.useRef();

  const toggleOpen = (event) => {
    event.stopPropagation();
    if(open && buttonRef.current) buttonRef.current.focus();
    setOpen(!open);
  }

  return (
    <>
      {open && (
        <Modal onClose={toggleOpen}>
          <Modal.CloseButton />

          <Modal.Content>
            <img src="https://placehold.co/800x600" />
          </Modal.Content>
        </Modal>
      )}

      <Button ref={buttonRef} aria-label="Return focus modal example" onClick={toggleOpen}>Open</Button>
    </>
  );
}

System Modifiers

The Modal component supports the props applied using the following system functions:

Modal.Content supports

Translatable Fields

The Modal support translation on the following fields:

  • Modal.closeLabel - controls the close button text on the Modal component

For more on translatable fields, view the useTranslation docs here: useTranslation

Modal - React | Sky UI Design System