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.
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
onDismissso 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.