Components · Notifications

Modal

A modal is the most disruptive notification. It blocks the page until the user makes a decision, so use it only when the user must confirm or choose before going on.

Tokens, sizes, measurements and requirements. Values come from the live token package and from E-Com Modal.

Design Tokens

Resolved from the live token package.

PartRoleTokenValue

Sizes

Setup per breakpoint

Two sizes to choose between, Small and Large (see Sizes on Examples & Guidelines). The modal has three setups, one per Figma breakpoint group. Tablet (sm) is not the desktop setup and not the mobile one: it has the narrower Large (576px) and the mobile type, but still a centered card.

Desktop (769px+)Tablet, sm (640–768px)Mobile, xs (below 640px)
Figma breakpointXLarge-Large-MediumSmallXSmall (Large and Small only)
Small440px wide, centered440px wide (adapts to the available width), centeredCentered card, height by content, at least 16px side margin: max width 440px; 343px on a 375px viewport
Large705px wide, centered576px wide (adapts to the available width), centeredFills the whole screen (375 × 100dvh): content on top, buttons pinned to the bottom
HeightBy content, limited by the available screen heightBy content, limited by the available screen heightSmall: by content, limited by the screen height. Large: 100dvh
Padding24px24px16px
TypeDesktop sizes (label 14, title 20, body 17)Mobile sizes (label 12, title 18, body 16)Mobile sizes
Space above the buttons32px24px24px
OverlayDims the pageDims the pageSmall: dims the page. Large: covers it completely

The panel is never wider than the window: max-width: calc(100vw - 32px) and max-height: calc(100dvh - 32px); longer content scrolls inside the panel. On mobile Small keeps 16px to the edges (max-width: calc(100vw - 32px), 343px on a 375px viewport). Large is top: 0; left: 0; width: 100%; height: 100dvh; max-width: none, so it has no margin to the screen.


Measurements

Dimensions

The padding of the modal panel. The numbers are read from the component.

Breakpoint
A Small modal at true size. Change the Breakpoint to see the mobile values.
AttributeDesktop (769px+) and tabletMobile (below 640px)
Padding24px16px
Space above the buttons32px (tablet: 24px)24px
Header gap, label to title8px8px
Title to body8px (desktop 8px)8px
Gap between the buttons8px8px
Buttons32px high32px high

Spacing

The same distances as spacing tokens.

PartValue
Padding, tablet and desktopspace-24
Padding, mobilespace-16
Above the buttons, desktopspace-32
Above the buttons, mobilespace-24
Label, title and body gapsspace-8
Between the buttonsspace-8
Header to ×space-12

Elevation

PartTokenValue
Panelshadow-elevation-b-100The highest bottom shadow.
Overlaysurface-opacity-black-20Dims the page behind the panel. Z-index 9998; the panel is 9999.

Typography and spacing

ElementDesktop (769px+)Tablet and mobile
Labelalt-label-sm 14/14, 0.56px, 500, uppercase12/12, 0.48px
Titletitle-md 20/24, bold18/22, bold
Bodybody-md 17/24, 0.32px16/22, 0.32px
Buttons32px high, label-sm 14px, 0.56px32px high, 14px, 0.42px
Space above buttons32px24px
Gap label to title, header to body8px8px

Structure

Elements

ElementClassNotes
Overlaymodal-overlayFixed, covers the page.
Panelmodal modal--small|largerole="dialog", aria-modal="true", aria-labelledby.
Headermodal__header, modal__header-textLabel, title and the ×.
Label, title, bodymodal__label, modal__title, modal__bodyThe label is optional.
Footermodal__footerBlank Cancel and Primary buttons.
Closeicon-btn icon-btn--closeAlways present.

Types

Two sizes: Small and Large. With or without a label. No status and no emphasis.

Width

See Sizes above.


Motion

MotionPropertyDurationEasing
EnterOverlay: opacity. Panel: opacity and translate from 48px below (space-48) to 0duration-fast-4 (200ms), --modal-in-durationease-decelerate-emphasized, --modal-in-ease
ExitOverlay: opacity. Panel: opacity and translate from 0 to 48px below (space-48)duration-fast-3 (150ms), --modal-out-durationease-accelerate-generic, --modal-out-ease

A short move (48px) with the fade, no scale. Why 48px, and why no token: the move is short (a small share of the view), so it uses the Fast durations of eco-motion; 48px is a trial (24px was the first value): it is a clear lift, and still a short move, so the Fast durations apply. The value is space-48, an existing spacing token, written in the keyframes. There is no distance token and no custom property for it: Carbon, Adobe Spectrum and Atlassian keep duration and easing as the motion tokens and leave the travel distance to the component (Atlassian puts it inside a per-component token such as motion.modal.enterModal). Add a shared distance scale only if a second component needs the same move. The panel uses translate, not transform, so the centering is untouched. The exit is shorter than the enter and accelerates, as when an element disappears (eco-motion); Material, Carbon and Atlassian also close faster than they open. The script adds is-leaving and removes the dialog when the animation has run. Reduced motion: no fade, removed at once. Compare other values in the live Motion section on Examples & Guidelines.


Behavior

InputResult
Click ×Closes the modal.
ESCCloses the modal.
Click the overlayCloses the modal. A click inside the panel does not.
OpenFocus moves into the dialog. Page scroll is locked (body.has-modal).
Tab / Shift+TabStays inside the dialog.
CloseFocus returns to the button that opened it.
Markuprole="dialog", aria-modal="true", aria-labelledby pointing at the title.

Accessibility Requirements

TopicRequirement
Markuprole="dialog", aria-modal="true", aria-labelledby pointing at the title.
FocusMoves into the dialog on open, is trapped inside it and returns to the opener on close (WCAG 2.4.3). The ring is 2px, border-focus (WCAG 2.4.7).
CloseThree ways, always: ×, ESC and the overlay.
ScrollThe page behind does not scroll while the modal is open.
Reduced motionNo fade under prefers-reduced-motion: reduce.