@redrob-labs/ui v1.0.2 · Redrob Group Design System 2026

Modal

Feedback · src/components/Modal/Modal.tsx

Interrupts, for one decision that has to be made before anything else.

The bar is high: it takes the whole screen away. A destructive confirmation qualifies, a form usually does not, and information almost never does.

aria-modal and role="dialog" are on the panel, not the scrim, and the title is wired through aria-labelledby - so a screen reader announces what it is rather than "dialog".

Clicking the scrim closes it only when the click both started and ended there, which is why the handler compares target with currentTarget: a drag that began inside the panel should not dismiss the decision.

Import

import { Modal } from '@redrob-labs/ui';

Rendered

The design system's own preview case, run against this package's build. The parity gate compares this rendering to the reference bundle's.

Props

PropTypeNotes
open boolean false renders nothing. The app owns whether it is open.
title React.ReactNode
footer React.ReactNode The actions. A modal that asks a question needs an answer and a way out.
width number | string Max width. Keep it narrow: a wide modal is a page that forgot to be one.
closeLabel string
className string
children React.ReactNode
onClose () => void