Installation
Install the packages, wire up the CSS and render your first component.
The toolkit ships as four independent packages. For components you only need @akhatmirzo/ui
and @akhatmirzo/tokens — add the others when you need them.
Requirements
- React 18 or newer (React 19 is supported)
- Tailwind CSS v4 — components are styled with Tailwind classes, and your own Tailwind build generates the CSS
- An ESM-aware bundler: Vite, Next.js, Rsbuild and so on
Install
Add the packages
pnpm add @akhatmirzo/ui @akhatmirzo/tokensThe font is optional, but the design is tuned for Manrope:
pnpm add @fontsource-variable/manropeWire up the CSS
In your main stylesheet, import the tokens after Tailwind and tell Tailwind to scan the component classes:
@import 'tailwindcss';
@import '@fontsource-variable/manrope';
@import '@akhatmirzo/tokens/theme.css';
/* The path is relative to this CSS file */
@source '../node_modules/@akhatmirzo/ui/dist';Don't forget @source
Tailwind v4 does not scan node_modules on its own. Without the @source line the components
render, but unstyled. Adjust the path to where your CSS file lives — for src/styles/app.css it
would be '../../node_modules/@akhatmirzo/ui/dist'.
Add the providers
Once, at the root of your app. toast(), confirm() and tooltips depend on them:
import { ConfirmProvider, Toaster, TooltipProvider } from '@akhatmirzo/ui';
export function App() {
return (
<TooltipProvider>
<ConfirmProvider>
<Routes />
<Toaster position="bottom-right" />
</ConfirmProvider>
</TooltipProvider>
);
}Render your first component
import { Button, toast } from '@akhatmirzo/ui';
export function SaveButton() {
return (
<Button variant="primary" onClick={() => toast.success('Saved')}>
Save
</Button>
);
}Vite
Tailwind v4 plugs into Vite through its official plugin:
pnpm add -D tailwindcss @tailwindcss/viteimport tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [react(), tailwindcss()],
});The stylesheet usually lives in src/, so @source goes one level up:
@import 'tailwindcss';
@import '@fontsource-variable/manrope';
@import '@akhatmirzo/tokens/theme.css';
@source '../node_modules/@akhatmirzo/ui/dist';Add the providers in src/main.tsx or at the root of App, as in step 3 above.
Next.js (App Router)
The components use state and browser APIs, so render them from client components — put
'use client' at the top of the file.
In Next.js, Tailwind v4 runs as a PostCSS plugin:
pnpm add -D tailwindcss @tailwindcss/postcssexport default {
plugins: { '@tailwindcss/postcss': {} },
};@import 'tailwindcss';
@import '@fontsource-variable/manrope';
@import '@akhatmirzo/tokens/theme.css';
@source '../node_modules/@akhatmirzo/ui/dist';Move the providers into their own file and wrap them around your layout.tsx:
'use client';
import { ConfirmProvider, Toaster, TooltipProvider } from '@akhatmirzo/ui';
import type { ReactNode } from 'react';
export function Providers({ children }: { children: ReactNode }) {
return (
<TooltipProvider>
<ConfirmProvider>
{children}
<Toaster />
</ConfirmProvider>
</TooltipProvider>
);
}import { Providers } from './providers';
import './globals.css';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body className="bg-background font-sans text-text antialiased">
<Providers>{children}</Providers>
</body>
</html>
);
}Optional packages
They work without the components, too — each one stands on its own:
pnpm add @akhatmirzo/core @akhatmirzo/hooks| Package | What you get |
|---|---|
@akhatmirzo/ui | React components (Tailwind v4 + Radix) |
@akhatmirzo/tokens | Design tokens: CSS variables and a Tailwind @theme |
@akhatmirzo/core | Formatting, validation, text, storage and API — no React, zero dependencies |
@akhatmirzo/hooks | React hooks: useDebounce, useHotkeys, useLocalStorage and more |
You don't have to install core and hooks yourself
@akhatmirzo/ui already depends on them. If you import them directly in your own code, add them
to your package.json as well.
Troubleshooting
Tailwind can't see the @akhatmirzo/ui classes. Check that your stylesheet has the @source
line and that the path is correct relative to that CSS file. In a pnpm monorepo, point it
at the app's own node_modules folder, not the one at the repository root.
Render <Toaster /> and <ConfirmProvider> once at the root of your app. Without them the
functions don't throw — nothing just appears on screen.
Add 'use client'; as the first line of the file that uses the component. Server Components
can only render static markup.
The tokens follow the <html data-theme="dark"> attribute — class="dark" alone isn't
enough. The Dark mode page shows how to set it up with next-themes.