React
How to install and use Kaida components in your React application.
Installation
- Install Tailwind CSS v4 in your React project:
- Official Tailwind CSS guide
- For Next.js: follow the Next.js guide
Copy the theme CSS variables to your
index.cssorglobals.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 and convert attributes to JSX:
Always convert to camelCase:
- HTML: class → className, for → htmlFor, tabindex → tabIndex
- Events: onclick → onClick, onchange → onChange
- SVG: stroke-width → strokeWidth, fill-opacity → fillOpacity, clip-path → clipPath
Keep as-is (no conversion):
- data-* attributes (e.g., data-accordion, data-accordion-trigger)
- aria-* attributes (e.g., aria-expanded, aria-hidden)
- id, type, name, placeholder, href, src, target
export function Example() {
return (
<button
name="button"
type="button"
className="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>
);
}
Tip: Use online converters for automatic conversion: transform.tools or magic.reactjs.
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 useEffect:
import { useEffect } from 'react';
import { init_accordions } from '@/lib/accordion';
export function AccordionExample() {
useEffect(() => {
init_accordions();
}, []);
return (
<div data-accordion="open">
{/* accordion items */}
</div>
);
}
Important: Use an empty dependency array
[]to initialize only once. Callinginit_accordions()multiple times will create duplicate instances.
Global initialization (recommended)
For better performance, initialize all components once in your root file:
// src/main.tsx or src/index.tsx
import { useEffect } from 'react';
import { init_accordions } from '@/lib/accordion';
// import other init functions as needed
export default function App() {
useEffect(() => {
init_accordions();
// init_other_components();
}, []);
return <>{children}</>;
}
Then use components anywhere without worrying about initialization:
// Any component - no useEffect needed
export function FAQ() {
return (
<div data-accordion="open">
{/* accordion items */}
</div>
);
}
Note for Next.js users: If you're using Next.js App Router (13+), add
'use client'directive at the top of files that useuseEffector other React hooks. See Next.js documentation for more details.
Example
Here's a complete example using the Accordion component:
import { useEffect } from 'react';
import { init_accordions } from '@/lib/accordion';
export function FAQ() {
useEffect(() => {
init_accordions();
}, []);
return (
<div data-accordion="open">
<button
type="button"
data-accordion-trigger="#panel-0"
aria-expanded="false"
className="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=""
className="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"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
></path>
</svg>
</button>
<div id="panel-0" className="hidden">
<div className="px-24px pb-20px text-p2">
<p>Description</p>
</div>
</div>
<button
type="button"
data-accordion-trigger="#panel-1"
aria-expanded="false"
className="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=""
className="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"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
></path>
</svg>
</button>
<div id="panel-1" className="hidden">
<div className="px-24px pb-20px text-p2">
<p>Description</p>
</div>
</div>
</div>
);
}
Key points:
- No JS components (Button, Badge, Input, Card, etc.) — just copy HTML, no initialization
- JS components (Accordion, Toast, Dropdown, etc.) — initialize once in
useEffect - Use
classNameinstead ofclassin React/TSX - Initialize with empty dependency array
[]to avoid duplicates - For multiple JS components, initialize globally in your root file (
src/main.tsx) - Data attributes (
data-accordion,data-accordion-trigger, etc.) remain the same - Next.js App Router: Add
'use client'directive in files that use hooks (see note above)
On this page