GitHub

Manual Installation

Add dependencies to your project manually.

Add Tailwind CSS

Components are styled using Tailwind CSS. You need to install Tailwind CSS in your project.

Follow the Tailwind CSS installation instructions to get started.

Add dependencies

Add the following dependencies to your project:

npm install tailwindcss-animate class-variance-authority clsx tailwind-merge

Edit tsconfig.json file

Add the following code to the tsconfig.json file to resolve paths:

{
  "compilerOptions": {
    // ...
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./src/*"
      ]
    }
    // ...
  }
}

Update vite.config.ts

Add the following code to the vite.config.ts so your app can resolve paths without error

# (so you can import "path" without error)
npm i -D @types/node
import path from "path"
 
import solid from "@vitejs/plugin-solid"
import { defineConfig } from "vite"
 
export default defineConfig({
  plugins: [solid()],
  resolve: {
    alias: {
      "~": path.resolve(__dirname, "./src")
    }
  }
})

Configure tailwind.config.js

Here's what my tailwind.config.js file looks like:

/**@type {import("tailwindcss").Config} */
module.exports = {
  darkMode: ["variant", [".dark &", '[data-kb-theme="dark"] &']],
  content: ["./src/**/*.{ts,tsx}"],
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px"
      }
    },
    extend: {
      colors: {
        border: "hsl(var(--border))",
        input: "hsl(var(--input))",
        ring: "hsl(var(--ring))",
        background: "hsl(var(--background))",
        foreground: "hsl(var(--foreground))",
        primary: {
          DEFAULT: "hsl(var(--primary))",
          foreground: "hsl(var(--primary-foreground))"
        },
        secondary: {
          DEFAULT: "hsl(var(--secondary))",
          foreground: "hsl(var(--secondary-foreground))"
        },
        destructive: {
          DEFAULT: "hsl(var(--destructive))",
          foreground: "hsl(var(--destructive-foreground))"
        },
        info: {
          DEFAULT: "hsl(var(--info))",
          foreground: "hsl(var(--info-foreground))"
        },
        success: {
          DEFAULT: "hsl(var(--success))",
          foreground: "hsl(var(--success-foreground))"
        },
        warning: {
          DEFAULT: "hsl(var(--warning))",
          foreground: "hsl(var(--warning-foreground))"
        },
        error: {
          DEFAULT: "hsl(var(--error))",
          foreground: "hsl(var(--error-foreground))"
        },
        muted: {
          DEFAULT: "hsl(var(--muted))",
          foreground: "hsl(var(--muted-foreground))"
        },
        accent: {
          DEFAULT: "hsl(var(--accent))",
          foreground: "hsl(var(--accent-foreground))"
        },
        popover: {
          DEFAULT: "hsl(var(--popover))",
          foreground: "hsl(var(--popover-foreground))"
        },
        card: {
          DEFAULT: "hsl(var(--card))",
          foreground: "hsl(var(--card-foreground))"
        }
      },
      borderRadius: {
        xl: "calc(var(--radius) + 4px)",
        lg: "var(--radius)",
        md: "calc(var(--radius) - 2px)",
        sm: "calc(var(--radius) - 4px)"
      },
      keyframes: {
        "accordion-down": {
          from: { height: 0 },
          to: { height: "var(--kb-accordion-content-height)" }
        },
        "accordion-up": {
          from: { height: "var(--kb-accordion-content-height)" },
          to: { height: 0 }
        },
        "content-show": {
          from: { opacity: 0, transform: "scale(0.96)" },
          to: { opacity: 1, transform: "scale(1)" }
        },
        "content-hide": {
          from: { opacity: 1, transform: "scale(1)" },
          to: { opacity: 0, transform: "scale(0.96)" }
        }
      },
      animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
        "content-show": "content-show 0.2s ease-out",
        "content-hide": "content-hide 0.2s ease-out"
      }
    }
  },
  plugins: [require("tailwindcss-animate")]
}

Configure styles

Add the following to your app.css file:

@tailwind base;
@tailwind components;
@tailwind utilities;
 
@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 240 10% 3.9%;
 
    --muted: 240 4.8% 95.9%;
    --muted-foreground: 240 3.8% 46.1%;
 
    --popover: 0 0% 100%;
    --popover-foreground: 240 10% 3.9%;
 
    --border: 240 5.9% 90%;
    --input: 240 5.9% 90%;
 
    --card: 0 0% 100%;
    --card-foreground: 240 10% 3.9%;
 
    --primary: 240 5.9% 10%;
    --primary-foreground: 0 0% 98%;
 
    --secondary: 240 4.8% 95.9%;
    --secondary-foreground: 240 5.9% 10%;
 
    --accent: 240 4.8% 95.9%;
    --accent-foreground: 240 5.9% 10%;
 
    --destructive: 0 84.2% 60.2%;
    --destructive-foreground: 0 0% 98%;
 
    --info: 204 94% 94%;
    --info-foreground: 199 89% 48%;
 
    --success: 149 80% 90%;
    --success-foreground: 160 84% 39%;
 
    --warning: 48 96% 89%;
    --warning-foreground: 25 95% 53%;
 
    --error: 0 93% 94%;
    --error-foreground: 0 84% 60%;
 
    --ring: 240 5.9% 10%;
 
    --radius: 0.5rem;
  }
 
  .dark,
  [data-kb-theme="dark"] {
    --background: 240 10% 3.9%;
    --foreground: 0 0% 98%;
 
    --muted: 240 3.7% 15.9%;
    --muted-foreground: 240 5% 64.9%;
 
    --accent: 240 3.7% 15.9%;
    --accent-foreground: 0 0% 98%;
 
    --popover: 240 10% 3.9%;
    --popover-foreground: 0 0% 98%;
 
    --border: 240 3.7% 15.9%;
    --input: 240 3.7% 15.9%;
 
    --card: 240 10% 3.9%;
    --card-foreground: 0 0% 98%;
 
    --primary: 0 0% 98%;
    --primary-foreground: 240 5.9% 10%;
 
    --secondary: 240 3.7% 15.9%;
    --secondary-foreground: 0 0% 98%;
 
    --destructive: 0 62.8% 30.6%;
    --destructive-foreground: 0 0% 98%;
 
    --info: 204 94% 94%;
    --info-foreground: 199 89% 48%;
 
    --success: 149 80% 90%;
    --success-foreground: 160 84% 39%;
 
    --warning: 48 96% 89%;
    --warning-foreground: 25 95% 53%;
 
    --error: 0 93% 94%;
    --error-foreground: 0 84% 60%;
 
    --ring: 240 4.9% 83.9%;
 
    --radius: 0.5rem;
  }
}
 
@layer base {
  * {
    @apply border-border;
  }
  body {
    @apply bg-background text-foreground;
    font-feature-settings:
      "rlig" 1,
      "calt" 1;
  }
}
 
@media (max-width: 640px) {
  .container {
    @apply px-4;
  }
}

Add a cn helper

I use a cn helper to make it easier to conditionally add Tailwind CSS classes. Here's how I define it in lib/utils.ts:

import type { ClassValue } from "clsx"
import { clsx } from "clsx"
import { twMerge } from "tailwind-merge"
 
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

That's it

You can now start adding components to your project.