Overlays
Modal panels on a navy scrim (DS-012), multi-step headers, toasts, popover menus, tooltips and inline notices. Layering follows the z-index ladder (DS-013).
Modal
Use a native <dialog>: showModal() gives the scrim via ::backdrop, focus trapping and Escape for free. The same classes work on a div inside .saga-scrim.
<button class="saga-btn" onclick="document.getElementById('demo-dialog').showModal()">Open Edit Session</button>
<button class="saga-btn saga-btn--secondary" onclick="document.getElementById('demo-steps-dialog').showModal()">Open Configure Period</button>
<dialog class="saga-modal" id="demo-dialog" aria-labelledby="demo-dialog-title">
<form method="dialog" style="display:contents">
<div class="saga-modal__header">
<h2 class="saga-modal__title" id="demo-dialog-title">Edit Session</h2>
<button class="saga-btn saga-btn--quiet saga-btn--icon saga-modal__close" aria-label="Close" value="cancel"><iconify-icon icon="material-symbols-light:close-rounded"></iconify-icon></button>
</div>
<div class="saga-modal__body">
<div class="saga-field"><label class="saga-label" for="m-title">Session Title</label><input class="saga-input" id="m-title" value="Out Of Window Test - Early"></div>
</div>
<div class="saga-modal__footer">
<div class="saga-modal__footer-end">
<button class="saga-btn saga-btn--secondary" value="cancel">Cancel</button>
<button class="saga-btn" value="save">Save</button>
<button class="saga-btn saga-btn--danger" value="delete">Delete</button>
</div>
</div>
</form>
</dialog>
Shown inline
Edit Session
<div class="saga-modal" role="dialog" aria-labelledby="inl-title" aria-modal="true" style="margin:0 auto">
<div class="saga-modal__header">
<h2 class="saga-modal__title" id="inl-title">Edit Session</h2>
<button class="saga-btn saga-btn--quiet saga-btn--icon saga-modal__close" aria-label="Close"><iconify-icon icon="material-symbols-light:close-rounded"></iconify-icon></button>
</div>
<div class="saga-modal__body">
<div class="saga-field"><label class="saga-label" for="m2-title">Session Title</label><input class="saga-input" id="m2-title" value="Out Of Window Test - Early"></div>
</div>
<div class="saga-modal__footer">
<div class="saga-modal__footer-end">
<button class="saga-btn saga-btn--secondary">Cancel</button>
<button class="saga-btn">Save</button>
<button class="saga-btn saga-btn--danger">Delete</button>
</div>
</div>
</div>
Confirm dialog
.saga-modal--confirm is 440px: a question for a title, one secondary paragraph, two buttons, role="alertdialog", the safe button focused first. Caution confirms use .saga-btn--caution (--color-warning-strong) and a --color-warning-border top edge.
<dialog class="saga-modal saga-modal--confirm" id="demo-confirm" aria-labelledby="dc-title">
<form method="dialog" style="display:contents">
<div class="saga-modal__header"><h2 class="saga-modal__title" id="dc-title">Delete this session?</h2></div>
<div class="saga-modal__body"><p class="text-secondary">Students will lose their place in Pod 6. This cannot be undone.</p></div>
<div class="saga-modal__footer"><div class="saga-modal__footer-end"><button class="saga-btn saga-btn--secondary" value="cancel" autofocus>Cancel</button><button class="saga-btn saga-btn--danger" value="delete">Delete session</button></div></div>
</form>
</dialog>
Shown inline: danger and caution
Delete this session?
Students will lose their place in Pod 6. This cannot be undone.
Move 3 students to Pod 2?
They keep their attendance history. Their current tutor will see the change on the next schedule refresh.
<div class="saga-modal saga-modal--confirm" role="alertdialog" aria-modal="true" aria-labelledby="cf-title" aria-describedby="cf-body" style="margin:0 auto">
<div class="saga-modal__header"><h2 class="saga-modal__title" id="cf-title">Delete this session?</h2></div>
<div class="saga-modal__body"><p class="text-secondary" id="cf-body">Students will lose their place in Pod 6. This cannot be undone.</p></div>
<div class="saga-modal__footer">
<div class="saga-modal__footer-end">
<button class="saga-btn saga-btn--secondary">Cancel</button>
<button class="saga-btn saga-btn--danger">Delete session</button>
</div>
</div>
</div>
<div class="saga-modal saga-modal--confirm" role="alertdialog" aria-modal="true" aria-labelledby="cf2-title" style="margin:0 auto;border-top:var(--space-xs) solid var(--color-warning-border)">
<div class="saga-modal__header"><h2 class="saga-modal__title" id="cf2-title">Move 3 students to Pod 2?</h2></div>
<div class="saga-modal__body"><p class="text-secondary">They keep their attendance history. Their current tutor will see the change on the next schedule refresh.</p></div>
<div class="saga-modal__footer">
<div class="saga-modal__footer-end">
<button class="saga-btn saga-btn--secondary">Never mind</button>
<button class="saga-btn saga-btn--caution">Yes, move them</button>
</div>
</div>
</div>
Framed shell with a local scrim and toast stack
A .saga-shell--framed fills its positioned frame instead of the viewport (a decision-board scene, a preview). Inside it, .saga-scrim--local and .saga-toast-stack--local are absolute to the frame, so overlays stay in the scene. A native <dialog> always goes to the top layer, so a framed scene uses the div form (DS-118).
Demo Program 08/17
A framed shell: the scrim and toast stack stay inside this box.
Discard changes?
Your edits to Period 1 will be lost.
<div class="demo-frame">
<div class="saga-shell saga-shell--framed">
<nav class="saga-nav" aria-label="Scene nav"><div class="saga-nav__logo"></div><ul class="saga-nav__items"><li><a class="saga-nav__item" href="#" aria-current="page"><iconify-icon icon="material-symbols-light:calendar-month-outline-rounded"></iconify-icon> Sessions</a></li></ul></nav>
<div class="saga-shell__main">
<header class="saga-topbar"><h1 class="saga-topbar__title">Demo Program 08/17</h1></header>
<main class="saga-page"><p class="text-secondary">A framed shell: the scrim and toast stack stay inside this box.</p></main>
</div>
<div class="saga-scrim saga-scrim--local">
<div class="saga-modal saga-modal--confirm" role="alertdialog" aria-modal="true" aria-labelledby="cf3-title">
<div class="saga-modal__header"><h2 class="saga-modal__title" id="cf3-title">Discard changes?</h2></div>
<div class="saga-modal__body"><p class="text-secondary">Your edits to Period 1 will be lost.</p></div>
<div class="saga-modal__footer"><div class="saga-modal__footer-end"><button class="saga-btn saga-btn--secondary">Keep editing</button><button class="saga-btn saga-btn--danger">Discard</button></div></div>
</div>
</div>
<div class="saga-toast-stack saga-toast-stack--local"><div class="saga-toast saga-toast--success" role="status"><span class="saga-toast__msg">Period 2 saved.</span></div></div>
</div>
</div>
Steps header
A multi-step modal puts .saga-steps directly under the header. Numbers are auto-counted when .saga-step__num is empty; aria-current="step" marks the active step, data-complete a finished one.
Period 2 | Configure Period
- Configure Period
- Build Pods
Step content goes here.
<div class="saga-modal saga-modal--large" role="dialog" aria-labelledby="st-title" aria-modal="true" style="margin:0 auto">
<div class="saga-modal__header">
<h2 class="saga-modal__title" id="st-title"><em>Period 2</em> | Configure Period</h2>
<button class="saga-btn saga-btn--quiet saga-btn--icon saga-modal__close" aria-label="Close"><iconify-icon icon="material-symbols-light:close-rounded"></iconify-icon></button>
</div>
<ol class="saga-steps">
<li class="saga-step" aria-current="step"><span class="saga-step__num"></span> Configure Period</li>
<li class="saga-step"><span class="saga-step__num"></span> Build Pods</li>
</ol>
<div class="saga-modal__body">
<p class="text-secondary">Step content goes here.</p>
</div>
<div class="saga-modal__footer">
<div class="saga-modal__footer-end">
<button class="saga-btn saga-btn--secondary">Cancel</button>
<button class="saga-btn">Continue</button>
</div>
</div>
</div>
Toasts
Bottom-right stack, navy surface, a 4px colored left edge (DS-102, DS-115). Dwell is 3500ms + 50ms per character, clamped to 4–15s. Enter and exit animate opacity and transform only; under reduced motion the rise collapses and the fade stays.
<button class="saga-btn saga-btn--secondary" onclick="showToast('Roster uploaded.', 'success')">Success toast</button>
<button class="saga-btn saga-btn--secondary" onclick="showToast('Session saved without a period — it will not appear on the schedule.', 'warning', 'Undo')">Warning with action</button>
<button class="saga-btn saga-btn--secondary" onclick="showToast('Could not reach the server. Your changes were not saved.', 'danger')">Danger toast</button>
<button class="saga-btn saga-btn--secondary" onclick="showToast('You have 2 students online now, waiting in Period 1 (B.1).', '', 'Join')">Default</button>
<div class="saga-toast-stack" style="position:static;width:auto;align-items:stretch">
<div class="saga-toast saga-toast--success" role="status"><span class="saga-toast__icon"><iconify-icon icon="material-symbols-light:check-circle-outline-rounded"></iconify-icon></span><span class="saga-toast__msg">Roster uploaded.</span><button class="saga-toast__close" aria-label="Dismiss"><iconify-icon icon="material-symbols-light:close-rounded"></iconify-icon></button></div>
<div class="saga-toast saga-toast--warning" role="status"><span class="saga-toast__icon"><iconify-icon icon="material-symbols-light:warning-outline-rounded"></iconify-icon></span><span class="saga-toast__msg">Session saved without a period.</span><button class="saga-toast__action">Undo</button><button class="saga-toast__close" aria-label="Dismiss"><iconify-icon icon="material-symbols-light:close-rounded"></iconify-icon></button></div>
<div class="saga-toast saga-toast--danger" role="alert"><span class="saga-toast__icon"><iconify-icon icon="material-symbols-light:error-outline-rounded"></iconify-icon></span><span class="saga-toast__msg">Could not reach the server.</span><button class="saga-toast__close" aria-label="Dismiss"><iconify-icon icon="material-symbols-light:close-rounded"></iconify-icon></button></div>
<div class="saga-toast" role="status"><span class="saga-toast__msg">2 students are waiting in Period 1 (B.1).</span><button class="saga-toast__action">Join</button></div>
</div>
Popover menu
- Session
<ul class="saga-popover" role="menu" aria-label="Session actions">
<li class="saga-popover__heading">Session</li>
<li><button class="saga-popover__item" role="menuitem"><iconify-icon icon="material-symbols-light:edit-outline-rounded"></iconify-icon> Edit session</button></li>
<li><button class="saga-popover__item" role="menuitem"><iconify-icon icon="material-symbols-light:content-copy-outline-rounded"></iconify-icon> Duplicate</button></li>
<li><button class="saga-popover__item is-active" role="menuitemradio" aria-checked="true"><iconify-icon icon="material-symbols-light:calendar-view-month-outline-rounded"></iconify-icon> Month view</button></li>
<li><button class="saga-popover__item" role="menuitem" disabled><iconify-icon icon="material-symbols-light:lock-outline"></iconify-icon> Lock (no permission)</button></li>
<li class="saga-popover__divider" role="separator"></li>
<li><button class="saga-popover__item" role="menuitem" data-danger><iconify-icon icon="material-symbols-light:delete-outline-rounded"></iconify-icon> Delete session</button></li>
</ul>
Tooltip
White with a --color-border-strong hairline and --shadow-md, as dash's core-ui Tooltip renders (DS-057, DS-120); --filled is the primary-blue variant for the info-icon trigger; --rich is left-aligned with a semibold .saga-tooltip__title first line.
<span class="saga-tooltip" role="tooltip">Configure program</span>
<span class="saga-tooltip" role="tooltip">Students and tutors always meet in the same pods. Tooltips wrap at 16rem.</span>
<span class="saga-tooltip saga-tooltip--filled" role="tooltip">Search pages <kbd>⌘K</kbd></span>
<span class="saga-tooltip saga-tooltip--rich" role="tooltip"><span class="saga-tooltip__title">Aaliyah Lawrence</span>Period 1 · Pod 6 · joined 09/02/2026</span>
Notices
Levels are the modifier: bare .saga-notice is the notice level (--notice is an accepted alias), then --warning, --danger, --success, and --attention for a standing problem.
<div class="saga-notice" role="status"><span class="saga-notice__icon"><iconify-icon icon="material-symbols-light:info-outline-rounded"></iconify-icon></span><div class="saga-notice__body"><span class="saga-notice__title">Preview deploy skipped</span> Switch the PR to ready for review to trigger it.</div><button class="saga-btn saga-btn--quiet saga-btn--icon saga-btn--sm saga-notice__dismiss" aria-label="Dismiss"><iconify-icon icon="material-symbols-light:close-rounded"></iconify-icon></button></div>
<div class="saga-notice saga-notice--warning" role="status"><span class="saga-notice__icon"><iconify-icon icon="material-symbols-light:warning-outline-rounded"></iconify-icon></span><div class="saga-notice__body">This session has no period and will not appear on the schedule. <button class="saga-notice__action">Assign a period</button></div></div>
<div class="saga-notice saga-notice--danger" role="alert"><span class="saga-notice__icon"><iconify-icon icon="material-symbols-light:error-outline-rounded"></iconify-icon></span><div class="saga-notice__body"><span class="saga-notice__title">Upload failed</span> 3 rows had an unknown school code.</div></div>
<div class="saga-notice saga-notice--success" role="status"><span class="saga-notice__icon"><iconify-icon icon="material-symbols-light:check-circle-outline-rounded"></iconify-icon></span><div class="saga-notice__body">Program configuration saved.</div></div>
<div class="saga-notice saga-notice--attention" role="status"><span class="saga-notice__icon"><iconify-icon icon="material-symbols-light:flag-outline-rounded"></iconify-icon></span><div class="saga-notice__body"><span class="saga-notice__title">Needs attention</span> 2 pods have no tutor assigned.</div></div>