Skip to content

Dialog

A fully accessible, headless Dialog (modal) component for React. Composed of multiple subcomponents for flexible usage.

Features

  • Accessible (focus trap, keyboard navigation, ARIA attributes)
  • Headless (no styles, fully customizable)
  • Composable API (Dialog, DialogOverlay, DialogContent, DialogTitle, DialogActions)
  • Context-powered hooks

Installation

bash
npm install react-headless-ui-kit

Usage

tsx
import {
  Dialog,
  DialogOverlay,
  DialogContent,
  DialogTitle,
  DialogActions,
  useDialog,
} from "react-headless-ui-kit";

function ExampleDialog() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Open dialog</button>
      <Dialog open={open} onClose={() => setOpen(false)}>
        <DialogOverlay
          style={{
            position: "fixed",
            inset: 0,
            background: "rgba(0,0,0,0.5)",
            display: "grid",
            placeItems: "center",
          }}
        >
          <DialogContent
            style={{
              background: "white",
              padding: "1rem",
              borderRadius: 8,
              maxWidth: 400,
              width: "100%",
            }}
          >
            <DialogTitle>Dialog Title</DialogTitle>
            <DialogContent>
              Dialog body content goes here.
            </DialogContent>
            <DialogActions
              style={{ marginTop: 16, display: "flex", gap: 8 }}
            >
              <button onClick={() => setOpen(false)}>Close</button>
            </DialogActions>
          </DialogContent>
        </DialogOverlay>
      </Dialog>
    </>
  );
}

API Reference

<Dialog />

PropTypeDescription
openbooleanWhether the dialog is open
onClose() => voidCallback to close the dialog
childrenReactNodeDialog content
containerElement | nullPortal target (default: body)

<DialogOverlay />

Wraps the dialog content and handles click outside to close.

PropTypeDescription
childrenReactNodeOverlay content

<DialogContent />

Main dialog content container. Handles focus management and ARIA attributes.

PropTypeDescription
childrenReactNodeDialog content

<DialogTitle />

Dialog title, linked via aria-labelledby.

PropTypeDescription
childrenReactNodeTitle text

<DialogActions />

Container for dialog action buttons.

PropTypeDescription
childrenReactNodeAction buttons

useDialog()

Hook to access dialog context values inside subcomponents.

Return valueDescription
onCloseClose callback
onOpenOpen callback
openDialog open state
titleIdARIA title id
descriptionIdARIA description id

Accessibility

  • Focus is trapped inside the dialog when open.
  • Pressing Escape closes the dialog.
  • ARIA attributes are set for screen readers.

Customization

All components are unstyled. Use your own styles via className or style props.