shadcn/ui Components

TurboStack uses shadcn/ui - a collection of beautifully designed, accessible React components.

Accessible

Built with Radix UI primitives

Customizable

Style with CSS variables

Copy & Paste

Own your components

Included Components

TurboStack comes with these pre-installed components:
  • Button - Clickable buttons with variants - Input - Text input fields - Textarea - Multi-line text input - Select - Dropdown selection - Checkbox - Boolean checkbox - Switch - Toggle switch - Label - Form labels - Form - Form wrapper with validation

Usage Examples

Button Variants

import { Button } from "@/components/ui/button";

export function ButtonDemo() {
  return (
    <div className="flex gap-4">
      <Button>Default</Button>
      <Button variant="secondary">Secondary</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="destructive">Destructive</Button>
      <Button variant="link">Link</Button>
    </div>
  );
}
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(6),
});

export function LoginForm() {
  const form = useForm({
    resolver: zodResolver(schema),
  });

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)}>
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Email</FormLabel>
              <FormControl>
                <Input placeholder="you@example.com" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit">Login</Button>
      </form>
    </Form>
  );
}
import { toast } from "sonner";
import { Button } from "@/components/ui/button";

export function ToastDemo() {
  return (
    <div className="flex gap-4">
      <Button onClick={() => toast.success("Success!")}>
        Success
      </Button>
      <Button
        variant="destructive"
        onClick={() => toast.error("Error occurred")}
      >
        Error
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.loading("Loading...")}
      >
        Loading
      </Button>
    </div>
  );
}
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";

export function DialogDemo() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button>Open Dialog</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Are you sure?</DialogTitle>
          <DialogDescription>
            This action cannot be undone.
          </DialogDescription>
        </DialogHeader>
        {/* Dialog content here */}
      </DialogContent>
    </Dialog>
  );
}

Adding New Components

1

Browse Available Components

Visit ui.shadcn.com to see all available components.
2

Install Component

cd apps/frontend
npx shadcn@latest add [component-name]

# Examples:
npx shadcn@latest add calendar
npx shadcn@latest add data-table
npx shadcn@latest add chart
3

Import and Use

import { Calendar } from "@/components/ui/calendar";

export function DatePicker() {
  const [date, setDate] = useState<Date>();

  return (
    <Calendar
      mode="single"
      selected={date}
      onSelect={setDate}
    />
  );
}

Theming

CSS Variables

Customize the theme in globals.css:
@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 240 10% 3.9%;
    --primary: 240 5.9% 10%;
    --primary-foreground: 0 0% 98%;
    --secondary: 240 4.8% 95.9%;
    --accent: 240 4.8% 95.9%;
    --destructive: 0 84.2% 60.2%;
    --ring: 240 5% 64.9%;
    --radius: 0.5rem;
  }

  .dark {
    --background: 240 10% 3.9%;
    --foreground: 0 0% 98%;
    --primary: 0 0% 98%;
    --primary-foreground: 240 5.9% 10%;
  }
}

Dark Mode

TurboStack uses next-themes for dark mode:
import { useTheme } from "next-themes";

export function ThemeToggle() {
  const { theme, setTheme } = useTheme();

  return (
    <Button
      variant="ghost"
      onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
    >
      {theme === "dark" ? "🌙" : "☀️"}
    </Button>
  );
}
All shadcn/ui components automatically support dark mode when you toggle the theme.