Brik Design System
Components

Modal

Portal-rendered dialog overlay with backdrop, escape key, and scroll lock. Five sizes plus a confirm preset.

Modal is the canonical dialog overlay. Portal-rendered (escapes the source DOM), backdrop with optional click-to-close, Escape key dismissal, scroll lock on the underlying page. Five sizes plus a preset="confirm" for destructive/confirmation flows.

Use it for

  • Focused tasks (forms, multi-step flows)
  • Confirmations and destructive-action prompts (preset="confirm")
  • Any modal interaction where the user needs to commit or cancel before continuing

For sliding panels anchored to a screen edge (detail views, edit workflows), use Sheet. For floating content panels anchored to a trigger, use Popover.

Import

import { Modal } from '@brikdesigns/bds';

Default mode

import { useState } from 'react';
const [open, setOpen] = useState(false);

<Modal
  isOpen={open}
  onClose={() => setOpen(false)}
  title="Edit profile"
  footer={
    <>
      <Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
      <Button variant="primary" onClick={handleSave}>Save</Button>
    </>
  }
>
  <p>Form content here…</p>
</Modal>

Sizes

SizeUse case
smCompact messages, simple confirms
md (default)Standard dialogs
lgExtended content
xlData-heavy views
fullFull-screen takeover

Confirm preset

preset="confirm" collapses the legacy Dialog component into Modal. Sets role="alertdialog", locks to a tighter 440px width, hides the X close button, and auto-renders Cancel / Confirm buttons.

<Modal
  isOpen={open}
  onClose={() => setOpen(false)}
  preset="confirm"
  title="Delete this item?"
  description="This action cannot be undone."
  confirmLabel="Delete"
  confirmVariant="destructive"
  onConfirm={handleDelete}
/>

Confirm preset props

  • confirmLabel / cancelLabel — button labels (defaults: "Confirm" / "Cancel")
  • confirmVariant'primary' (default) or 'destructive' for delete-style actions
  • confirmDisabled — disables the confirm button (e.g. while form is invalid)
  • confirmLoading — shows loading state on the confirm button (in-flight request)
  • onConfirm — called when the user confirms

Pass a custom footer to override the auto-rendered actions while keeping the rest of the preset.

The standalone Dialog component is @deprecated and slated for deletion in a future major version. Migrate to Modal preset="confirm" — same prop names, same behavior. See ADR-004.

When not to use

  • Don't use Modal for persistent state. Modals interrupt the user. For background notifications, use Toast. For persistent alerts, use Banner.
  • Don't use Modal for ephemeral hover content. Use Tooltip or Popover.
  • Don't nest Modals. Modal-on-modal indicates a flow problem. Refactor as a single multi-step Modal or as a Sheet push-stack.
  • Don't put navigation in a Modal. Modals are for committing — back-out flows belong on the page itself.

Accessibility

  • Renders role="dialog" (or alertdialog for confirm preset) with aria-labelledby linking the title.
  • Focus trap inside the modal — Tab cycles within, focus returns to the trigger on close.
  • Escape closes (auto). Backdrop click closes by default; opt out via closeOnBackdrop={false}.
  • Body scroll is locked while the modal is open.

API

Default mode

PropTypeDefault
isOpenboolean (required)
onClose() => void (required)
titlestring
size'sm' | 'md' | 'lg' | 'xl' | 'full''md'
childrenReactNode
footerReactNode
closeOnBackdropbooleantrue
closeOnEscapebooleantrue
showCloseButtonbooleantrue

Confirm preset

PropTypeDefault
preset'confirm' (required)
titlestring (required)
descriptionstring
confirmLabelstring'Confirm'
cancelLabelstring'Cancel'
confirmVariant'primary' | 'destructive''primary'
confirmDisabledbooleanfalse
confirmLoadingbooleanfalse
onConfirm() => void

On this page