Vue adapter
Own Boobstrap interaction state in Vue 3 with SSR-safe headless composables and consumer-controlled markup.
Vue 3 integration
The official adapter returns reactive state and prop objects for your own semantic markup. It never initializes the vanilla controller layer on Vue-owned DOM.
Install
npm install @boobstrap/boobstrap @boobstrap/vue vueimport "@boobstrap/boobstrap/dist/boobstrap.css";
import { useCollapse } from "@boobstrap/vue";initBoobstrap on Vue-owned markup. A composable supplies reactive state, ARIA attributes, event handlers, and template refs; your template supplies semantic elements and bs-* classes.Compose a collapse
The preview is the rendered result of the Vue single-file component directly below it. The composable supplies the button type, relationship, expanded state, panel ID, visibility, and public state while your template supplies the content and classes.
<script setup>
import { useCollapse } from "@boobstrap/vue";
const details = useCollapse({ id: "account-details", defaultOpen: true });
</script>
<template>
<button class="bs-btn bs-btn-secondary" v-bind="details.getTriggerProps()">
Account details
</button>
<div class="bs-collapse bs-card bs-mt-4" v-bind="details.getPanelProps()">
<div class="bs-card-body">Profile and security settings.</div>
</div>
</template>Coordinate an accordion
Use useAccordion for group state and pass each item's options into useCollapse. The default keeps one item open; set alwaysOpen: true when multiple panels may remain visible.
import { useAccordion, useCollapse } from "@boobstrap/vue";
const accordion = useAccordion({ defaultOpenIds: ["profile"] });
const profile = useCollapse({
id: "profile-panel",
...accordion.getItemOptions("profile"),
});
const billing = useCollapse({
id: "billing-panel",
...accordion.getItemOptions("billing"),
});See the complete Vue accordion template for semantic headings, prop binding, and panel relationships.
Controlled state
import { ref } from "vue";
import { useDialog } from "@boobstrap/vue";
const open = ref(false);
const dialog = useDialog({ open, onOpenChange: (next) => { open.value = next; } });Events and lifecycle
Composables emit the same cancelable before-events and completed lifecycle events as core controllers. Change callbacks receive the next value plus detail containing adapter: "vue", a transition reason, and the source event when one exists. DOM listeners, timers, and floating-position listeners are released during component unmount.
One owner
Do not run initBoobstrap inside the same component subtree. Vue owns state and lifecycle there.
SSR
Composables avoid DOM access during setup so server markup hydrates with stable relationships and initial state.
Controlled state
Use default* options for uncontrolled initial state and refs for reactive controlled ownership. Both expose a computed public state.
Toast parity
Autohide pauses while a toast is hovered or contains focus, then resumes on pointer leave or focus exit—the same contract as vanilla, Alpine, and React.
Component guides
Use this page for shared ownership rules, then use each component guide for copy-ready templates and component-specific semantics.
Composable API
| Composable | Owns |
|---|---|
useAccordion | Single-open or always-open group state and item options. |
useButton | Loading state and busy semantics. |
useCollapse, useDialog, useDropdown | Open state, IDs, focus, and dismissal. |
useCombobox, useTabs | Selection, keyboard navigation, and ARIA relationships. |
useToast, useTooltip, usePopover | Feedback visibility and trigger/panel props, including pause-aware toast autohide. |