Manual

How to set up Kõsori UI in your Next.js project.

Add dependencies

Install the following dependencies:

npm install clsx next-themes tailwind-merge tailwind-variants tailwindcss-animate @radix-ui/colors

Add theme provider

Add the <ThemeProvider /> component at the root of your app.

app/layout.tsx
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
import { ThemeProvider } from 'next-themes'; 
 
const inter = Inter({ subsets: ['latin'] });
 
export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};
 
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang='en'>
      <body className={inter.className}>
        <ThemeProvider attribute='class'> // [!code highlight]
          {children}
        </ThemeProvider> // [!code highlight]
      </body>
    </html>
  );
}

Add dark mode

Set darkMode strategy to class in your Tailwind CSS config file.

tailwind.config.ts
import type { Config } from 'tailwindcss';
 
const config: Config = {
  darkMode: 'class',  
  // ...
};
 
export default config;

Add tailwind border radius

Overwrite the borderRadius object in your theme object.

tailwind.config.ts
import type { Config } from 'tailwindcss';
 
const config: Config = {
  darkMode: 'class',
  content: [
    '...',
  ],
  theme: {
    // ...

    borderRadius: {
      none: '0px',
      sm: 'calc(var(--radius) - 3px)',
      DEFAULT: 'var(--radius)',
      md: 'var(--radius)',
      lg: 'calc(var(--radius) + 3px)',
      xl: 'calc(var(--radius) + 6px)',
      '2xl': 'calc(var(--radius) + 9px)',
      '3xl': 'calc(var(--radius) + 12px)',
      full: '9999px',
    },
  },
  plugins: [],
};
 
export default config;

Add tailwind colors

Extend the colors object in your theme object.

tailwind.config.ts
import type { Config } from 'tailwindcss';
 
const config: Config = {
  darkMode: 'class',
  content: [
    '...',
  ],
  theme: {
    // ...
    extend: {
      // ...

      colors: {
        primary: {
          base: 'var(--primary-1)',
          'bg-subtle': 'var(--primary-2)',
          bg: 'var(--primary-3)',
          'bg-hover': 'var(--primary-4)',
          'bg-active': 'var(--primary-5)',
          line: 'var(--primary-6)',
          border: 'var(--primary-7)',
          'border-hover': 'var(--primary-8)',
          'focus-ring': 'var(--primary-8)',
          solid: 'var(--primary-9)',
          'solid-hover': 'var(--primary-10)',
          text: 'var(--primary-11)',
          'text-contrast': 'var(--primary-12)',
        },
 

        grey: {
          base: 'var(--grey-1)',
          'bg-subtle': 'var(--grey-2)',
          bg: 'var(--grey-3)',
          'bg-hover': 'var(--grey-4)',
          'bg-active': 'var(--grey-5)',
          line: 'var(--grey-6)',
          border: 'var(--grey-7)',
          'border-hover': 'var(--grey-8)',
          'focus-ring': 'var(--grey-8)',
          solid: 'var(--grey-9)',
          'solid-hover': 'var(--grey-10)',
          text: 'var(--grey-11)',
          'text-contrast': 'var(--grey-12)',
        },
 

        info: {
          base: 'var(--info-1)',
          'bg-subtle': 'var(--info-2)',
          bg: 'var(--info-3)',
          'bg-hover': 'var(--info-4)',
          'bg-active': 'var(--info-5)',
          line: 'var(--info-6)',
          border: 'var(--info-7)',
          'border-hover': 'var(--info-8)',
          'focus-ring': 'var(--info-8)',
          solid: 'var(--info-9)',
          'solid-hover': 'var(--info-10)',
          text: 'var(--info-11)',
          'text-contrast': 'var(--info-12)',
        },
 

        success: {
          base: 'var(--success-1)',
          'bg-subtle': 'var(--success-2)',
          bg: 'var(--success-3)',
          'bg-hover': 'var(--success-4)',
          'bg-active': 'var(--success-5)',
          line: 'var(--success-6)',
          border: 'var(--success-7)',
          'border-hover': 'var(--success-8)',
          'focus-ring': 'var(--success-8)',
          solid: 'var(--success-9)',
          'solid-hover': 'var(--success-10)',
          text: 'var(--success-11)',
          'text-contrast': 'var(--success-12)',
        },
 

        warning: {
          base: 'var(--warning-1)',
          'bg-subtle': 'var(--warning-2)',
          bg: 'var(--warning-3)',
          'bg-hover': 'var(--warning-4)',
          'bg-active': 'var(--warning-5)',
          line: 'var(--warning-6)',
          border: 'var(--warning-7)',
          'border-hover': 'var(--warning-8)',
          'focus-ring': 'var(--warning-8)',
          solid: 'var(--warning-9)',
          'solid-hover': 'var(--warning-10)',
          text: 'var(--warning-11)',
          'text-contrast': 'var(--warning-12)',
        },
 

        error: {
          base: 'var(--error-1)',
          'bg-subtle': 'var(--error-2)',
          bg: 'var(--error-3)',
          'bg-hover': 'var(--error-4)',
          'bg-active': 'var(--error-5)',
          line: 'var(--error-6)',
          border: 'var(--error-7)',
          'border-hover': 'var(--error-8)',
          'focus-ring': 'var(--error-8)',
          solid: 'var(--error-9)',
          'solid-hover': 'var(--error-10)',
          text: 'var(--error-11)',
          'text-contrast': 'var(--error-12)',
        },
      },
    },
  },
  plugins: [],
};
 
export default config;

Add tailwind animations

Extend the keyframes and animation objects in your theme object.

tailwind.config.ts
const config: Config = {
  darkMode: 'class',
  content: [
    '...',
  ],
  theme: {
    // ...
    extend: {
      // ...

      keyframes: {
        'accordion-down': {
          from: { height: '0' },
          to: { height: 'var(--radix-accordion-content-height)' },
        },
        'accordion-up': {
          from: { height: 'var(--radix-accordion-content-height)' },
          to: { height: '0' },
        },
        'caret-blink': {
          '0%,70%,100%': { opacity: '1' },
          '20%,50%': { opacity: '0' },
        },
        'collapsible-down': {
          from: { height: '0' },
          to: {
            height: 'var(--radix-collapsible-content-height)',
          },
        },
        'collapsible-up': {
          from: {
            height: 'var(--radix-collapsible-content-height)',
          },
          to: { height: '0' },
        },
      },
      animation: {
        'accordion-down': 'accordion-down 0.2s ease-out',
        'accordion-up': 'accordion-up 0.2s ease-out',
        'caret-blink': 'caret-blink 1.25s ease-out infinite',
        'collapsible-down': 'collapsible-down 0.15s ease-out',
        'collapsible-up': 'collapsible-up 0.15s ease-out',
      },
    },
  },
};

Add tailwind plugins

Add the tailwindcss-animate plugin to your Tailwind CSS config.

tailwind.config.ts
import type { Config } from 'tailwindcss';
import animate from 'tailwindcss-animate'; 
 
const config: Config = {
  // ...,
  plugins: [animate], 
};

Add css variables

Add the border radius and color variables to your CSS file. You can learn more about using CSS variables for theming in the colors section.

app/globals.css

  @import '@radix-ui/colors/violet.css';
  @import '@radix-ui/colors/violet-dark.css';
  @import '@radix-ui/colors/mauve.css';
  @import '@radix-ui/colors/mauve-dark.css';
  @import '@radix-ui/colors/blue.css';
  @import '@radix-ui/colors/blue-dark.css';
  @import '@radix-ui/colors/green.css';
  @import '@radix-ui/colors/green-dark.css';
  @import '@radix-ui/colors/yellow.css';
  @import '@radix-ui/colors/yellow-dark.css';
  @import '@radix-ui/colors/red.css';
  @import '@radix-ui/colors/red-dark.css';
 
  @tailwind base;
  @tailwind components;
  @tailwind utilities;
 
  :root {
    --radius: 5rem; 
 

    --primary-1: var(--violet-1);
    --primary-2: var(--violet-2);
    --primary-3: var(--violet-3);
    --primary-4: var(--violet-4);
    --primary-5: var(--violet-5);
    --primary-6: var(--violet-6);
    --primary-7: var(--violet-7);
    --primary-8: var(--violet-8);
    --primary-9: var(--violet-9);
    --primary-10: var(--violet-10);
    --primary-11: var(--violet-11);
    --primary-12: var(--violet-12);
 

    --grey-1: var(--mauve-1);
    --grey-2: var(--mauve-2);
    --grey-3: var(--mauve-3);
    --grey-4: var(--mauve-4);
    --grey-5: var(--mauve-5);
    --grey-6: var(--mauve-6);
    --grey-7: var(--mauve-7);
    --grey-8: var(--mauve-8);
    --grey-9: var(--mauve-9);
    --grey-10: var(--mauve-10);
    --grey-11: var(--mauve-11);
    --grey-12: var(--mauve-12);
 

    --info-1: var(--blue-1);
    --info-2: var(--blue-2);
    --info-3: var(--blue-3);
    --info-4: var(--blue-4);
    --info-5: var(--blue-5);
    --info-6: var(--blue-6);
    --info-7: var(--blue-7);
    --info-8: var(--blue-8);
    --info-9: var(--blue-9);
    --info-10: var(--blue-10);
    --info-11: var(--blue-11);
    --info-12: var(--blue-12);
 

    --success-1: var(--green-1);
    --success-2: var(--green-2);
    --success-3: var(--green-3);
    --success-4: var(--green-4);
    --success-5: var(--green-5);
    --success-6: var(--green-6);
    --success-7: var(--green-7);
    --success-8: var(--green-8);
    --success-9: var(--green-9);
    --success-10: var(--green-10);
    --success-11: var(--green-11);
    --success-12: var(--green-12);
 

    --warning-1: var(--yellow-1);
    --warning-2: var(--yellow-2);
    --warning-3: var(--yellow-3);
    --warning-4: var(--yellow-4);
    --warning-5: var(--yellow-5);
    --warning-6: var(--yellow-6);
    --warning-7: var(--yellow-7);
    --warning-8: var(--yellow-8);
    --warning-9: var(--yellow-9);
    --warning-10: var(--yellow-10);
    --warning-11: var(--yellow-11);
    --warning-12: var(--yellow-12);
 

    --error-1: var(--red-1);
    --error-2: var(--red-2);
    --error-3: var(--red-3);
    --error-4: var(--red-4);
    --error-5: var(--red-5);
    --error-6: var(--red-6);
    --error-7: var(--red-7);
    --error-8: var(--red-8);
    --error-9: var(--red-9);
    --error-10: var(--red-10);
    --error-11: var(--red-11);
    --error-12: var(--red-12);
 
  .dark {

    --primary-1: var(--violet-dark-1);
    --primary-2: var(--violet-dark-2);
    --primary-3: var(--violet-dark-3);
    --primary-4: var(--violet-dark-4);
    --primary-5: var(--violet-dark-5);
    --primary-6: var(--violet-dark-6);
    --primary-7: var(--violet-dark-7);
    --primary-8: var(--violet-dark-8);
    --primary-9: var(--violet-dark-9);
    --primary-10: var(--violet-dark-10);
    --primary-11: var(--violet-dark-11);
    --primary-12: var(--violet-dark-12);
 

    --grey-1: var(--mauve-dark-1);
    --grey-2: var(--mauve-dark-2);
    --grey-3: var(--mauve-dark-3);
    --grey-4: var(--mauve-dark-4);
    --grey-5: var(--mauve-dark-5);
    --grey-6: var(--mauve-dark-6);
    --grey-7: var(--mauve-dark-7);
    --grey-8: var(--mauve-dark-8);
    --grey-9: var(--mauve-dark-9);
    --grey-10: var(--mauve-dark-10);
    --grey-11: var(--mauve-dark-11);
    --grey-12: var(--mauve-dark-12);
 

    --info-1: var(--blue-dark-1);
    --info-2: var(--blue-dark-2);
    --info-3: var(--blue-dark-3);
    --info-4: var(--blue-dark-4);
    --info-5: var(--blue-dark-5);
    --info-6: var(--blue-dark-6);
    --info-7: var(--blue-dark-7);
    --info-8: var(--blue-dark-8);
    --info-9: var(--blue-dark-9);
    --info-10: var(--blue-dark-10);
    --info-11: var(--blue-dark-11);
    --info-12: var(--blue-dark-12);
 

    --success-1: var(--green-dark-1);
    --success-2: var(--green-dark-2);
    --success-3: var(--green-dark-3);
    --success-4: var(--green-dark-4);
    --success-5: var(--green-dark-5);
    --success-6: var(--green-dark-6);
    --success-7: var(--green-dark-7);
    --success-8: var(--green-dark-8);
    --success-9: var(--green-dark-9);
    --success-10: var(--green-dark-10);
    --success-11: var(--green-dark-11);
    --success-12: var(--green-dark-12);
 

    --warning-1: var(--yellow-dark-1);
    --warning-2: var(--yellow-dark-2);
    --warning-3: var(--yellow-dark-3);
    --warning-4: var(--yellow-dark-4);
    --warning-5: var(--yellow-dark-5);
    --warning-6: var(--yellow-dark-6);
    --warning-7: var(--yellow-dark-7);
    --warning-8: var(--yellow-dark-8);
    --warning-9: var(--yellow-dark-9);
    --warning-10: var(--yellow-dark-10);
    --warning-11: var(--yellow-dark-11);
    --warning-12: var(--yellow-dark-12);
 

    --error-1: var(--red-dark-1);
    --error-2: var(--red-dark-2);
    --error-3: var(--red-dark-3);
    --error-4: var(--red-dark-4);
    --error-5: var(--red-dark-5);
    --error-6: var(--red-dark-6);
    --error-7: var(--red-dark-7);
    --error-8: var(--red-dark-8);
    --error-9: var(--red-dark-9);
    --error-10: var(--red-dark-10);
    --error-11: var(--red-dark-11);
    --error-12: var(--red-dark-12);
  }
}

Add utilities

Create the cn() utility function.

app/utils/cn.ts
import type { ClassValue } from 'clsx';
import { clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
 
export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs));

On this page