ZEROlobby
22/22 strict⌘Kvisitor
skip to main
ADR-025
skin
——:——:——zcovenant · audit
overlays· chapter 31 · 10 primitives · 3 anchors · 3 dismissals

ten overlays · one grammar · no ad-hoc backdrops

every floating surface in the brand system declares one of three anchors and one of three dismissal modes. tooltip, popover, dropdown, dialog, and toast came first; the audit's eighth gap was the missing five — sheet, drawer, accordion, context menu, and alert-dialog. they ship together so the covenant detector can grep one set of data-dismissal attributes and every consumer reaches the same chrome by typing.

board · live

five overlay primitives reachable from one stage · tooltip · popover · sheet · drawer · dialog · toast. dial each anchor and watch the floating-ui math respond. the receipt below traces the contract: anchor · dismissal · decision-node kind.

overlay board · live· five primitives · three anchors · three dismissals · open any · the receipt below traces the contractidle
tooltiphover · 8 placements · viewport anchor · casual
popoverclick · 4 placements · viewport anchor · casual
sheetedge anchor · top or bottom · scroll-locked · casual
draweredge anchor · left or right · optional persistent · casual
dialogviewport anchor · scroll-locked · committed
toastedge anchor · 4 verbs · 4s auto-dismiss · informational

toasts mount in the global ToastProvider · prefer-reduced-motion is respected

trade receipt
last overlay
idle
last action
no overlay opened yet
at
tooltip
placement top
popover
placement bottom-start
sheet
edge bottom
drawer
edge right · modal
01 · vocabularyten overlays · five existing · five new

the ten-overlay vocabulary

plate · A · every overlay primitive in @zero/uiADR-010 · ADR-025
metric
overlay-vocabulary
unit
primitives
window
static
agg
identity
source
packages/ui/src/index.ts
fresh
last build
#primitiveanchordismissalSSR-cleanuse case
17Tooltipanchorcasualnolabel-on-hover · keyboard-revealable
18Popoveranchorcasualnoclick-anchored panel · arbitrary content
19Dropdownanchorcasualnoselect-style menu · keyboard nav · typeahead
20Dialogviewportcasualnomodal panel · backdrop · scroll-lock
21ToastProvideredgemanualnolive region · auto-dismiss by timer
67Sheetedge (top/bottom)casualnomobile bottom-sheet · settings · file detail
68Draweredge (left/right)casual or manual (persistent)nodesktop side-rail · contextual operator detail
69Accordioninlinen/ayessibling-grouped collapsible · settings · FAQ
70ContextMenuanchor (cursor)casualnoright-click verbs · chart cell · row actions
71AlertDialogviewportcommittednodestructive confirm · refuse posture · forced choice
why ten, not five or twenty
five was incomplete (no mobile sheet, no desktop drawer, no collapsible group, no right-click verbs, no committed confirm). twenty would duplicate (every component library that ships twenty overlays has three flavours of "modal" and four flavours of "menu"). ten covers every consumer surface in cockpit · league · coliseum · studio · the future getzero.dev, and every primitive maps cleanly to one of three anchors and one of three dismissals.
02 · the five newSheet · Drawer · Accordion · ContextMenu · AlertDialog

the five primitives ADR-025 lands

plate · B · Accordion · live · the only SSR-clean overlaysingle mode
metric
overlay-vocabulary
unit
primitives
window
static
agg
identity
source
packages/ui/src/Accordion.tsx
fresh
last build
tonecovenant rule #4

every overlay carries the dark-only substrate, the amber focus ring, and the bone-on-ink hierarchy. nothing inverts when an overlay opens; the user's eye does not re-acclimate.

paletteci:amber

amber stays under the 7% surface ceiling even with an overlay open. AlertDialog tone='refuse'is the only overlay that paints with amber as a hairline, and even there it's a one-pixel border, not a fill.

cadencechapter 03 · motion

slide-in animations resolve in 220 ms via the four-clock organism's --ease-step. the refuse variant uses --ease-refuse — a slight backstep on entry that earns its own visual weight without flashbang attention.

plate · C · dossier matrix · five newfrom .meta
metric
overlay-vocabulary
unit
primitives
window
static
agg
identity
source
packages/ui/src/{Sheet,Drawer,Accordion,ContextMenu,AlertDialog}.tsx
fresh
last build
primitivenumclsheadline tokensstates
Sheet67.zero-sheet--ink-1 · --bone-1 · --hair-3 · --radius · --ease-stepclosed · opening · open · closing
Drawer68.zero-drawer--ink-1 · --bone-1 · --hair-3 · --shadow-4 · --ease-stepclosed · opening · open · closing · persistent
Accordion69.zero-accordion--ink-1 · --bone-1 · --hair-2 · --s-3 · --s-5idle · open · disabled
ContextMenu70.zero-context-menu--ink-1 · --bone-1 · --bone-3 · --hair-2 · --amberclosed · open · item-hover · item-active · item-refuse
AlertDialog71.zero-alert-dialog--ink-1 · --ink-2 · --amber · --shadow-4 · --ease-refuseclosed · open · tone-normal · tone-refuse
03 · anchoring grammarviewport · edge · anchor

three ways an overlay attaches to the surface

plate · D · anchoring grammarexhaustive
metric
overlay-vocabulary
unit
primitives
window
static
agg
identity
source
packages/ui/src/overlay-anchor.ts
fresh
last build
anchorpositionbackdropexample
viewportcentered · full screen reachfull · scroll-lockedDialog · AlertDialog
edgepinned to one of top | bottom | left | rightfull (default) · or none (persistent: true)Sheet · Drawer · Toast
anchorrelative to a trigger element or cursornone · click-outside dismissesTooltip · Popover · Dropdown · ContextMenu
why three anchors, not five
we considered portal-fixed (toast-style, but configurable) and inline-popover (popover that flows in document order). both collapsed cleanly into the three above. fewer anchors means fewer permutations the covenant detector has to grep, and one consistent positioning model across the catalog.
04 · dismissal grammarcasual · committed · manual

three ways an overlay closes

plate · E · dismissal grammarexhaustive
metric
overlay-vocabulary
unit
primitives
window
static
agg
identity
source
packages/ui/src/overlay-anchor.ts
fresh
last build
modeescape dismissesoutside-press dismissesused by
casualyesyesTooltip · Popover · Dropdown · Dialog · Sheet · Drawer · ContextMenu
committednonoAlertDialog (forces explicit confirm/cancel)
manualnonoToast (timer-driven) · Drawer (persistent: true)
committed dismissal is brand-grade
when you want the user to confirm a destructive action, you must reach for AlertDialog, not Dialog. the typing guides you: Dialog has no tone='refuse'; AlertDialog has no dismissal='casual'. the system will not let you ship an outside-press-dismissable demolition confirm.
05 · refuse postureAlertDialog tone='refuse'

the brand-verb overlay

aspecttone='normal'tone='refuse'
background--ink-1--ink-2 (one step deeper)
bottom edge1 px --hair-31 px --amber (the only amber paint)
confirm label defaultconfirmrefuse (the brand verb · article I)
slide-in easing--ease-step--ease-refuse (slight backstep on entry)
covenant rule#14 · brand verb consistency · enforced by ci:rewrite
why the refuse variant exists
article I of the constitution says we refuse loudly, deterministically, and on cue. the primitive shape now matches the verb shape. when an external coding agent assembles a demolition flow from @zero/ui, it inherits the refuse posture by typing — not by reading prose. the brand system does the work once; every consumer gets it for free.