Вёрстка сайта с использованием Shadcn/UI
Shadcn/UI — это не npm-пакет, а коллекция копируемых компонентов на основе Radix UI Primitives и Tailwind CSS. Компоненты добавляются в проект через CLI — исходный код оказывается прямо в репозитории и может быть изменён без форков. Это принципиально отличает Shadcn/UI от традиционных библиотек.
Инициализация
npx shadcn@latest init
CLI спрашивает о стиле (default/new-york), base color, alias для утилит. Конфигурация записывается в components.json:
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/styles/globals.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
Добавление компонентов:
npx shadcn@latest add button card dialog form input select table tabs
Каждая команда создаёт файл в src/components/ui/.
Цветовая система через CSS-переменные
/* src/styles/globals.css */
@import "tailwindcss";
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222 47% 11%;
--card: 0 0% 100%;
--card-foreground: 222 47% 11%;
--popover: 0 0% 100%;
--popover-foreground: 222 47% 11%;
--primary: 221 83% 53%; /* #2563eb */
--primary-foreground: 0 0% 100%;
--secondary: 210 40% 96%;
--secondary-foreground: 222 47% 11%;
--muted: 210 40% 96%;
--muted-foreground: 215 16% 47%;
--accent: 210 40% 96%;
--accent-foreground: 222 47% 11%;
--destructive: 0 84% 60%;
--destructive-foreground: 0 0% 100%;
--border: 214 32% 91%;
--input: 214 32% 91%;
--ring: 221 83% 53%;
--radius: 0.5rem;
}
.dark {
--background: 222 47% 7%;
--foreground: 210 40% 98%;
--card: 222 47% 11%;
--card-foreground: 210 40% 98%;
--popover: 222 47% 11%;
--popover-foreground: 210 40% 98%;
--primary: 217 91% 60%;
--primary-foreground: 0 0% 100%;
--secondary: 217 33% 17%;
--secondary-foreground: 210 40% 98%;
--muted: 217 33% 17%;
--muted-foreground: 215 20% 65%;
--accent: 217 33% 17%;
--accent-foreground: 210 40% 98%;
--destructive: 0 63% 31%;
--destructive-foreground: 210 40% 98%;
--border: 217 33% 17%;
--input: 217 33% 17%;
--ring: 217 91% 60%;
}
}
Компоненты из коробки: примеры использования
Диалог с формой
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
const ContactDialog = () => (
<Dialog>
<DialogTrigger asChild>
<Button>Связаться</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Свяжитесь с нами</DialogTitle>
<DialogDescription>
Заполните форму и мы ответим в течение 24 часов.
</DialogDescription>
</DialogHeader>
<div className="flex flex-col gap-4 py-4">
<div className="flex flex-col gap-2">
<Label htmlFor="name">Имя</Label>
<Input id="name" placeholder="Иван Иванов" />
</div>
<div className="flex flex-col gap-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="[email protected]" />
</div>
</div>
<DialogFooter>
<Button type="submit" className="w-full">Отправить</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
Форма с React Hook Form + Zod
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import * as z from 'zod';
const formSchema = z.object({
email: z.string().email('Некорректный email'),
name: z.string().min(2, 'Минимум 2 символа'),
subject: z.string().min(5, 'Минимум 5 символов'),
});
type FormValues = z.infer<typeof formSchema>;
const LeadForm = () => {
const form = useForm<FormValues>({ resolver: zodResolver(formSchema) });
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-5">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>Имя</FormLabel>
<FormControl>
<Input placeholder="Иван Иванов" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" placeholder="[email protected]" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" className="w-full">
Отправить заявку
</Button>
</form>
</Form>
);
};
Карточки с Tabs
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
const PricingTabs = () => (
<Tabs defaultValue="monthly" className="mx-auto max-w-2xl">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="monthly">Ежемесячно</TabsTrigger>
<TabsTrigger value="annual">Ежегодно</TabsTrigger>
</TabsList>
<TabsContent value="monthly">
<Card>
<CardHeader>
<CardTitle>Ежемесячная подписка</CardTitle>
<CardDescription>Оплата каждый месяц, отмена в любое время.</CardDescription>
</CardHeader>
<CardContent>
{/* Контент тарифов */}
</CardContent>
</Card>
</TabsContent>
<TabsContent value="annual">
<Card>
<CardHeader>
<CardTitle>Годовая подписка</CardTitle>
<CardDescription>Экономия 20% по сравнению с месячным тарифом.</CardDescription>
</CardHeader>
<CardContent>
{/* Контент тарифов */}
</CardContent>
</Card>
</TabsContent>
</Tabs>
);
Кастомизация компонентов
Поскольку код компонента в проекте, его можно модифицировать напрямую:
// src/components/ui/button.tsx — добавить вариант
const buttonVariants = cva(
'inline-flex items-center justify-center ...',
{
variants: {
variant: {
default: '...',
// Добавить новый вариант
gradient: 'bg-gradient-to-r from-brand-500 to-violet-600 text-white hover:opacity-90',
},
},
}
);
Обновление компонентов
# Проверить обновления
npx shadcn@latest diff
# Обновить конкретный компонент
npx shadcn@latest add button --overwrite
Сроки
Инициализация Shadcn/UI и базовая настройка темы: 1–2 часа. Добавление и кастомизация нужных компонентов: 2–4 часа. Посадочная страница на Shadcn/UI + Tailwind + React: 1–2 дня. Shadcn/UI хорошо подходит для SaaS-продуктов, admin-панелей и любых проектов, где нужен профессиональный UI с полным контролем над кодом компонентов.







