Documentation

Theming

Learn how to customize the appearance of your directory website using Tailwind CSS, Radix UI, and shadcn/ui components.

Dirstarter uses a modern theming system built on top of Tailwind CSS v4, Radix UI primitives, and shadcn/ui components. This guide will help you understand and customize the styles of your website.

Why this theming system?

The combination of Tailwind CSS, Radix UI and shadcn/ui components allows ready-to-use, complex UI components that can be fully customized to match your brands design.

Color System

The color system is defined using CSS variables in the @theme configuration. The base theme includes:

app/styles.css
:root {
  --color-background: hsl(0 0% 100%);
  --color-foreground: hsl(0 0% 12%);
  --color-border: hsl(0 0% 88%);
  --color-input: hsl(0 0% 88%);
  --color-ring: hsl(0 0% 83%);
  --color-card: hsl(0 0% 98%);
  --color-card-foreground: hsl(0 0% 12%);
  --color-popover: hsl(0 0% 100%);
  --color-popover-foreground: hsl(0 0% 3.9%);
  --color-primary: hsl(234 98% 61%);
  --color-primary-foreground: hsl(0 0% 98%);
  --color-secondary: hsl(0 0% 96%);
  --color-secondary-foreground: hsl(0 0% 30%);
  --color-muted: hsl(0 0% 96%);
  --color-muted-foreground: hsl(0 0% 45.1%);
  --color-accent: hsl(0 0% 96%);
  --color-accent-foreground: hsl(0 0% 9%);
  --color-destructive: hsl(0 84.2% 60.2%);
  --color-destructive-foreground: hsl(0 0% 98%);
}

Dark Mode

Dark mode is automatically handled using the prefers-color-scheme media query. The dark theme colors are defined as:

app/styles.css
@media (prefers-color-scheme: dark) {
  :root {
    --color-background: hsl(0 0% 8%);
    --color-foreground: hsl(0 0% 90%);
    --color-border: hsl(0 0% 18%);
    --color-input: hsl(0 0% 18%);
    --color-ring: hsl(0 0% 23%);
    --color-card: hsl(0 0% 11%);
    --color-card-foreground: hsl(0 0% 90%);
    --color-popover: hsl(0 0% 8%);
    --color-popover-foreground: hsl(0 0% 90%);
    --color-primary: hsl(234 98% 61%);
    --color-primary-foreground: hsl(0 0% 98%);
    --color-secondary: hsl(0 0% 13%);
    --color-secondary-foreground: hsl(0 0% 70%);
    --color-muted: hsl(0 0% 13%);
    --color-muted-foreground: hsl(0 0% 60%);
    --color-accent: hsl(0 0% 13%);
    --color-accent-foreground: hsl(0 0% 90%);
    --color-destructive: hsl(0 62.8% 30.6%);
    --color-destructive-foreground: hsl(0 0% 98%);
  }
}

Typography

The typography system uses Geist font as the primary font family by default:

@theme {
  --font-system: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
    "Segoe UI Symbol", "Noto Color Emoji";
  --font-sans: var(--font-geist), var(--font-system);
  --font-display: var(--font-geist), var(--font-system);
}

Component Variants

Components use the cva.style utility for variant management. This is a modern and powerful utility for defining and managing class variants. Here's an example of how variants are defined:

components/ui/button.tsx
const buttonVariants = cva({
  base: "relative border text-sm/tight rounded-md",
  variants: {
    variant: {
      primary: "text-background bg-foreground hover:opacity-90",
      secondary: "bg-background text-secondary-foreground hover:bg-card",
    },
    size: {
      sm: "px-2 py-1",
      md: "px-3 py-2",
      lg: "px-4 py-2.5",
    },
  },
  defaultVariants: {
    variant: "primary",
    size: "lg",
  },
})

Customizing Components

Using Radix UI Primitives

Components are built on top of Radix UI primitives for accessibility and functionality. For example:

const Dialog = DialogPrimitive.Root
const DialogTrigger = DialogPrimitive.Trigger
const DialogPortal = DialogPrimitive.Portal
const DialogClose = DialogPrimitive.Close

Styling with Tailwind

Components use Tailwind CSS for styling. You can customize the appearance by:

  1. Modifying the base styles in the component's cva configuration
  2. Extending the component with additional classes using the className prop
  3. Overriding the theme variables in your CSS

Example: Custom Button

const CustomButton = ({ className, ...props }) => (
  <button
    className={cx(
      buttonVariants({ variant: "primary", size: "lg" }),
      "custom-styles",
      className
    )}
    {...props}
  />
)

Best Practices

  1. Use CSS Variables: Always use theme variables for colors and other design tokens
  2. Maintain Consistency: Follow the established patterns for component variants
  3. Accessibility: Leverage Radix UI primitives for accessible components
  4. Responsive Design: Use the responsive utilities provided by Tailwind
  5. Dark Mode: Test your customizations in both light and dark modes

Extending the Theme

To extend the theme:

  1. Add new CSS variables in the @theme configuration
  2. Create new component variants using cva
  3. Add new utility classes in the Tailwind configuration
  4. Create new components following the established patterns
Edit on GitHub

Last updated on

On this page