Styling contract
Headless popover publishes slot and state hooks for the root, trigger, panel, and close controls. Owners are responsible for the anchored positioning and visual treatment of the panel.
Slot and state hooks
[data-slot="popover"]mirrorsdata-open,data-state,data-side,data-align, anddata-disabled.[data-slot="popover-trigger"]exposesaria-haspopup,aria-controls,aria-expanded, and matching open-state hooks.[data-slot="popover-panel"]carriesdata-side,data-align,data-state, and[hidden].[data-slot="popover-close"]gives you a stable selector for in-panel dismissal actions.
CSS starter
headless-popover.css
css
[data-slot="popover"] {
position: relative;
}
[data-slot="popover-trigger"] {
border-radius: 0.75rem;
min-height: 2.25rem;
padding-inline: 0.85rem;
}
[data-slot="popover-panel"] {
background: var(--tng-semantic-background-surface);
border: 1px solid var(--tng-semantic-border-strong);
border-radius: 0.9rem;
box-shadow: 0 22px 42px rgb(2 6 23 / 22%);
display: grid;
gap: 0.75rem;
left: 0;
min-inline-size: 16rem;
padding: 1rem;
position: absolute;
top: calc(100% + 0.5rem);
z-index: 50;
}
[data-slot="popover-panel"][data-side="top"] {
bottom: calc(100% + 0.5rem);
top: auto;
}
[data-slot="popover-panel"][data-align="end"] {
left: auto;
right: 0;
}
[data-slot="popover-panel"][hidden] {
display: none !important;
}
Owner guidance
- Anchor the panel with your own CSS; the primitive does not measure or reposition the overlay.
- Use
data-sideanddata-alignas styling signals for directional placement variants. - Keep the trigger and panel within the same positioned root when using simple absolute positioning.
- Choose the panel role to match the content model so the semantics and styling stay aligned.