Порядок установки
- проект (Vite, Next.js, Astro, React Router — любой из поддерживаемых);
- Tailwind CSS и его плагин сборки;
- алиас
@/в конфигурации сборщика и в TypeScript; npx shadcn@latest init;npx shadcn@latest add …— по мере надобности.
cn() как @/lib/utils, и этот путь должен
разрешаться и сборщиком, и редактором.Шаг за шагом на Vite
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
npm install tailwindcss @tailwindcss/vite
npm install -D @types/node
@import "tailwindcss";
// vite.config.ts
import path from "path"
import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react"
import { defineConfig } from "vite"
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
})
// tsconfig.json — и то же самое в tsconfig.app.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
Пакет @types/node нужен только затем, чтобы TypeScript
понимал path.resolve и __dirname в конфигурации Vite.
Что делает init
npx shadcn@latest init
✔ Preflight checks.
✔ Verifying framework. Found Vite.
✔ Validating Tailwind CSS. Found v4.
✔ Validating import alias.
✔ Writing components.json.
✔ Checking registry.
✔ Installing dependencies.
✔ Created 2 files:
- src/components/ui/button.tsx
- src/lib/utils.ts
✔ Updating src/index.css
Project initialization completed.
You may now add components.
Разберём вывод по строчкам:
- Verifying framework — CLI определяет, на чём проект;
- Validating Tailwind CSS — находит версию (v4) и главный CSS-файл;
- Validating import alias — проверяет тот самый
алиас
@/; - Writing components.json — сохраняет ответы на будущее;
- Installing dependencies — ставит примитивы,
cva,clsx,tailwind-merge, иконки; - Created 2 files — базовый компонент и
cn(); - Updating index.css — дописывает токены темы и
@theme inline.
init — как обустройство мастерской перед работой: он не
делает мебель, а расставляет верстак, свет и инструменты и записывает,
где что лежит. Каждая последующая команда add — это уже
изготовление конкретной детали по чертежу из реестра.
Что появилось в CSS
Главный файл стилей после init содержит четыре блока:
@import "tailwindcss";
@import "tw-animate-css"; /* анимации оверлеев */
@import "shadcn/tailwind.css"; /* базовые стили реестра */
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
/* … и так для всех ролей */
--radius-lg: var(--radius);
}
:root { --background: oklch(1 0 0); --foreground: oklch(0.145 0 0); /* … */ }
.dark { --background: oklch(0.145 0 0); --foreground: oklch(0.985 0 0); /* … */ }
@layer base {
* { @apply border-border outline-ring/50; }
body { @apply bg-background text-foreground; }
}
Узнаёте? Это ровно тот приём с семантическими токенами, который мы разбирали в уроке 13 — только набор ролей готовый и проверенный.
Алиасы: почему @/ и что настроить
Алиас должен быть прописан дважды, и это разные вещи:
| Где | Зачем | Что будет без этого |
|---|---|---|
vite.config.ts | сборщик разрешает путь при сборке | ошибка сборки: модуль не найден |
tsconfig.json | TypeScript и редактор понимают путь | красные подчёркивания и отсутствие автодополнения |
tsconfig.json и tsconfig.app.json. Пропишите
baseUrl и paths в обоих — иначе редактор будет
подсвечивать импорты как ошибочные, хотя сборка пройдёт.Добавление компонентов
npx shadcn@latest add button card input label
npx shadcn@latest add dialog dropdown-menu tabs table
CLI ставит недостающие зависимости и создаёт файлы. Если компонент
зависит от другого (например, Dialog использует
Button), он добавится автоматически.
src/components/ui/
├── button.tsx
├── card.tsx
├── dialog.tsx
├── dropdown-menu.tsx
├── input.tsx
├── label.tsx
├── table.tsx
└── tabs.tsx
Полезные режимы add
| Команда | Когда пригодится |
|---|---|
add button --dry-run | посмотреть, что произойдёт, ничего не меняя |
add button --diff | сравнить свой файл с версией реестра |
add button --overwrite | перезаписать (осторожно: сотрёт правки) |
add --all | поставить весь набор — удобно для изучения |
view button | прочитать исходник, не добавляя в проект |
Проверка результата
import { Button } from "@/components/ui/button"
export default function App() {
return (
<main className="flex min-h-svh items-center justify-center">
<Button>Click me</Button>
</main>
)
}
<div class="flex min-h-24 items-center justify-center rounded-lg bg-background">
<button class="inline-flex h-8 items-center justify-center rounded-lg bg-primary px-2.5 text-sm font-medium text-primary-foreground transition-all hover:bg-primary/80">
Click me
</button>
</div>
Если кнопка выглядит оформленной — значит, тема подключилась и алиасы работают. Если это обычная системная кнопка — CSS с токенами не импортирован в приложение.