Beautiful, accessible, and customizable UI components built on Tailwind CSS 4.
Framework-agnostic with zero JavaScript runtime.
π Documentation Β· π Getting Started Β· π§© Components Β· π¨ Theming
| Feature | Description |
|---|---|
| π Framework Agnostic | Works with Vue, React, Astro, Svelte, Angular, Next.js, Nuxt, or vanilla HTML |
| π¨ Tailwind CSS 4 | Built on the latest version with the new @theme directive |
| π Dark Mode | Automatic dark mode with system preference detection + manual toggle |
| π¦ Zero JS Runtime | Pure CSS components, no JavaScript overhead |
| π§ Modular Imports | Import only the components you need |
| βΏ Accessible | Built with accessibility best practices |
| π― Utility-First | Seamlessly mix with Tailwind utilities |
| π± Responsive | Mobile-first responsive design |
KamUI is pure CSS, so it works with any framework or no framework at all:
| Framework | Supported | Framework | Supported |
|---|---|---|---|
| Vue 3 | β | React | β |
| Astro | β | Next.js | β |
| Nuxt | β | Svelte | β |
| SvelteKit | β | Angular | β |
| Solid | β | Qwik | β |
| HTML/CSS | β | PHP/Blade | β |
# npm
npm install kamui
# pnpm
pnpm add kamui
# yarn
yarn add kamui- Node.js 18 or higher
- Tailwind CSS 4.x
npm install kamui tailwindcss @tailwindcss/vite// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [vue(), tailwindcss()],
});/* src/assets/main.css */
@import 'tailwindcss';
@import 'kamui';<!-- App.vue -->
<template>
<button class="button button-primary">Click me</button>
</template>npm install kamui tailwindcss @tailwindcss/vite// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [react(), tailwindcss()],
});/* src/index.css */
@import 'tailwindcss';
@import 'kamui';// App.jsx
export default function App() {
return <button className="button button-primary">Click me</button>;
}npm install kamui tailwindcss @tailwindcss/postcss postcss// postcss.config.mjs
const config = {
plugins: {
'@tailwindcss/postcss': {},
},
};
export default config;/* app/globals.css */
@import 'tailwindcss';
@import 'kamui';// app/page.jsx
export default function Home() {
return <button className="button button-primary">Click me</button>;
}npm install kamui tailwindcss @tailwindcss/vite// nuxt.config.ts
import tailwindcss from '@tailwindcss/vite';
export default defineNuxtConfig({
vite: {
plugins: [tailwindcss()],
},
css: ['~/assets/css/main.css'],
});/* assets/css/main.css */
@import 'tailwindcss';
@import 'kamui';<!-- app.vue -->
<template>
<button class="button button-primary">Click me</button>
</template>npm install kamui tailwindcss @tailwindcss/vite// astro.config.mjs
import { defineConfig } from 'astro/config';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
vite: {
plugins: [tailwindcss()],
},
});/* src/styles/global.css */
@import 'tailwindcss';
@import 'kamui';---
// src/pages/index.astro
import '../styles/global.css'
---
<button class="button button-primary">Click me</button>npm install kamui tailwindcss @tailwindcss/vite// vite.config.js
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [svelte(), tailwindcss()],
});/* src/app.css */
@import 'tailwindcss';
@import 'kamui';<!-- src/App.svelte -->
<button class="button button-primary">Click me</button>npm install kamui tailwindcss @tailwindcss/vite// vite.config.js
import { sveltekit } from '@sveltejs/kit/vite';
import tailwindcss from '@tailwindcss/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit(), tailwindcss()],
});/* src/app.css */
@import 'tailwindcss';
@import 'kamui';<!-- src/routes/+page.svelte -->
<button class="button button-primary">Click me</button>npm install kamui tailwindcss @tailwindcss/postcss postcss// .postcssrc.json
{
"plugins": {
"@tailwindcss/postcss": {}
}
}/* src/styles.css */
@import 'tailwindcss';
@import 'kamui';<!-- component.html -->
<button class="button button-primary">Click me</button>npm install kamui tailwindcss @tailwindcss/vite// vite.config.js
import { defineConfig } from 'vite';
import solid from 'vite-plugin-solid';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [solid(), tailwindcss()],
});/* src/index.css */
@import 'tailwindcss';
@import 'kamui';// src/App.jsx
export default function App() {
return <button class="button button-primary">Click me</button>;
}<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>KamUI Example</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="node_modules/kamui/library/index.css" />
</head>
<body class="bg-bg text-text p-8">
<button class="button button-primary">Click me</button>
</body>
</html>KamUI includes 23+ ready-to-use components:
| Component | Description | Component | Description |
|---|---|---|---|
| π Buttons | Multiple variants & sizes | π Cards | Content containers |
| π Forms | Inputs, labels, validation | π Alerts | Feedback messages |
| π·οΈ Badges | Labels & status indicators | π Tables | Data display |
| π¬ Modals | Dialog windows | π Tabs | Content organization |
| π Dropdowns | Menu lists | π€ Avatars | User images |
| π§ Breadcrumbs | Navigation paths | π‘ Tooltips | Hover information |
| π Popovers | Floating content | β³ Spinners | Loading indicators |
| π Progress | Progress bars | π Toasts | Notifications |
| πΉ Accordion | Collapsible content | β Dividers | Visual separators |
| π List Groups | Grouped items | πΆ Stepper | Multi-step progress |
| π Pagination | Page navigation | βοΈ Typography | Text styles |
<!-- Solid variants -->
<button class="button button-primary">Primary</button>
<button class="button button-secondary">Secondary</button>
<button class="button button-success">Success</button>
<button class="button button-warning">Warning</button>
<button class="button button-error">Error</button>
<!-- Outlined variants -->
<button class="button button-outlined button-outlined-primary">Outlined</button>
<!-- Ghost variant -->
<button class="button button-ghost">Ghost</button>
<!-- Sizes -->
<button class="button button-primary button-sm">Small</button>
<button class="button button-primary button-md">Medium</button>
<button class="button button-primary button-lg">Large</button>
<!-- Pill shape -->
<button class="button button-primary button-pill">Pill Button</button><div class="card">
<div class="card-header">Card Title</div>
<div class="card-body">
<p>Card content goes here.</p>
</div>
<div class="card-footer">
<button class="button button-primary">Action</button>
</div>
</div>
<!-- Card with image -->
<div class="card">
<img class="card-img" src="image.jpg" alt="Description" />
<div class="card-body">Content</div>
</div><!-- Basic input -->
<div>
<label class="form-label" for="email">Email</label>
<input
class="form-input"
type="email"
id="email"
placeholder="you@example.com"
/>
</div>
<!-- Floating label -->
<div class="form-floating">
<input
id="name"
type="text"
class="form-floating-input peer"
placeholder="Name"
/>
<label for="name" class="form-floating-label">Your Name</label>
</div>
<!-- Validation states -->
<input class="form-input form-input-success" type="text" value="Valid input" />
<input class="form-input form-input-error" type="text" value="Invalid input" /><div class="alert alert-success">
<span class="alert-icon">β</span>
<span class="alert-message">Operation completed successfully!</span>
</div>
<div class="alert alert-error">
<span class="alert-icon">β</span>
<span class="alert-message">Something went wrong.</span>
</div>
<div class="alert alert-warning">
<span class="alert-icon">β </span>
<span class="alert-message">Please review your input.</span>
</div>
<div class="alert alert-info">
<span class="alert-icon">βΉ</span>
<span class="alert-message">Here's some information.</span>
</div><!-- Solid badges -->
<span class="badge badge-success">Success</span>
<span class="badge badge-warning">Warning</span>
<span class="badge badge-error">Error</span>
<span class="badge badge-info">Info</span>
<!-- Sizes -->
<span class="badge badge-success badge-sm">Small</span>
<span class="badge badge-success badge-lg">Large</span>
<!-- Pill shape -->
<span class="badge badge-success badge-pill">Pill</span><div class="table-wrapper">
<table class="table">
<thead class="table-head">
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr class="table-row">
<td class="table-cell">John Doe</td>
<td class="table-cell">john@example.com</td>
<td class="table-cell">Admin</td>
</tr>
</tbody>
</table>
</div><div class="modal">
<div class="modal-backdrop"></div>
<div class="modal-content">
<div class="modal-header">Modal Title</div>
<div class="modal-body">
<p>Modal content goes here.</p>
</div>
<div class="modal-footer">
<button class="button button-ghost">Cancel</button>
<button class="button button-primary">Confirm</button>
</div>
</div>
</div><div class="tabs">
<div class="tab-list">
<button class="tab tab-active">Tab 1</button>
<button class="tab">Tab 2</button>
<button class="tab">Tab 3</button>
</div>
<div class="tab-panel">Tab content here.</div>
</div>Import only the components you need to reduce bundle size:
/* Import only what you need */
@import 'tailwindcss';
@import 'kamui/color'; /* Required: theme colors */
@import 'kamui/buttons'; /* Only buttons */
@import 'kamui/cards'; /* Only cards */
@import 'kamui/forms'; /* Only forms */| Import | Component |
|---|---|
kamui |
All components |
kamui/color |
Theme colors (required) |
kamui/buttons |
Buttons |
kamui/cards |
Cards |
kamui/forms |
Form inputs |
kamui/alerts |
Alerts |
kamui/badges |
Badges |
kamui/tables |
Tables |
kamui/modals |
Modals |
kamui/tabs |
Tabs |
kamui/dropdowns |
Dropdowns |
kamui/avatars |
Avatars |
kamui/breadcrumbs |
Breadcrumbs |
kamui/tooltips |
Tooltips |
kamui/popovers |
Popovers |
kamui/spinners |
Spinners |
kamui/progress |
Progress bars |
kamui/toasts |
Toasts |
kamui/accordion |
Accordion |
kamui/dividers |
Dividers |
kamui/list-groups |
List groups |
kamui/stepper |
Stepper |
kamui/pagination |
Pagination |
kamui/typography |
Typography |
KamUI uses CSS custom properties (variables) for theming, defined with Tailwind CSS 4's @theme directive.
| Variable | Light Mode | Dark Mode |
|---|---|---|
--color-primary |
#2f27ce |
#3a31d8 |
--color-secondary |
#dddbff |
#020024 |
--color-accent |
#443dff |
#0600c2 |
--color-bg |
#fbfbfe |
#010104 |
--color-text |
#040316 |
#eae9fc |
--color-success |
#059669 |
#10b981 |
--color-warning |
#d97706 |
#f59e0b |
--color-error |
#dc2626 |
#ef4444 |
--color-info |
#0284c7 |
#06b6d4 |
Override the theme colors in your CSS:
@import 'tailwindcss';
@import 'kamui';
/* Override colors */
@theme {
--color-primary: #8b5cf6;
--color-primary-hover: #7c3aed;
--color-primary-focus: #a78bfa;
--color-primary-active: #6d28d9;
--color-primary-ring: #ddd6fe;
}
/* Override dark mode colors */
.dark {
--color-primary: #a78bfa;
--color-primary-hover: #8b5cf6;
}The theme colors work as Tailwind utilities:
<div class="bg-primary text-white">Primary background</div>
<div class="text-success">Success text</div>
<div class="border-error">Error border</div>
<div class="bg-bg-elevated">Elevated background</div>KamUI supports dark mode out of the box with two methods:
Dark mode is automatically applied based on the user's system preference using prefers-color-scheme.
Add the .dark class to the <html> element:
<html class="dark">
<!-- Dark mode active -->
</html>// Toggle dark mode
function toggleTheme() {
document.documentElement.classList.toggle('dark');
}
// Set specific theme
function setTheme(theme) {
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
}import { useState, useEffect } from 'react';
function useTheme() {
const [isDark, setIsDark] = useState(false);
useEffect(() => {
const saved = localStorage.getItem('theme');
const prefersDark = window.matchMedia(
'(prefers-color-scheme: dark)'
).matches;
if (saved === 'dark' || (!saved && prefersDark)) {
setIsDark(true);
document.documentElement.classList.add('dark');
}
}, []);
const toggleTheme = () => {
setIsDark(!isDark);
document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', !isDark ? 'dark' : 'light');
};
return { isDark, toggleTheme };
}<script setup>
import { ref, onMounted } from 'vue';
const isDark = ref(false);
onMounted(() => {
const saved = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (saved === 'dark' || (!saved && prefersDark)) {
isDark.value = true;
document.documentElement.classList.add('dark');
}
});
const toggleTheme = () => {
isDark.value = !isDark.value;
document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', isDark.value ? 'dark' : 'light');
};
</script>kamui/
βββ library/ # π¦ Distributed library (npm package)
β βββ index.css # Main entry point
β βββ theme/
β β βββ color.css # Theme colors & dark mode
β βββ components/
β βββ alerts.css
β οΏ½οΏ½οΏ½ββ avatars.css
β βββ badges.css
β βββ buttons.css
β βββ cards.css
β βββ ...
βββ src/ # π§ Source & demo app
β βββ library/ # Source CSS files
β βββ ... # Demo application
βββ tests/ # π§ͺ Test files
βββ package.json
βββ README.md
Contributions are welcome! Please read our Contributing Guide before submitting a Pull Request.
# Clone the repository
git clone https://github.com/JotnarDev/KamUI.git
cd KamUI
# Install dependencies
npm install
# Start development server
npm run dev
# Run tests
npm run test
# Check formatting
npm run format:checkMIT License Β© 2025 JotnarDev
See LICENSE for more information.
- Built with Tailwind CSS 4
- Inspired by modern design systems
Made with π by JotnarDev