Vite + Untitled UI

Untitled UI works seamlessly with Vite, offering a fast development experience and optimized production builds. This guide will help you set up a Vite project with Untitled UI, configure Tailwind CSS v4.1, and implement import path aliases.

Installation

The easiest way to get started with Untitled UI in a Vite project is to use our CLI:

1

Initialize a new Vite project with Untitled UI

Using our CLI, you can initialize a new Vite project with Untitled UI with the following command:

npx untitledui@latest init --vite untitled-ui

While running the command, you'll be asked a few questions to set up your project:

? What is your project named? › untitled-ui
? Which color would you like to use as the brand color?
   brand
    error
    warning
    success
 gray-neutral

This will create a new Vite project in the untitled-ui directory with all the necessary configurations and components pre-installed.

2

Ready to go!

Great! You're all set to start using Untitled UI components.

If something is missing, just head over to the component's page and copy/paste what you need into your project.

Manual Installation

If you prefer to add Untitled UI to an existing Vite project, you can follow these steps:

1

Install packages

Simply install the required packages with your favorite package manager:

npm install @untitledui/icons react-aria-components tailwindcss @tailwindcss/vite tailwindcss-react-aria-components tailwind-merge tailwindcss-animate
2

Configure Vite

Update your vite.config.ts (or vite.config.js) file to include the Tailwind CSS plugin and set up path aliases:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
import { resolve } from 'path';
 
export default defineConfig({
  plugins: [
    react(),
    tailwindcss(),
  ],
  resolve: {
    alias: {
      '@': resolve(__dirname, './src'),
    },
  },
});

This configuration does two important things:

  1. Adds the Tailwind CSS Vite plugin for efficient processing
  2. Sets up the @/ path alias to point to your src directory

Note that for TypeScript projects, you'll also need to update your tsconfig.json with the path aliases.

3

Update TypeScript Configuration (for TS projects)

If you're using TypeScript, update your tsconfig.json to include the path alias:

{
  "compilerOptions": {
    // other options...
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}
4

Set up CSS

In your main CSS file (usually src/index.css or src/styles.css), import Tailwind CSS and our plugins directly:

@import "tailwindcss";
@import "tailwindcss-react-aria-components";
@import "tailwindcss-animate";
 
@import "./theme.css";

Make sure to create a theme.css file with Untitled UI's theme variables. You can copy this from our installation docs or generate it using our CLI.

Setting up router provider

To make React Aria components work with client-side routing in Vite, you'll need to set up a RouterProvider:

// src/providers/route-provider.tsx
import { type PropsWithChildren } from "react";
import { RouterProvider } from "react-aria-components";
import { useNavigate, useHref } from "react-router-dom";
import type { NavigateOptions } from "react-router-dom";
 
declare module "react-aria-components" {
  interface RouterConfig {
    routerOptions: NavigateOptions;
  }
}
 
export const RouteProvider = ({ children }: PropsWithChildren) => {
  const navigate = useNavigate();
  
  return (
    <RouterProvider 
      navigate={navigate} 
      useHref={useHref}
    >
      {children}
    </RouterProvider>
  );
};

Then wrap your app with this provider:

// src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { RouteProvider } from './providers/route-provider';
import App from './App';
import './index.css';
 
ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <BrowserRouter>
      <RouteProvider>
        <App />
      </RouteProvider>
    </BrowserRouter>
  </React.StrictMode>
);

Using components with Vite

After setting up your project, you can start using Untitled UI components by importing them from your component library:

// src/App.tsx
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
 
function App() {
  return (
    <div className="container mx-auto p-4">
      <h1 className="text-2xl font-bold">Welcome to Untitled UI + Vite</h1>
      <div className="mt-4">
        <Input placeholder="Enter your name" />
        <Button className="mt-2">Submit</Button>
      </div>
    </div>
  );
}
 
export default App;

Dark mode support

For dark mode support in Vite, you can use a lightweight theme toggle implementation:

// src/components/theme-toggle.tsx
import { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { MoonIcon, SunIcon } from '@untitledui/icons';
 
export function ThemeToggle() {
  const [theme, setTheme] = useState(() => {
    if (typeof window !== 'undefined') {
      return document.documentElement.classList.contains('dark-mode') 
        ? 'dark-mode' 
        : 'light-mode';
    }
    return 'light-mode';
  });
  
  useEffect(() => {
    const root = document.documentElement;
    root.classList.remove('light-mode', 'dark-mode');
    root.classList.add(theme);
    localStorage.setItem('theme', theme);
  }, [theme]);
  
  return (
    <Button
      variant="ghost"
      size="icon"
      onClick={() => setTheme(theme === 'light-mode' ? 'dark-mode' : 'light-mode')}
    >
      {theme === 'light-mode' ? <MoonIcon className="h-5 w-5" /> : <SunIcon className="h-5 w-5" />}
      <span className="sr-only">Toggle theme</span>
    </Button>
  );
}

FAQs

You can either use our CLI command (npx untitledui@latest init --vite) for a complete setup, or manually install the required packages and configure Vite. The key is to use the @tailwindcss/vite plugin and set up your CSS imports correctly with Tailwind CSS v4.1's direct import system.

In your vite.config.ts file, add a resolve.alias configuration that maps '@/' to your source directory. For TypeScript projects, also update your tsconfig.json with matching paths. This allows you to use imports like '@/components/ui/button' instead of relative paths.

Yes, Untitled UI components work seamlessly with Vite's hot module replacement. Changes to your components will be reflected immediately without losing component state, making for a great development experience.

Vite already provides excellent build optimization. For additional performance, use dynamic imports for code-splitting, lazy-load non-critical components, and make sure to use the production build command (npm run build) when deploying.

Tailwind CSS v4.1 integrates with Vite through the @tailwindcss/vite plugin. This is more efficient than the previous PostCSS-based approach. In your CSS, you simply import Tailwind directly with @import 'tailwindcss' and any additional plugins you need.