@akhatmirzo/ui

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/tokens

The font is optional, but the design is tuned for Manrope:

pnpm add @fontsource-variable/manrope

Wire up the CSS

In your main stylesheet, import the tokens after Tailwind and tell Tailwind to scan the component classes:

app.css
@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:

App.tsx
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/vite
vite.config.ts
import 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:

src/index.css
@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/postcss
postcss.config.mjs
export default {
  plugins: { '@tailwindcss/postcss': {} },
};
app/globals.css
@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:

app/providers.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>
  );
}
app/layout.tsx
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
PackageWhat you get
@akhatmirzo/uiReact components (Tailwind v4 + Radix)
@akhatmirzo/tokensDesign tokens: CSS variables and a Tailwind @theme
@akhatmirzo/coreFormatting, validation, text, storage and API — no React, zero dependencies
@akhatmirzo/hooksReact 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

Next steps

On this page