Vue

How to install and use Kaida components in your Vue application.

Installation

  1. Install Tailwind CSS v4 in your Vue project:
  1. Copy the theme CSS variables to your App.vue or assets/main.css.

  2. 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 in onMounted. 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_accordions function includes the data-accordion-initialized check 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, not className)
  • 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