Align
Use Popover positioner alignment to control cross-axis placement.
Current align: start
Components
Provide lightweight anchored floating content with deterministic non-modal dismissal semantics.
vanilla live preview activates on the client; source HTML keeps a readable preview island and primitive contract.
vanilla popover preview activates on the client.
Install adapter-specific dependencies first, then complete setup via the installation guide. installation docs
pnpm add @nake-ui/primitives @nake-ui/adapter-vanilla @nake-ui/theme-vanilla
Minimal runnable usage for the current adapter.
import "@nake-ui/theme-vanilla/styles.css";
import { bindPopover } from "@nake-ui/adapter-vanilla";
const binding = bindPopover(nodes, items, options);
binding.destroy();
Show start / center / end cross-axis placement with aligned popover positioners.
import "@nake-ui/theme-vanilla/styles.css";
import { bindPopover } from "@nake-ui/adapter-vanilla";
const aligns = ["start", "center", "end"] as const;
for (const align of aligns) {
const binding = bindPopover(
{ root, trigger, positioner, content, title, description },
{ id: `example-popover-${align}`, defaultOpen: false, placement: "bottom", align, matchAnchorWidth: false }
);
// cleanup on unmount
binding.destroy();
}
trigger.textContent = "Align: start";
Render a custom profile card while preserving popover title, description, and dialog semantics.
import "@nake-ui/theme-vanilla/styles.css";
import { bindPopover } from "@nake-ui/adapter-vanilla";
if (typeof window !== "undefined" && typeof document !== "undefined") {
const binding = bindPopover(
{ root, trigger, positioner, content, title, description },
{ id: "example-custom-popover", defaultOpen: false, matchAnchorWidth: false }
);
// cleanup on unmount
binding.destroy();
}
trigger.textContent = "Open profile card";
The same structure running inside a `dir="rtl"` container.
vanilla popover preview activates on the client.
Complete
Closure Score: 100% (19/19)
Required Checks
schemaRegistered
specDocumented
reactMapper
siteExampleCoverage
siteA11yCoverage
siteVisible
schemaValidatorCoverage
schemaAriaCoverage
specValidatorRulesSection
specTestChecklistSection
specSsrHydrationSection
reactSsrHydrationCoverage
reactRenderLevelSsrCoverage
solidSsrCoverage
coreImplemented
primitiveUnitTest
domContractSnapshot
vanillaBinding
adapterParitySnapshot
All required closure checks are currently satisfied.
Provide lightweight anchored floating content with deterministic non-modal dismissal semantics.
root (optional structural wrapper in Vue)anchor (optional positioning anchor)triggerpositioner (optional floating wrapper)contenttitle (optional)description (optional)<div data-ui="popover" data-slot="root" data-state="open">
<button
id="popover-trigger"
data-ui="popover"
data-slot="trigger"
data-state="open"
aria-haspopup="dialog"
aria-expanded="true"
aria-controls="popover-content"
></button>
<div data-slot="positioner" data-state="open" data-placement="bottom-start" data-side="bottom">
<div
id="popover-content"
data-slot="content"
data-state="open"
role="dialog"
aria-labelledby="popover-content-title"
aria-describedby="popover-content-description"
hidden=""
></div>
</div>
</div>
open and defaultOpenopen + onOpenChangeopen is omittedclose / openPopover / toggle request helpers for hook/compound usageanchor and content node linkage for layer dismissal behavioraria-labelledby / aria-describedbyclick toggles open/closeEscape dismisses active popover layerEscape closes the layer and returns control to native focus patharia-haspopup="dialog", aria-expanded, aria-controlsrole="dialog", aria-labelledby, aria-describedby, hiddenstructure.invalid-slot-placement
structure.missing-required-slot
aria.broken-controls-linkage
aria.missing-label
keyboard.unhandled-escape
state.invalid-open-state
createPopoverController
value
PopoverController
type
PopoverControllerOptions
type
bindPopover
function
PopoverBindingOptions
interface
PopoverElements
interface
PopoverPositioningAlign
type
PopoverPositioningPlacement
type