Desktop components

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:

Anatomy

ClassRole
.p-modal-backgroundShared backdrop layer for all modals on the page.
.p-modalBase modal hook used by the JS manager.
.p-desktop-modalDesktop alert shell. Centers the modal and handles the open transition.
.p-desktop-modal__surfaceGlass surface. Radius 34, keyline, inner top and bottom highlight, and shadow.
.p-desktop-modal__bodyTitle and description group.
.p-desktop-modal__actionsAction row or stack.
.p-desktop-modal__actionShared pill button styling for alert actions.
.p-desktop-modal__action--primaryFilled affirmative action.
.p-desktop-modal__action--secondaryNeutral cancel action.
.p-desktop-modal__action--destructiveDestructive 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

Notes

Copied