Modals
Desktop modals in Puppertino are compact alert dialogs for pointer-driven interfaces: a translucent glass body, 260px width, 34px radius, and pill actions arranged either as a vertical stack or a horizontal pair.
When to use them
Use them for short confirmation moments, destructive warnings, and small decision points. Avoid them for large forms, long reading flows, or anything that needs a lot of scrolling.
Preview
Desktop modals use two layouts. Stacked handles three actions. Split handles two.
Variants
Two alert layouts are available:
.p-desktop-modal--stackedfor three actions..p-desktop-modal--splitfor two actions placed side by side.
Anatomy
| Class | Role |
|---|---|
.p-modal-background | Shared backdrop layer for all modals on the page. |
.p-modal | Base modal hook used by the JS manager. |
.p-desktop-modal | Desktop alert shell. Centers the modal and handles the open transition. |
.p-desktop-modal__surface | Glass surface. Radius 34, keyline, inner top and bottom highlight, and shadow. |
.p-desktop-modal__body | Title and description group. |
.p-desktop-modal__actions | Action row or stack. |
.p-desktop-modal__action | Shared pill button styling for alert actions. |
.p-desktop-modal__action--primary | Filled affirmative action. |
.p-desktop-modal__action--secondary | Neutral cancel action. |
.p-desktop-modal__action--destructive | Destructive action with red tint. |
Usage
The trigger uses data-p-open-modal with the selector of the modal you want to open. Add data-p-close-on-outside="true" if clicking the backdrop should dismiss it, and add data-p-cancel to any action that should close the active modal automatically.
<button class="p-button p-button-primary" data-p-open-modal="#example-modal">
Open Alert
</button>
<div class="p-modal-background">
<div
class="p-modal p-desktop-modal p-desktop-modal--split"
id="example-modal"
data-p-close-on-outside="true"
role="dialog"
aria-modal="true"
aria-hidden="true"
aria-labelledby="example-modal-title"
>
<div class="p-desktop-modal__surface">
<div class="p-desktop-modal__body">
<h2 class="p-desktop-modal__title" id="example-modal-title">
Save this message as a draft?
</h2>
<p class="p-desktop-modal__description">
This message has not been sent and<br />
contains unsaved changes. You can save<br />
it as a draft to work on later.
</p>
</div>
<div class="p-desktop-modal__actions">
<button class="p-desktop-modal__action p-desktop-modal__action--secondary" data-p-cancel>
Cancel
</button>
<button class="p-desktop-modal__action p-desktop-modal__action--primary">
Save
</button>
</div>
</div>
</div>
</div>
Action layout
Use the stacked variant when you need three clear outcomes. Order the actions primary first, destructive second, and cancel last.
<div class="p-desktop-modal__actions">
<button class="p-desktop-modal__action p-desktop-modal__action--primary">Save</button>
<button class="p-desktop-modal__action p-desktop-modal__action--destructive">Don’t Save</button>
<button class="p-desktop-modal__action p-desktop-modal__action--secondary" data-p-cancel>Cancel</button>
</div>
Use the split variant when the choice is binary.
<div class="p-desktop-modal__actions">
<button class="p-desktop-modal__action p-desktop-modal__action--secondary" data-p-cancel>Cancel</button>
<button class="p-desktop-modal__action p-desktop-modal__action--primary">Save</button>
</div>
JavaScript API
The modal manager initializes automatically when src/js/modals.js is loaded.
PuppertinoModalManager.openModal("#example-modal");
PuppertinoModalManager.closeActiveModal();
PuppertinoModalManager.closeModal("#example-modal");
PuppertinoModalManager.isModalOpen("#example-modal");
Surface
The surface is rgba(247, 247, 247, 0.73) over a 30px blur, so the backdrop shows through at roughly a quarter strength. A 0.5px dark keyline sits just outside the edge. A bright 1px line runs along the inside of the top and bottom edges, fading into a soft glow about 8px deep; the sides get the keyline only. The shadow is 0 18px 48px at 25%. The radius is a plain 34px arc.
The body sits 20px from the top and 16px from the sides and bottom. The message ends 16px above the first action. Stacked actions are 28px tall with 6px between them; side-by-side actions are 32px tall with 8px between them.
Actions: the primary is the control accent (#0088FF, dark #0091FF). Cancel is a quiet fill, black at 10% (dark: white at 8.5%), so it darkens with the surface instead of sitting on it as a flat gray. Destructive uses the vibrant red because it sits on glass: #F52F32 at 23% behind a #E11B1E label in light mode, #FF4747 at 23% behind a #FF4747 label in dark mode. Any .p-button you place inside the alert is vibrant too (see Buttons).
Dark mode
The surface turns into a near-black glass, rgba(26, 26, 26, 0.9), with a darker keyline and a dimmer inner highlight (white at 20%). The shadow deepens to 45%.
Accessibility
- Add
role="dialog"andaria-modal="true"to every modal. - Point
aria-labelledbyat the modal title. - The manager moves focus into the modal when it opens and restores focus to the trigger when it closes.
Escapecloses the active modal.data-p-cancelkeeps cancel actions semantic while still closing the dialog.- With
prefers-reduced-transparencyorprefers-contrast: morethe surface becomes opaque (#EBEBEB, dark#1A1A1A). Increased contrast also draws a solid 1px edge.
Notes
- The mobile modal classes are unaffected. The desktop alert variant is additive.
- The backdrop is intentionally restrained: a light dim layer, no heavy blur. The card itself carries the visual treatment.
- The split layout collapses to a vertical stack on narrow screens.