AniUI Academy
medium+200 XP

Build a modal dialog

Build a modal that opens from a button.

It should close three ways: an explicit close button, pressing Escape, and clicking the backdrop behind it — but clicking inside the modal's own content must never close it.

Requirements

  • A button `data-testid="open-modal"` opens the modal.
  • While open, an element with `role="dialog"` is present in the DOM; while closed, it is not present at all (unmounted, not just hidden).
  • A button `data-testid="close-modal"` inside the dialog closes it.
  • Pressing Escape while the modal is open closes it.
  • A `data-testid="modal-backdrop"` element behind the dialog closes it when clicked directly — but a click on the dialog content itself must not propagate into a close.

Your workspace

import { useState } from "react";

export default function App() {
  const [open, setOpen] = useState(false);

  // TODO: pressing Escape while the modal is open should also close it.
  // (Closing via the button and the backdrop already works below.)

  return (
    <div style={{ fontFamily: "sans-serif", padding: 16 }}>
      <button data-testid="open-modal" onClick={() => setOpen(true)}>
        Open modal
      </button>

      {open ? (
        <div
          data-testid="modal-backdrop"
          onClick={() => setOpen(false)}
          style={{
            position: "fixed",
            inset: 0,
            background: "rgba(0,0,0,0.4)",
            display: "grid",
            placeItems: "center",
          }}
        >
          <div
            role="dialog"
            aria-modal="true"
            onClick={(e) => e.stopPropagation()}
            style={{ background: "white", padding: 24, borderRadius: 8, minWidth: 240 }}
          >
            <p>Modal content</p>
            <button data-testid="close-modal" onClick={() => setOpen(false)}>
              Close
            </button>
          </div>
        </div>
      ) : null}
    </div>
  );
}

Ready to check it?

5 tests run against your rendered component, right here in your browser. Sign in to claim the XP when you pass.

Stuck? The react course covers the ideas this problem is built on.