Componentsv2.189.1
Iconsv1.19.0
MCPv0.8.62
Tokensv0.34.3

Modals are dialogs displayed over inert content that allow users to complete a singular, focused task without leaving the page.

Modal

Usage

  • Use Modal for tasks requiring the user's immediate attention: action confirmations, short forms, feature moments, and supplementary workflows.
  • Never nest Modals. Rework the flow, move content inline, or use a Popover instead.
  • Use Modal when users must confirm a task or provide input before continuing. Use Drawer for content with less contextual relation to the main page. Use Popover for small, inline supplementary content.
  • Keep Modal content focused on a single task. Move multi-step workflows or lengthy content to a dedicated page.

Common Patterns

  • Confirmation — hide the close button (shouldShowCloseButton={false}) and provide primary/secondary footer actions.
  • Destructive confirmation — hide the close button, require additional user input (e.g., a text field), and disable the primary action (isDisabled) until input requirements are met. Mark the primary action as isDanger.
  • Form — disable overlay click dismissal (shouldCloseOnOverlayClick={false}) to prevent accidental data loss. Place submit and cancel buttons in the footer.
  • Save/discard — hide the close button and provide three footer actions: a go-back action (use mr="auto" to push it to the left), a discard action (isDanger), and a save action (primary).
  • Informational — display read-only content with a single primary dismiss button in the footer.
  • Feature moment — use ModalSplit for a branded graphic panel alongside the body content. Hide the close button and include a single call-to-action.

Types

  • Standard — single-column layout with optional header and footer, and scrollable body content. This is the default.
  • Split — two-column layout using ModalSplit. Place ModalSplit before ModalBody for a left panel, or after for a right panel.

Appearance

  • Size (size, default "md") — use "md" for most use cases. Use "sm" for shorter content and smaller viewports.
  • Close button (shouldShowCloseButton, default true) — hide it only when the Modal requires an explicit user decision. Always provide a cancel action in the footer when the close button is hidden.
  • Inset (ModalInset) — renders content edge-to-edge, ignoring the Modal's default padding. Use for full-width backgrounds, images, or dividers.

Behaviors

  • Dismissal methods — close button, action button, overlay click, and the Escape key. All are enabled by default.
  • Non-dismissable shortcut (isDismissable={false}) — sets shouldShowCloseButton, shouldCloseOnOverlayClick, and shouldCloseOnEscapePress to false in one prop. Individual props still override isDismissable when explicitly set.
  • Overlay click dismissal (shouldCloseOnOverlayClick, default true) — disable for form Modals to prevent accidental data loss.
  • Escape key dismissal (shouldCloseOnEscapePress, default true) — disable alongside the close button for Modals that require an explicit choice.
  • Scrolling (shouldScrollInViewport, default false) — by default the Modal body scrolls while the header and footer remain fixed. Set to true to scroll the entire Modal within the viewport.
  • Animation (animationTransitionDuration) — fade and downward slide. The duration is customizable.

Content

  • Write titles in sentence case. Use descriptive, action-oriented titles following the pattern "Action + object" (e.g., "Delete campaign?"). Never use generic confirmation titles like "Are you sure?" or "Delete?"
  • Include the object — a noun or noun phrase related to the workflow — in the title.
  • End the title with a question mark when asking for confirmation. Omit ending punctuation otherwise.
  • Write footer action labels with specific verbs that match the Modal's purpose. Keep labels to 1–3 words in sentence case with no period.
  • Prefer specific labels (e.g., "Send campaign" over "Submit"), but generic labels are acceptable when the context makes the action clear.
  • Be consistent in verbiage across the application.
  • State the consequence in the body. Explicitly note when an action is irreversible.
  • Keep body content concise and focused on the task at hand.

Implementation Notes

  • Compose Modal with subcomponents: ModalBody for scrollable body content, ModalFooter for action buttons, ModalSplit for split-layout panels, and ModalInset for edge-to-edge content.
  • ModalFooter wraps ButtonGroup with groupVariant="spaced" — pass Button components directly as children.
  • ModalSplit panel side is controlled by DOM order relative to ModalBody, not a prop.
  • ModalInset accepts inheritPadding to control whether it inherits the Modal's padding.
  • Control visibility with isOpen and onClose. onClose receives (event, reason) where reason is "close-button-press", overlay click, or escape press.
  • Lifecycle callbacks: onOpen fires when opened, onCloseComplete fires after the close animation finishes.
  • initialFocusIndex overrides which focusable element receives focus when the Modal opens (default is the first).
  • state prop accepts all Modal props as a single object for use with a ModalsManager pattern.
  • title prop renders the default header. Omit title to render no header.
  • Ember invocation: <PlumaModal @isOpen={{this.isOpen}} @onClose={{this.handleClose}} @title="Modal title">. Subcomponents: <PlumaModalBody>, <PlumaModalFooter>, <PlumaModalSplit>, <PlumaModalInset>.
  • Ember default block yields a context value: <PlumaModal ... as |ctx|>.
  • Global defaults for animationTransitionDuration can be set via PlumaProvider's componentConfig.PlumaModal.

On this page