Vue
How to install and use Kaida components in your Vue application.
Installation
- Install Tailwind CSS v4 in your Vue project:
Copy the theme CSS variables to your
App.vueorassets/main.css.Copy the component files into your project (e.g.,
src/components/).
Usage
Kaida components are divided into two types:
Components without JavaScript
Components like Button, Badge, Input, Card work with pure CSS/Tailwind. No JavaScript initialization needed — just copy the HTML:
<template>
<button
name="button"
type="button"
class="flex gap-8px items-center justify-center whitespace-nowrap py-4px px-16px text-btn2 [&>svg]:w-16px [&>svg]:h-16px rounded-8px text-white dark:text-accent-900 border disabled:opacity-30 focus:shadow-[0_0_0_2px_#FFFFFF,0_0_0_4px_#0F172A] dark:focus:shadow-[0_0_0_2px_#2d2e33,0_0_0_4px_#FFFFFF] bg-accent-900 border-accent-900 hover:bg-accent-700 hover:border-accent-700 focus:bg-accent-700 focus:border-accent-700 active:bg-accent-500 active:border-accent-500 dark:bg-white dark:border-white dark:hover:bg-accent-200 dark:hover:border-accent-200 dark:focus:bg-accent-200 dark:focus:border-accent-200 dark:active:bg-accent-400 dark:active:border-accent-400"
title="Get started">
Get started
</button>
</template>
Tip: Vue templates use standard HTML attributes — no conversion needed.
Components with JavaScript
Components like Accordion, Toast, Dropdown require JavaScript initialization.
Basic initialization
Copy the JS file to your project (e.g., src/lib/accordion.ts) and initialize in onMounted:
<script setup>
import { onMounted } from 'vue';
import { init_accordions } from '@/lib/accordion';
onMounted(() => {
init_accordions();
});
</script>
<template>
<div data-accordion="open">
<!-- accordion items -->
</div>
</template>
Important: Call
init_accordions()only once inonMounted. Multiple calls will create duplicate instances.
Global initialization (recommended only for persistent UI elements)
For better performance, you can initialize all components once in your root component.
Important: This method works only for elements that are always present in the DOM (e.g., headers, footers, sidebars). If your accordion is inside a page component loaded via <router-view> or a v-if block that becomes true later, it will not be initialized.
For page-specific accordions, always initialize locally inside the component using onMounted.
// src/main.js or src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import { init_accordions } from '@/lib/accordion';
const app = createApp(App);
app.mount('#app');
// Initialize after mount
init_accordions();
Then use components anywhere without worrying about initialization:
<!-- Any component - no initialization needed -->
<template>
<div data-accordion="open">
<!-- accordion items -->
</div>
</template>
Using with Nuxt
For Nuxt 3, use a plugin to initialize components:
<!-- Any component - no initialization needed -->
<template>
<div data-accordion="open">
<!-- accordion items -->
</div>
</template>
// plugins/kaida.client.ts
import { defineNuxtPlugin } from '#app';
import { init_accordions } from '@/lib/accordion';
export default defineNuxtPlugin((nuxtApp) => {
const init = () => init_accordions();
onNuxtReady(init); // Initial load
// Re-initialize after client-side navigation
nuxtApp.hook('page:finish', init);
});
Note: Ensure your
init_accordionsfunction includes thedata-accordion-initializedcheck to prevent duplicate event listeners.
Example
Here's a complete example using the Accordion component:
<script setup>
import { onMounted } from 'vue';
import { init_accordions } from '@/lib/accordion';
onMounted(() => {
init_accordions();
});
</script>
<template>
<div data-accordion="open">
<button
type="button"
data-accordion-trigger="#panel-0"
aria-expanded="false"
class="flex items-center justify-between gap-16px w-full pt-20px pb-20px px-24px text-h9 rtl:text-right border-t border-accent-200 dark:border-black-600 [&.active]:pb-12px will-change:padding-bottom [&>span]:will-change:opacity transition-all [&>span]:transition-all hover:[&>span]:opacity-70">
<span>
Text
</span>
<svg
data-accordion-icon=""
class="rotate-180 shrink-0"
aria-hidden="true"
width="24"
height="24"
viewbox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M18 15L12 9L6 15"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
</path>
</svg>
</button>
<div
id="panel-0"
class="hidden">
<div class="px-24px pb-20px text-p2">
<p>
Description
</p>
</div>
</div>
<button
type="button"
data-accordion-trigger="#panel-1"
aria-expanded="false"
class="flex items-center justify-between gap-16px w-full pt-20px pb-20px px-24px text-h9 rtl:text-right border-t border-accent-200 dark:border-black-600 [&.active]:pb-12px will-change:padding-bottom [&>span]:will-change:opacity transition-all [&>span]:transition-all hover:[&>span]:opacity-70">
<span>
Text
</span>
<svg
data-accordion-icon=""
class="rotate-180 shrink-0"
aria-hidden="true"
width="24"
height="24"
viewbox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M18 15L12 9L6 15"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round">
</path>
</svg>
</button>
<div
id="panel-1"
class="hidden">
<div class="px-24px pb-20px text-p2">
<p>
Description
</p>
</div>
</div>
</div>
</template>
Key points:
- No JS components (Button, Badge, Input, Card, etc.) — just copy HTML, no conversion needed
- JS components (Accordion, Toast, Dropdown, etc.) — initialize once in
onMounted - Vue templates use standard HTML attributes (
class, notclassName) - Initialize once to avoid duplicates
- For multiple JS components, initialize globally in
src/main.js - Data attributes (
data-accordion,data-accordion-trigger, etc.) remain the same - Nuxt 3: Use a client-side plugin (
.client.ts) for initialization
On this page