Skip to main contentCarbon Design System

Modal

<Modal> allows you to use its bespoke set of contents. children prop maps to the modal body content. You can also use modalLabel, modalHeading, secondaryButtonText and primaryButtonText props to change the corresponding text:

Modifiers
size

ComposedModal

<ComposedModal> provides you with more flexibility in the contents. You can provide the contents via <ModalHeader>, <ModalBody> and <ModalFooter> with your contents in them:

ComposedModal
size
ModalBody
Modifiers
ModalFooter
Modifiers

Installation

To use styles:

@import "carbon-components/scss/components/modal/modal";

To import React components:

// For using `<Modal>`
import { Modal } from "carbon-components-react";
// For using `<ComposedModal>`
import {
ComposedModal,
ModalHeder,
ModalBody,
ModalFooter,

Usage

This section explains usage with our React variant. For usage with other frameworks, please follow a link in component live demo above.

Opening/closing modal

For both modal variants, you can open/close the modal by changing the open prop. For example, you can implement a launcher button with a React state and a <Button> that changes the state:

function ModalStateManager() {
const [open, setOpen] = useState(false);
return (
<>
{typeof document === "undefined"
? null
: ReactDOM.createPortal(
<ComposedModal open={open} onClose={() => setOpen(false)}>
...

You can create an abstract version of such state manager, like:

const ModalStateManager = ({
renderLauncher: LauncherContent,
children: ModalContent,
}) => {
const [open, setOpen] = useState(false);
return (
<>
{!ModalContent || typeof document === "undefined"
? null

There are four responsive modal sizes: xs, small, default, and large. You can set it via size prop:

<ComposedModal size="lg">
<ModalHeader />
<ModalBody>
<p className="bx--modal-content__text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
cursus fermentum risus, sit amet fringilla nunc pellentesque quis. Duis
quis odio ultrices, cursus lacus ac, posuere felis. Donec dignissim libero
in augue mattis, a molestie metus vestibulum. Aliquam placerat felis
ultrices lorem condimentum, nec ullamcorper felis porttitor.
<ComposedModal>
<ModalHeader />
<ModalBody hasForm>
<TextInput data-modal-primary-focus labelText="Enter something" />
<p className="bx--modal-content__text bx--modal-content__regular-content">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
cursus fermentum risus, sit amet fringilla nunc pellentesque quis. Duis
quis odio ultrices, cursus lacus ac, posuere felis. Donec dignissim libero
in augue mattis, a molestie metus vestibulum. Aliquam placerat felis
<ComposedModal size="large">
<ModalHeader />
<ModalBody hasScrollingContent>
<p className=".bx--modal-content__text">Some very large contents...</p>
</ModalBody>
</ComposedModal>

With <Modal>, you have limited control over the set of buttons. Supported patterns are the following:

  • No button (passive modal): With passiveModal prop in <Modal>
  • Transactional modals: Only supports two buttons variant. For others, use <ComposedModal>
  • Danger modal: With danger prop in <Modal> (like below)
<Modal danger>
<ModalHeader />
<p className="bx--modal-content__text">The modal body content</p>
</Modal>

With <ComposedModal>, you can control the buttons with the following:

  • No button (passive modal): By not putting <ModalFooter>
  • Transactional modals:
    • One button (acknowledgement modal): By setting primaryButtonText prop to <ModalFooter>
    • Two buttons: By setting secondaryButtonText prop to <ModalFooter> in addition to primaryButtonText prop
    • Three buttons: Put three buttons as children of <ModalFooter>, instead of using primaryButtonText or secondaryButtonText. Using this option requires style adjustment defined in application-level CSS for <ModalFooter>, e.g. .bx--modal-footer { padding: 25%; }.
  • Danger modal: By setting danger prop in <ModalFooter> (like below)
<ComposedModal>
...
<ModalFooter danger primaryButtonText="OK" secondaryButtonText="Cancel" />
</ComposedModal>
<ComposedModal>
...
<ModalFooter>
<Button
kind="secondary"
onClick={() => { (Run some action...) setOpen(false); }}>
Another button
</Buttton>
<Button

Using modal title as message

For short, direct messages the title can include the whole message to add visual clarity to an otherwise repetitive title and body message.

To use this pattern with <Modal>, you can omit children prop:

const modalHeadding =
'Are you sure you want to add the "Speech to Text" service ' +
'to the node-test app?';
...
<Modal
modalHeading={modalHeading}
secondaryButtonText="Cancel"
primaryButtonText="Add"
/>

To use this pattern with <ComposedModal>, you can omit <ModalBody>:

<ComposedModal>
<ModalHeader label="Modla label">
<h1>
Are you sure you want to add the "Speech to Text" service to the node-test
app?
</h1>
</ModalHeader>
<ModalFooter primaryButtonText="OK" secondaryButtonText="Cancel" />
</ComposedModal>

Focus management

For both modal variants, once modal gets open, keyboard focus will be restricted inside modal. It means:

  • If you hit tab key at the last keyboard-focusable element in modal, the first keyboard-focusable element in modal will get focus.
  • If you hit shift-tab key at the first keyboard-focusable element in modal, the last keyboard-focusable element in modal will get focus.

Also for both modal variants, you can set the DOM element that gets focus when the modal gets open, by either of the following ways:

Setting data-modal-primary-focus attribute to the target element

<ComposedModal>
<ModalBody hasForm>
<TextInput data-modal-primary-focus labelText="Enter something" />
</ModalBody>
</ComposedModal>

Specifying a query selector to the target element

{
/* `.bx--text-input` selects the `<input>` in `<TextInput>` */
}
<ComposedModal selectorPrimaryFocus=".bx--text-input">
<ModalBody hasForm>
<TextInput labelText="Enter something" />
</ModalBody>
</ComposedModal>;

Component API

Please see Show Info button at our storybook, or follow a link in component live demo above for other frameworks.