Skip to main content
The Vercel AI Chatbot uses Tailwind CSS v4 and shadcn/ui for styling, giving you full control over the visual appearance through CSS variables and utility classes.

Design system

The chatbot implements a token-based design system using CSS custom properties defined in app/globals.css. This approach allows you to customize colors, spacing, and other design elements globally.

Color tokens

All colors are defined as HSL values in both light and dark modes:
app/globals.css
:root {
  --background: hsl(0 0% 100%);
  --foreground: hsl(240 10% 3.9%);
  --primary: hsl(240 5.9% 10%);
  --primary-foreground: hsl(0 0% 98%);
  --secondary: hsl(240 4.8% 95.9%);
  --secondary-foreground: hsl(240 5.9% 10%);
  --muted: hsl(240 4.8% 95.9%);
  --muted-foreground: hsl(240 3.8% 46.1%);
  --accent: hsl(240 4.8% 95.9%);
  --accent-foreground: hsl(240 5.9% 10%);
  --destructive: hsl(0 84.2% 60.2%);
  --destructive-foreground: hsl(0 0% 98%);
  --border: hsl(240 5.9% 90%);
  --input: hsl(240 5.9% 90%);
  --ring: hsl(240 10% 3.9%);
  --radius: 0.5rem;
}

Dark mode

Dark mode is implemented using a custom variant that allows programmatic control:
app/globals.css
@custom-variant dark (&:is(.dark, .dark *));

.dark {
  --background: hsl(240 10% 3.9%);
  --foreground: hsl(0 0% 98%);
  --primary: hsl(0 0% 98%);
  --primary-foreground: hsl(240 5.9% 10%);
  /* ... other dark mode tokens */
}
The theme is managed by next-themes in the ThemeProvider component:
components/theme-provider.tsx
import { ThemeProvider as NextThemesProvider } from "next-themes";

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
}

Customizing colors

1

Choose your color palette

Select your brand colors in HSL format. You can use tools like HSL Color Picker to convert hex colors to HSL.
2

Update CSS variables

Modify the color tokens in app/globals.css for both light and dark modes:
app/globals.css
:root {
  --primary: hsl(220 90% 56%); /* Your brand color */
  --primary-foreground: hsl(0 0% 100%);
}

.dark {
  --primary: hsl(220 90% 66%); /* Lighter variant for dark mode */
  --primary-foreground: hsl(0 0% 0%);
}
3

Test across components

The color tokens are automatically applied across all UI components. Test your changes in both light and dark modes to ensure proper contrast and readability.

Customizing components

shadcn/ui configuration

The chatbot uses shadcn/ui components configured in components.json:
components.json
{
  "style": "default",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "css": "app/globals.css",
    "baseColor": "zinc",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils",
    "ui": "@/components/ui"
  }
}

Button variants

All buttons use the Button component with customizable variants:
components/ui/button.tsx
const buttonVariants = cva(
  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md...",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
        outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
        secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "text-primary underline-offset-4 hover:underline",
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 rounded-md px-3",
        lg: "h-11 rounded-md px-8",
        icon: "h-10 w-10",
        "icon-sm": "h-8 w-8",
      },
    },
  }
);
You can add custom variants by modifying this configuration.

Styling chat messages

Message styling is controlled through the Message component:
components/ai-elements/message.tsx
export const MessageContent = ({ children, className, ...props }) => (
  <div
    className={cn(
      "is-user:dark flex w-fit min-w-0 max-w-full flex-col gap-2",
      "group-[.is-user]:ml-auto group-[.is-user]:rounded-lg",
      "group-[.is-user]:bg-secondary group-[.is-user]:px-4 group-[.is-user]:py-3",
      "group-[.is-user]:text-foreground",
      "group-[.is-assistant]:text-foreground",
      className
    )}
    {...props}
  >
    {children}
  </div>
);
User messages are styled with the secondary background color, while assistant messages have no background. Customize these by modifying the MessageContent component or overriding with the className prop.

Custom scrollbar

The chatbot includes custom scrollbar styling for a polished appearance:
app/globals.css
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: transparent;
}

::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 3px;
  transition: background 0.2s ease;
}

::-webkit-scrollbar-thumb:hover {
  background: --alpha(var(--muted-foreground) / 0.5);
}

/* Firefox scrollbar styling */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}

Border radius

Global border radius is controlled by the --radius variable:
app/globals.css
:root {
  --radius: 0.5rem; /* Default radius */
}

@theme {
  --radius-lg: var(--radius);
  --radius-md: calc(var(--radius) - 2px);
  --radius-sm: calc(var(--radius) - 4px);
}
Change --radius to adjust the roundness of all components globally.

Typography

The chatbot uses Geist Sans and Geist Mono fonts:
app/globals.css
@theme {
  --font-sans: var(--font-geist);
  --font-mono: var(--font-geist-mono);
}
To use different fonts, update these variables and import your chosen fonts in app/layout.tsx.

Advanced customization

The sidebar has dedicated color tokens:
app/globals.css
:root {
  --sidebar-background: hsl(0 0% 98%);
  --sidebar-foreground: hsl(240 5.3% 26.1%);
  --sidebar-primary: hsl(240 5.9% 10%);
  --sidebar-accent: hsl(240 4.8% 95.9%);
  --sidebar-border: hsl(220 13% 91%);
}

Suggestion highlights

Document suggestions use a custom highlight style:
app/globals.css
.suggestion-highlight {
  @apply bg-blue-200 hover:bg-blue-300 
         dark:hover:bg-blue-400/50 
         dark:text-blue-50 
         dark:bg-blue-500/40;
}

Code editor theme

The code editor (CodeMirror) styling can be customized:
app/globals.css
.cm-editor,
.cm-gutters {
  @apply bg-background! dark:bg-zinc-800! outline-hidden!;
}

.ͼo.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground {
  @apply bg-zinc-200! dark:bg-zinc-900!;
}
The chatbot uses Tailwind CSS v4’s @theme directive for defining design tokens. This is different from v3’s configuration approach. Learn more in the Tailwind CSS v4 documentation.