Doc Page
Adapter Integration (Vanilla)
Bind current vanilla adapter APIs to predictable DOM contracts and cleanup-safe lifecycle flows.
Integration Rule
Adapters can change syntax, but they cannot change semantic truth. The same primitive should expose the same state transitions, slot names, ARIA relationships, keyboard behavior, and public data-* contract across React, Vanilla, Vue, Solid, and Svelte.
This rule is stricter than "the examples look similar." A menu item selected from a submenu should close the active menu tree in every adapter. A Select option clicked while already selected should still close the popup in every adapter. A portalled Select inside a Popover should still be treated as part of the active layer boundary.
Sources: shared/en/adapter-integration
Adapter Shapes
Vanilla integration is explicit:
const binding = bindSelect(elements, registrations, options);
binding.sync();
binding.destroy();The host provides DOM nodes and data registrations. The adapter applies controller props, event handlers, ARIA, public data-*, and cleanup.
Sources: shared/en/adapter-integration, vanilla/en/adapter-integration
Contract Mapping
Vanilla bindings must receive all required elements:
- Disclosure:
root,trigger,content. - Tabs:
list, tab element map, panel element map. - Dialog:
trigger,overlay,content,title,description,closewhere rendered. - Select/Listbox/Combobox/Menu: option or item registrations with stable IDs and labels.
- Popover/Tooltip/Menu/Select/Combobox: anchor, positioner, content, and placement options where used.
The adapter writes public attributes; host code should not overwrite them after binding.
Sources: shared/en/adapter-integration, vanilla/en/adapter-integration
API Surface Matrix
import {
bindCombobox,
bindDialog,
bindDisclosure,
bindListbox,
bindMenu,
bindPopover,
bindSelect,
bindTabs,
bindTooltip,
connectDisclosure
} from "@nake-ui/adapter-vanilla";Supported canonical primitives:
bindDisclosure(elements, options)andconnectDisclosure(elements, state)bindTabs(elements, registrations, options)bindDialog(elements, options)bindPopover(elements, options)bindMenu(elements, registrations, options)bindListbox(elements, registrations, options)bindSelect(elements, registrations, options)bindCombobox(elements, registrations, options)bindTooltip(elements, options)
Sources: shared/en/adapter-integration, vanilla/en/adapter-integration
SSR And Hydration
Vanilla can progressively enhance server-rendered HTML:
- Render semantic fallback markup.
- Include stable IDs for ARIA relationships.
- Bind only after the relevant nodes exist.
- Keep closed floating content hidden before activation.
- Destroy bindings when the host route/view is removed.
Sources: shared/en/adapter-integration, vanilla/en/adapter-integration
Parity Testing
Vanilla parity tests are especially important because the host owns lifecycle. Test:
- Binding and teardown idempotence.
sync()after external updates.- Keyboard behavior after DOM registration.
- Outside dismiss and focus handling.
- Floating placement reflection.
Sources: shared/en/adapter-integration, vanilla/en/adapter-integration
Pitfalls
- Double-binding the same nodes.
- Forgetting
destroy()during route changes. - Using unstable option IDs.
- Replacing
aria-*anddata-*after adapter sync. - Using floating content as its own anchor in nested layer trees.
Sources: shared/en/adapter-integration, vanilla/en/adapter-integration
Checklist
- Binding handle is stored and cleaned up.
- Registrations are stable.
- Public DOM attributes are adapter-owned after bind.
sync()is called for external state changes.- Interaction tests include keyboard and outside dismiss.
Sources: shared/en/adapter-integration, vanilla/en/adapter-integration