Урок 17. Примеры: установка по шагам
⚡ Кратко
Полный прогон установки с реальным выводом команд, разбор созданных файлов и первая страница на компонентах.
1. Новый проект целиком
npm create vite@latest tailwind-course -- --template react-ts
cd tailwind-course
npm install
npm install tailwindcss @tailwindcss/vite
npm install -D @types/node
📄 src/index.css
@import "tailwindcss";
📄 vite.config.ts
// 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.json — и то же самое в tsconfig.app.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
npx shadcn@latest 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.
2. Что записал CLI
📄 components.json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "base-nova",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"rtl": false,
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"menuColor": "default",
"menuAccent": "subtle",
"registries": {}
}
📄 src/lib/utils.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
3. Добавляем компоненты
npx shadcn@latest add card input label badge
✔ Checking registry.
✔ Installing dependencies.
✔ Created 4 files:
- src/components/ui/card.tsx
- src/components/ui/input.tsx
- src/components/ui/label.tsx
- src/components/ui/badge.tsx
4. Первая страница
📄 src/App.tsx
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export default function App() {
return (
<main className="flex min-h-svh items-center justify-center bg-background p-6">
<Card className="w-full max-w-sm">
<CardHeader>
<CardTitle>Вход в систему</CardTitle>
<CardDescription>Введите почту и пароль</CardDescription>
</CardHeader>
<CardContent className="grid gap-3">
<div className="grid gap-1.5">
<Label htmlFor="email">Почта</Label>
<Input id="email" type="email" placeholder="name@example.com" />
</div>
<div className="grid gap-1.5">
<Label htmlFor="password">Пароль</Label>
<Input id="password" type="password" />
</div>
</CardContent>
<CardFooter className="justify-end gap-2">
<Button variant="ghost">Отмена</Button>
<Button>Войти</Button>
</CardFooter>
</Card>
</main>
)
}
Как это выглядит:
Вход в систему
Введите почту и пароль
<div class="flex justify-center bg-background p-4">
<div class="w-full max-w-sm overflow-hidden rounded-xl bg-card py-4 text-sm text-card-foreground ring-1 ring-foreground/10">
<div class="grid auto-rows-min gap-1 px-4">
<div class="text-base leading-snug font-medium">Вход в систему</div>
<div class="text-sm text-muted-foreground">Введите почту и пароль</div>
</div>
<div class="grid gap-3 px-4 pt-3">
<div class="grid gap-1.5">
<label class="text-sm leading-none font-medium" for="ex-mail">Почта</label>
<input id="ex-mail" type="email" placeholder="name@example.com"
class="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 py-1 text-sm transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50">
</div>
<div class="grid gap-1.5">
<label class="text-sm leading-none font-medium" for="ex-pass">Пароль</label>
<input id="ex-pass" type="password" value="secret"
class="h-8 w-full rounded-lg border border-input bg-transparent px-2.5 py-1 text-sm transition-colors outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50">
</div>
</div>
<div class="mt-4 flex items-center justify-end gap-2 rounded-b-xl border-t bg-muted/50 p-4">
<button class="inline-flex h-8 items-center justify-center rounded-lg px-2.5 text-sm font-medium hover:bg-muted">Отмена</button>
<button class="inline-flex h-8 items-center justify-center rounded-lg bg-primary px-2.5 text-sm font-medium text-primary-foreground hover:bg-primary/80">Войти</button>
</div>
</div>
</div>
5. Установка в Next.js
npx create-next-app@latest my-app
cd my-app
npx shadcn@latest init
В Next.js алиас @/ уже настроен шаблоном, а Tailwind
подключается через @tailwindcss/postcss. Поле rsc
в конфигурации будет true — CLI добавит директиву
"use client" в компоненты, которым она нужна.
6. Проверка проекта
npx shadcn@latest info
Команда печатает, что CLI «видит» в вашем проекте: фреймворк, версию
Tailwind, путь к CSS, алиасы. Первое, что стоит запустить, если
add ведёт себя странно.