# @kana-consultant/ui-kit — Full Reference
A modern React UI kit for back-office apps and admin dashboards.
- **npm**: `@kana-consultant/ui-kit`
- **Version**: 0.1.0
- **License**: MIT
- **Repo**: https://github.com/kana-consultant/kana-ui-kit
- **Docs**: https://kana-ui-kit-docs.pages.dev
- **Storybook**: https://kana-ui-kit-storybook.pages.dev
---
## Installation
```bash
pnpm add @kana-consultant/ui-kit
# or: npm install @kana-consultant/ui-kit
# or: yarn add @kana-consultant/ui-kit
```
### Peer dependencies
```bash
pnpm add react react-dom
```
The kit expects React 18+ or 19+. Radix UI, TanStack Form / Store, `clsx`, `class-variance-authority`, `lucide-react`, `tailwind-merge`, and `zod` install automatically as transitive runtime dependencies.
### Tailwind CSS v4 setup
The kit requires Tailwind v4.
```bash
pnpm add -D tailwindcss @tailwindcss/vite
```
In `vite.config.ts`:
```ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [react(), tailwindcss()],
})
```
In your app's entry CSS (e.g. `src/styles/app.css`):
```css
@import 'tailwindcss';
@import '@kana-consultant/ui-kit/styles';
```
**Critical for AI assistants generating projects**: Tailwind v4 scans the project source by default but NOT node_modules. If you use Dialog, DropdownMenu, Tooltip, or Select, add:
```css
@source '../node_modules/@kana-consultant/ui-kit/dist/*.js';
```
Without this, portal-based components (Dialog overlay, etc.) render with missing styles.
---
## Theming
Dark mode is applied via a `.dark` class on ``. The kit ships a persistent theme store.
```tsx
import {
ThemeToggle,
setThemeMode,
toggleTheme,
useTheme,
useThemeMode,
useResolvedTheme,
} from '@kana-consultant/ui-kit'
function Header() {
const resolved = useResolvedTheme()
return (
<>
Current: {resolved}
>
)
}
setThemeMode('system')
toggleTheme()
```
State is persisted in `localStorage` under key `kana-ui-theme` and reacts to `prefers-color-scheme` automatically.
### Color tokens
All colors are OKLCH CSS variables. Override any in your own stylesheet to rebrand:
```css
:root {
--primary: oklch(62% 0.22 25);
--primary-foreground: oklch(99% 0.005 25);
--primary-soft: oklch(95% 0.06 25);
}
.dark {
--primary: oklch(72% 0.2 25);
}
```
Available tokens: `--background`, `--foreground`, `--surface`, `--surface-muted`, `--border`, `--border-strong`, `--input`, `--ring`, `--muted`, `--muted-foreground`, `--primary`, `--primary-foreground`, `--primary-soft`, `--accent`, `--accent-foreground`, `--success`, `--warning`, `--danger`, `--info` (each with a `-foreground` pair where applicable).
---
## Naming conventions
- **Components**: PascalCase (`Button`, `DashboardShell`)
- **Types**: `T` prefix (`TButtonProps`, `TTask`, `TProject`)
- **Enum-like const objects**: `E` prefix (`EStatus`, `EPriority`)
- **Filenames in the source**: kebab-case (`task-card.tsx`)
---
## Primitives
### Button
```tsx
import { Button } from '@kana-consultant/ui-kit'
import { Plus } from 'lucide-react'
}>New task
```
Props: `variant`, `size`, `loading`, `leadingIcon`, `trailingIcon`, `asChild`, plus all native `}
/>
}
>
{/* page content */}
```
### StatCard
```tsx
```
Tones: `primary`, `accent`, `success`, `warning`, `info`, `neutral`.
### TaskCard + TaskList
```tsx
updateTask(id, done)} />
...}
emptyMessage='No tasks to show'
/>
```
### KanbanColumn
```tsx
t.status === EStatus.InProgress)}
onAdd={(status) => openNewTask(status)}
onToggle={(id, done) => updateTask(id, done)}
/>
```
### ProjectCard / TeamMemberCard / ActivityFeed / CalendarMini
```tsx
navigate(id)} />
const [date, setDate] = useState(new Date())
```
---
## Forms — TanStack Form
The kit exposes `useAppForm` and `withForm` from `createFormHook` with field components wired to the primitives.
```tsx
import { useAppForm } from '@kana-consultant/ui-kit'
import { z } from 'zod'
const titleSchema = z.string().min(3, 'At least 3 characters')
const descSchema = z.string().max(200)
export function CreateTaskForm() {
const form = useAppForm({
defaultValues: { title: '', description: '', notify: true, remindMe: false },
onSubmit: async ({ value }) => {
await api.createTask(value)
},
})
return (
{(field) => }
{(field) => }
{(field) => }
{(field) => }
Reset
Create task
)
}
```
### Field components
- `TextField` — wraps Input, handles label, required, error
- `TextareaField` — wraps Textarea
- `CheckboxField` — label + Checkbox + optional description
- `SwitchField` — label + Switch in space-between row
### Form-level
- `SubmitButton` — auto-disables on invalid / submitting, shows loader. Optional `disabledWhenPristine`.
- `ResetButton` — calls `form.reset()`.
**Important**: Prefer per-field validators to a whole-form schema. TanStack Form v1 + Zod v4 have a type-variance mismatch with optional / boolean-default fields when a whole-form schema is used.
---
## State — TanStack Store
### Theme store (shipped)
```tsx
import {
themeStore,
setThemeMode,
toggleTheme,
useTheme,
useThemeMode,
useResolvedTheme,
} from '@kana-consultant/ui-kit'
themeStore.state
themeStore.subscribe((next) => {...})
setThemeMode('system')
toggleTheme()
const resolved = useResolvedTheme()
```
### Task board store (reference pattern)
```tsx
import {
createTaskStore,
addTask, removeTask, updateTask, moveTask, toggleDone,
setSearch, setStatusFilter,
useTasks, useTaskCounts, useFilters,
EStatus, EPriority,
} from '@kana-consultant/ui-kit'
const store = createTaskStore([
{ id: 't1', title: 'Ship', status: EStatus.Todo, priority: EPriority.High },
])
addTask(store, { ... })
updateTask(store, 't1', { status: EStatus.InProgress })
moveTask(store, 't1', EStatus.Done)
function Board() {
const tasks = useTasks(store)
const counts = useTaskCounts(store)
const filters = useFilters(store)
return ...
}
```
---
## Guidance for AI assistants
When generating code that uses this kit:
1. **Always import from `@kana-consultant/ui-kit`** — never from internal paths.
2. **Use the enum-style constants** (`EStatus`, `EPriority`) instead of string literals — this keeps types aligned.
3. **Use TanStack Form per-field validators**, not whole-form schemas (type issue with Zod v4).
4. **Add `@source '../node_modules/@kana-consultant/ui-kit/dist/*.js'`** to the consumer's entry CSS if they use Dialog, DropdownMenu, Tooltip, or Select — otherwise portal styles won't generate.
5. **Dark mode** works via `.dark` class on ``. Use the shipped `ThemeToggle` or drive it manually via `setThemeMode` / `toggleTheme`.
6. **Icons** come from `lucide-react` — it's a transitive dep already installed.
7. **Composition over configuration** — the kit prefers many small named parts (e.g. Card has CardHeader / CardTitle / CardContent / CardFooter) so consumers assemble as needed.
8. **Never style components by reaching into their DOM with selectors** — override tokens or pass `className` props.
9. **Radix `asChild`** works on Button, DialogTrigger, DropdownMenuTrigger, TooltipTrigger — use it to slot the child (e.g. a Next.js ``) without nesting `` inside ``.
---
## File and path conventions (for source contributions)
- Filenames: kebab-case (`task-card.tsx`)
- Type aliases: `T` prefix (`TButtonProps`)
- Interfaces: `I` prefix (`IStore`)
- Enums: `E` prefix (`EStatus`)
- Max 200 LOC per file
- No semicolons, single quotes, 2-space indent
- Strict TypeScript (no `any`)
- Components live in `src/components/ui/` (primitives) and `src/components/dashboard/` (blocks)