Zetta v1.6

Components · Overlays & menus

Blanket

The dimming scrim behind a modal or drawer — a fixed full-screen layer at the blanket z-index that darkens the page and catches outside clicks. A transparent variant captures clicks without darkening (for dismissable popovers).

Preview

Page content
A modal sits above the blanket

Build with the skill

No package to install — hand this to your AI to generate or migrate the component in your stack.

Prompt for your AI
Apply the Zetta "Blanket" component to this project using the zetta-design-md skill.

WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `blanket` spec (variants: default, transparent) and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `blanket` spec in this project's stack.

AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.

ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility.

Anatomy & rules

╔══════════════════════════════════════╗
║                                      ║
║   [dimmed page content]              ║  ← blanket covers this
║                                      ║
║         ╭──────────────────╮         ║
║         │   Modal / Drawer │         ║  ← content above blanket
║         ╰──────────────────╯         ║
╚══════════════════════════════════════╝
State Visual
Default {colors.overlay} semi-transparent fill, covers full viewport
Transparent backgroundColor: transparent, pointerEvents: none — for non-modal loading contexts
Entering Fade in: opacity 0 → 1, {motion.duration-slow}
Exiting Fade out: opacity 1 → 0, {motion.duration-moderate}

When to use

  • Behind all modal dialogs.
  • Behind drawers and side panels when they are in modal (non-inline) mode.
  • Behind full-screen overlays and image lightboxes.

When not to use

  • Behind tooltips or non-modal popovers — those do not require a blanket.
  • In inline/non-modal modes of drawers — omit the blanket so the page remains interactive.

Do

  • Always provide onDismiss so the blanket acts as a click-to-close target.
  • Mount blanket and the overlaid content as siblings — never nest the content inside the blanket element.

Don't

  • Don't render multiple blankets simultaneously. If modals can stack, use a single blanket beneath the topmost modal.

Not applicable — blanket carries no text content. It is a purely visual/interactive layer.

Keyboard

Blanket is a visual overlay layer with no interactive keyboard behavior of its own. Click-to-dismiss is handled by the parent component (Modal, Drawer) via their Escape key behavior.

Accessibility

  • aria-hidden="true" on the blanket element — it is decorative.
  • Dismissal must be available from the keyboard on the associated overlay, not by blanket click alone.
  • Focus must be trapped inside the modal/drawer — users should never be able to move focus to elements behind the blanket.

Spec

Values and token references resolved straight from the Zetta spec.

blanket
position
fixed
inset
0
backgroundColor
{colors.overlay}
zIndex
{elevation.z-index.blanket}
opacity
1
pointerEvents
auto
blanket-transparent
backgroundColor
transparent
pointerEvents
none

Known gaps

  • Stacked blanket z-index strategy — when a dialog opens over a drawer (both needing a blanket), one blanket must be reused or z-index values must be coordinated. Not yet specified.
  • Blanket animation — enter/exit transition (fade) not yet specified in motion tokens.