Usage
Modal displays content that temporarily blocks interaction with the rest of the application. Modals are interruptive, so reach for them sparingly — for confirmations, short forms, or focused tasks the user must complete or dismiss before continuing.
A modal is opened by calling showModal() on the element, and closed with close(), by pressing Esc, by clicking the backdrop, or by submitting a <form method="dialog"> inside it.
import "@nordhealth/components/lib/Modal"
Give each modal an accessible name with aria-labelledby pointing at its header, then trigger it from a button:
Composition New since Jul 24, 2026
A modal can be assembled from three structural light-DOM parts plus an optional standalone close part, all placed as direct children of nord-modal. The structural parts assign themselves to the right zones, so the modal's built-in close button, scrolling body and responsive footer keep working. The nord-modal root stays in shadow DOM — it owns the backdrop, focus trapping and dismissal.
import "@nordhealth/components/lib/ModalHeader"
import "@nordhealth/components/lib/ModalBody"
import "@nordhealth/components/lib/ModalFooter"
import "@nordhealth/components/lib/ModalClose"
nord-modal
├── nord-modal-header title row, beside the built-in close button
├── nord-modal-body main content; scrolls when the modal is `scrollable`
├── nord-modal-footer call-to-action buttons; stacked on narrow, row on wide
└── nord-modal-close standalone close control; place it anywhere
<nord-modal aria-labelledby="title">
<nord-modal-header>
<h2 id="title" class="n-typescale-l">Modal title</h2>
</nord-modal-header>
<nord-modal-body>…</nord-modal-body>
<nord-modal-footer>
<nord-button-group variant="spaced">
<nord-button>Cancel</nord-button>
<nord-button variant="primary">Save changes</nord-button>
</nord-button-group>
</nord-modal-footer>
</nord-modal>
The parts are additive — the header, feature and footer slots still work for existing markup. Bring your own heading element in nord-modal-header (the part is layout only); for full-bleed media, use the feature slot directly.
Composable close New since Jul 24, 2026
The modal's built-in close button lives in the header zone, so it only appears when you use a header. When you build completely custom content — a two-column layout, a full-bleed panel, anything without a header — use nord-modal-close instead. It is a standalone control you can place anywhere inside nord-modal; clicking it dismisses the modal through the same cancelable flow as the built-in button (the cancel event still fires and can be prevented).
Left empty, it renders the default close icon — position it against the modal frame (which is position: relative) to float it over your content. Wrap your own control and it becomes a transparent close trigger, e.g. a "Cancel" button in a footer:
<nord-modal aria-labelledby="title">
<!-- floating icon close, no header required -->
<nord-modal-close
style="position: absolute; inset-block-start: var(--n-space-s); inset-inline-end: var(--n-space-s)"
></nord-modal-close>
<div class="your-custom-layout">…</div>
<!-- or turn any control into a close trigger -->
<nord-modal-close><nord-button>Not now</nord-button></nord-modal-close>
</nord-modal>
Examples
Sizes
The size attribute controls the max-width of the modal: s, m (default), l, and xl. Small modals suit confirmations, while larger sizes give complex forms more room.
Form with method="dialog"
Set a form's method to "dialog" so submitting it closes the modal without any extra JavaScript. The modal's returnValue is set to the value of the submit button that was pressed. Associate a footer button with the form using its form attribute.
Persistent
Add the persistent attribute so the modal cannot be dismissed by clicking the backdrop or pressing Esc. The close button is hidden automatically, so only the action buttons can dismiss it. Use this for flows the user must explicitly resolve.
Preventing close
When the user attempts to dismiss the modal, it fires a cancel event. Call preventDefault() on that event to keep the modal open — useful for guarding unsaved work. Toggle the checkbox below and try to close the modal.
Feature image
Use the feature slot to place a full-bleed illustration or banner at the top of the modal, above the header. This works well for onboarding, announcements, or empty states.
Feature without header or footer
A feature modal can drop its header and footer entirely, letting the illustration and its own content carry the message.
Forms
Place a <form> inside the modal and associate footer buttons with it via the form attribute. Inputs lay out naturally in the modal body.
Complex forms
Larger modals (size="l") give multi-field forms room to breathe, combining selects, inputs, and a textarea. Stacks switch to a single column on narrow screens.
Custom footer
The footer slot accepts any layout. Combine inline helper content with a button group to build footers richer than a simple row of actions.
Destructive actions
For irreversible actions, use a danger button in the footer and a clear, specific heading. Autofocus the destructive button only when it is the safest default.
Managing focus
Add the autofocus attribute to any interactive element inside the modal to focus it automatically when the modal opens, directing the user to the primary input or action.
Multiple modals
Modals can be stacked — opening a second modal from within the first layers it on top, with focus and backdrop managed automatically.
Scroll behavior
When content overflows, the modal body scrolls internally while the header and footer stay fixed. Compare scrolling inside the modal with scrolling the page behind it.
Trigger events
The modal emits events as it opens and closes, and reports how it was dismissed (backdrop, close button, Esc, or an action button). Open the console to inspect the events as you interact.
Scrollable terms
Add the scrollable attribute for long-form content such as terms and conditions, keeping the heading and footer actions in view while the body scrolls.
RTL
Modals follow the document or container direction. Toggle the direction to see the layout mirror.
Accessibility
- Always give the modal an accessible name by pointing
aria-labelledbyat theidof its header element. - The modal traps focus while open and restores focus to the triggering element when it closes. Add
autofocusto the element that should receive focus on open, such as the primary action button. - The modal can be dismissed with the Esc key, the close button, or by clicking the backdrop; intercept the
cancelevent and callpreventDefault()when you need to block dismissal. - Use
persistentfor flows that must be explicitly resolved — it disables backdrop and Esc dismissal and hides the close button, leaving only your action buttons.
API reference
Modal
Modal component is used to display content that temporarily blocks interactions with the main view of an application. Modal should be used sparingly and only when necessary.
<nord-modal></nord-modal>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
open | open | Controls whether the modal is open or not. | boolean | false |
size | size | Controls the max-width of the modal when open. | 's' | 'm' | 'l' | 'xl' | 'm' |
scrollable | scrollable | By default if a modal is too big for the browser window, the entire modal will scroll. This setting changes that behavior so that the body of the modal scrolls instead, with the modal itself remaining fixed. | boolean | false |
persistent | persistent | When true, the modal will not close when clicking the backdrop or pressing Escape, and the close button will be hidden. Only programmatic close or custom action buttons can dismiss the modal. | boolean | false |
Slots
| Slot name | Description |
|---|---|
Default slot | Default slot |
header | Slot which holds the header of the modal, positioned next to the close button. |
feature | Slot for full bleed content like an image. |
footer | Slot which is typically used to hold call to action buttons, but can also be used to build custom footers. |
Methods
| Method name | Parameters | Description |
|---|---|---|
showModal() => void | N/A | Show the modal, automatically moving focus to the modal or a child
element with an autofocus attribute. |
close(returnValue?: string, trigger?: Event) => void | returnValue: An optional value to indicate why the modal was closed.trigger: An optional event that triggered the close. | Programmatically close the modal. |
focus(options?: FocusOptions) => void | options: An object which controls aspects of the focusing process. | Programmatically focus the modal. |
| Event | Detail Type | Description |
|---|---|---|
cancel | ModalCancelEvent | Dispatched before the modal has closed when a user attempts to dismiss a modal. The event includes a trigger property containing the original event that caused the dismiss. Call preventDefault() on the event to prevent the modal closing. |
close | ModalCloseEvent | Dispatched when a modal is closed for any reason. The event includes an optional trigger property containing the original event that caused the close, if the modal was closed by a user action. |
CSS Properties
CSS Custom Properties provide more fine grain control over component presentation. We advise utilizing existing properties on the component before using these.
| Property | Description | Default |
|---|---|---|
--n-modal-padding-inline | Controls the padding on the sides of the modal, using our spacing tokens. | var(--n-space-m) |
--n-modal-padding-block | Controls the padding above and below the header of the modal, using our spacing tokens. | var(--n-space-m) |
--n-modal-max-inline-size | Controls the width of the modal. | 620px |
Parts
This component is made up of the following parts.
Modal Body
The main content region of a composed Modal. This is the
scrolling zone (when the modal is scrollable) between the fixed header and
footer, and carries the modal's body padding.
It occupies the modal's default slot, so place it as a direct child of
nord-modal (no slot attribute).
<nord-modal-body></nord-modal-body>Slots
| Slot name | Description |
|---|---|
Default slot | The modal body content. |
Modal Close
A standalone close control for a composed Modal.
Unlike the modal's built-in close button (which is locked into the header
zone), this part can be placed **anywhere** inside nord-modal — floated over
completely custom content, dropped into a footer as a "Cancel" button, or
nested inside your own layout. Clicking it dismisses the nearest
nord-modal through the same cancelable flow as the built-in button (the
modal's cancel event still fires and can be prevented).
When left empty it renders the default close "✕" icon button. Give it your own
control (a nord-button, button, or link) and it becomes a transparent
wrapper that turns that control into a close trigger:
The part is unpositioned by default — place it with your own styles (the
modal frame is position: relative, so it is the positioning context):
``html
<!-- floating icon button over custom content -->
<nord-modal-close
style="position: absolute; inset-block-start: var(--n-space-s); inset-inline-end: var(--n-space-s)"
></nord-modal-close>
<!-- any control becomes a close trigger -->
<nord-modal-close><nord-button>Cancel</nord-button></nord-modal-close>
``
<nord-modal-close></nord-modal-close>Props
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
label | label | Overrides the accessible label of the default close button. | string | undefined | — |
Slots
| Slot name | Description |
|---|---|
Default slot | Optional custom close control. When empty, a default icon button is rendered. |
Modal Footer
The footer region of a composed Modal. A fixed zone at
the bottom for call-to-action buttons; stacks on narrow viewports and lays
out as an end-aligned row on wider ones.
Auto-assigns itself to the modal's footer slot, so place it as a direct
child of nord-modal (no slot attribute needed).
<nord-modal-footer></nord-modal-footer>Slots
| Slot name | Description |
|---|---|
Default slot | The modal footer content. |
Modal Header
The header region of a composed Modal. A fixed zone that
sits beside the modal's close button; bring your own heading element.
Auto-assigns itself to the modal's header slot, so place it as a direct
child of nord-modal (no slot attribute needed).
<nord-modal-header></nord-modal-header>Slots
| Slot name | Description |
|---|---|
Default slot | The modal header content. |
Dependencies
This component is internally dependent on the following components:
- <nord-footer>
Footer
The footer is a block of designated space for providing additional information or actions that are positioned below the main content.
- <nord-icon>
Icon
Icons are used to provide additional meaning or in places where text label doesn’t fit. Icon component allows you to display an icon from the Nordicons library.
Design guidelinesFor designers
Usage
This section includes guidelines for designers and developers about the usage of this component in different contexts.
Do
- Use for confirmations and conditional changes.
- Use when the user is required to take an action.
- Use when you need to display content that temporarily blocks interactions with the main view of an application.
- Use when you need to ask a confirmation from a user before proceeding.
- Use for important warnings, as a way to prevent or correct critical errors.
Don’t
- Don’t use for nonessential information that is not related to the current userflow.
- Don’t use when the modal requires additional information for decision making that is unavailable in the modal itself.
- Don’t open a modal window on top of another modal.
Content guidelines
Modal title should be clear, accurate and predictable. Always lead with a strong verb that encourages action. To provide enough context to user, use the {verb} + {noun} content formula:
When writing modal titles, always write them in sentence case, not title case. The first word should be capitalized and the rest lowercase (unless a proper noun):
Avoid unnecessary words and articles in modal titles, such as “the”, “an” or “a”:
Avoid ending in punctuation:
Focus behaviour
- Use the
autofocusattribute to set the initial focus to the first location that accepts user input. - If it is a transactional modal without form inputs, then
autofocusshould be set on the primary button in the modal footer. This is for efficiency since most users will simply dismiss the dialog as soon as they have read the message. - If the modal contains a form, use
autofocusin the first form field. - Focus remains trapped inside the modal dialog until it is closed.
- For more examples and best practices, please see WAI-ARIA Authoring Practices Modal Dialog Example.