- Docs
- VueJS guide
Vue Guide
Use Flexilla in Vue by rendering DOM-first markup and initializing it after the component mounts.
Flexilla can be used in Vue when you want DOM-first, headless component behavior without replacing your styling approach.
The key idea is simple: let Vue render the markup, initialize Flexilla after mount, and clean it up when the component unmounts.
Create a Vue project
npm create vue@latest flexilla-vue
cd flexilla-vue
npm install Install Flexilla
npm i @flexilla/flexilla Example Vue component
Create a component such as
src/components/FaqAccordion.vue. <template>
<div id="vue-accordion" data-fx-accordion data-accordion-type="single">
<div data-accordion-item data-accordion-value="item-1">
<button type="button" data-accordion-trigger class="accordion-trigger">
Who renders the markup?
</button>
<div data-accordion-content class="accordion-content">
Vue renders the markup, then Flexilla enhances it.
</div>
</div>
<div data-accordion-item data-accordion-value="item-2">
<button type="button" data-accordion-trigger class="accordion-trigger">
Who controls the visual design?
</button>
<div data-accordion-content class="accordion-content">
You do. Flexilla stays headless and only manages behavior and state.
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted } from "vue";
import { Accordion } from "@flexilla/flexilla";
let accordion: Accordion | null = null;
onMounted(() => {
accordion = new Accordion("#vue-accordion");
});
onUnmounted(() => {
accordion?.cleanup();
accordion = null;
});
</script>
<style>
#vue-accordion {
max-width: 42rem;
border: 1px solid #d4d4d8;
border-radius: 0.75rem;
overflow: hidden;
}
.accordion-trigger {
width: 100%;
padding: 1rem;
border: 0;
background: #fff;
text-align: left;
cursor: pointer;
font: inherit;
}
.accordion-trigger[aria-expanded="true"] {
background: #f4f4f5;
}
.accordion-content {
height: 0;
overflow: hidden;
padding-inline: 1rem;
}
.accordion-content[data-state="open"] {
height: auto;
padding-block: 0 1rem;
}
</style> Why onMounted() matters
Flexilla needs the rendered DOM to exist before initialization. In Vue, that usually means:
- use
onMounted()for manual initialization - use
nextTick()as an extra guard if the DOM is conditionally rendered
Why cleanup matters
Vue components can mount and unmount many times during navigation and conditional rendering. Because Flexilla instances attach event listeners, you should clean them up in
onUnmounted(). Every component should follow this pattern:
- create the instance in
onMounted() - call
cleanup()inonUnmounted()
That keeps listeners and instance state from leaking across remounts.
Single-package version
<script setup lang="ts">
import { onMounted, onUnmounted } from "vue";
import { Accordion } from "@flexilla/accordion";
let accordion: Accordion | null = null;
onMounted(() => {
accordion = new Accordion("#vue-accordion");
});
onUnmounted(() => {
accordion?.cleanup();
accordion = null;
});
</script> When to use auto init in Vue
autoInit() can work in Vue, but manual initialization is usually clearer because Vue controls when nodes appear and disappear. Prefer manual initialization when:
- the component lives inside a Vue component
- the markup can re-render
- you want explicit lifecycle control
- you want to clean up listeners with
cleanup()during unmount
Styling options
Vue does not change the Flexilla styling model. You can still use:
- plain CSS in
<style> - UnoCSS
- Tailwind CSS
Next step
Once this works for one component, keep the same pattern for others:
- render the required markup in the template
- initialize Flexilla in
onMounted() - clean up with
cleanup()inonUnmounted() - style the states