Перейти к содержимому
Поиск
Разработка

shadcn Studio: компоненты React и генератор тем — примеры

Практическое руководство по shadcn Studio: установка компонентов, настройка темы для Tailwind CSS 4 и шесть примеров CSS/TSX. Бесплатная мастерская оформления без регистрации с предпросмотром и экспортом CSS/JSON.

Александр НекрасовИзменено:
shadcn Studio — Компоненты и темы. Собственная иллюстрация.

У хорошего интерфейса кнопки, поля, карточки и вкладки выглядят как части одного продукта. Когда каждый элемент оформляется отдельно, даже небольшая страница быстро обрастает разными цветами и отступами. shadcn Studio помогает начать с готовых вариантов компонентов для React, а затем подобрать общую тему и изменить код под свою задачу.

Ниже — бесплатная интерактивная мастерская без регистрации: выберите палитру, настройте цвета и скругления, сравните светлый и темный режимы на нескольких элементах интерфейса. После демонстрации разберем установку, CSS-переменные и собственные примеры TSX, которые можно использовать в своем проекте.

Выберите палитру, проверьте, перенесите

Мастерская темы для вашего интерфейса

Настройте цвета и скругления. Посмотрите оформление на кнопках, форме и карточках, затем скачайте CSS для своего проекта.

БесплатноБез регистрации

Загрузка мастерской…

Продолжите в своём проекте

В архиве — исходники нашей учебной мастерской и инструкция запуска. Компоненты для React добавьте по инструкции в статье.

Скачать пример проекта

Учебная мастерская — ae-nekrasov.ru. Материал посвящён shadcn Studio. Настройки обрабатываются в браузере.

Мастерская на этой странице создана нами для изучения темизации. Предпросмотр использует HTML и собственные стили с совместимыми именами токенов; это не официальный редактор Studio и не приложение на shadcn/ui. CSS переносит настройки оформления, JSON сохраняет проект мастерской. React-примеры ниже показывают, как применять тот же принцип в настоящем React-проекте.

Что такое shadcn Studio

В официальном репозитории shadcn Studio представлены варианты компонентов, блоки и инструменты оформления. Подход основан на добавлении исходного кода в проект: после установки можно менять разметку, классы и поведение. Обновления не заменяют внесенные вами изменения автоматически, поэтому перед повторным добавлением компонента полезно сравнить файлы.

В каталоге есть бесплатные и платные ресурсы. Для знакомства достаточно бесплатных компонентов и ручной настройки темы. PRO открывает дополнительные возможности и материалы; условия конкретного ресурса проверяйте на официальной странице. По вводной документации, Studio развивается отдельно от shadcn/ui и предлагает варианты поверх его экосистемы.

У бесплатной части лицензия MIT с дополнительными условиями Commons Clause. Условия ограничивают распространение неизмененных компонентов и создание конкурирующих продуктов. Поэтому наш материал объясняет подключение, а примеры ниже — собственные композиции из обычных shadcn/ui-элементов. Смотрите лицензию репозитория и раздел лицензирования Studio.

Установка: сначала проект, затем выбранные элементы

Понадобится React-проект со сборкой TypeScript/TSX, Tailwind CSS и настроенным shadcn/ui. Для нового проекта на Vite официальный CLI предлагает интерактивную подготовку. Выберите подходящие стиль и основу компонентов; в примерах ниже используются обычные API Button, Card, Input, Label, Badge и Tabs:

npx shadcn@latest init -t vite
npx shadcn@latest add button card input label badge tabs

Для существующего проекта не нужно создавать новый: настройте Tailwind, пути импорта @/ и файл components.json по инструкции shadcn/ui для Vite. Путь к глобальному CSS зависит от проекта: например, src/index.css в Vite или app/globals.css в Next.js. Компоненты должны читать этот файл через вашу сборку. Примеры рассчитаны на Vite; в Next.js файлы с состоянием и обработчиками событий должны быть клиентскими компонентами с директивой "use client" в начале.

Для бесплатных вариантов самого Studio зарегистрируйте его пространство имен, затем добавьте конкретный вариант. button-01 приведен в официальной инструкции как бесплатный:

npx shadcn@latest registry add "@shadcn-studio=https://shadcnstudio.com/r/{style}/{name}.json"
npx shadcn@latest add @shadcn-studio/button-01

Первая команда настраивает реестр, вторая устанавливает вариант; она не является установкой всех возможностей Studio. Перед подтверждением посмотрите, какие файлы и зависимости добавляются. Не включайте перезапись измененных файлов без сравнения. Актуальные команды и различия бесплатных и PRO-реестров описаны в документации Studio CLI.

Пример 1. Цвета как роли, а не разрозненные значения

Токен описывает роль цвета. --background отвечает за поверхность страницы, --foreground — за текст, --primary и --primary-foreground — за главное действие и надпись на нем. Если поменять эту пару, все элементы, использующие ее, получают единый вид. Темному режиму нужны собственные значения: простое затемнение страницы часто делает текст менее читаемым.

:root {
  --background: #f7f8fa;
  --foreground: #18212b;
  --card: #ffffff;
  --card-foreground: #18212b;
  --primary: #155e63;
  --primary-foreground: #ffffff;
  --muted: #eaf0f1;
  --muted-foreground: #52616b;
  --border: #cad7da;
  --input: #cad7da;
  --ring: #155e63;
  --radius: 0.75rem;
}

.dark {
  --background: #101c22;
  --foreground: #edf6f7;
  --card: #182a32;
  --card-foreground: #edf6f7;
  --primary: #8fd8d2;
  --primary-foreground: #102a2c;
  --muted: #233942;
  --muted-foreground: #b1c7ce;
  --border: #38535e;
  --input: #38535e;
  --ring: #8fd8d2;
}

Это сокращенный фрагмент нашей палитры: другие токены существующей темы сохраняйте. Не заменяйте им весь глобальный файл. Имена и пары цветов соответствуют правилам темизации shadcn/ui. В современных темах используются полноценные значения цветов, включая HEX или OKLCH; старые инструкции с hsl(var(--primary)) нельзя смешивать с такими значениями без адаптации.

Пример 2. Связь переменных с Tailwind CSS 4

Объявить переменную недостаточно, чтобы появился класс Tailwind. В настроенном shadcn-проекте связь обычно уже создана CLI. При ручной настройке проверьте блок @theme inline. Он позволяет применять семантические классы: bg-primary, text-primary-foreground и border-border, вместо повторения конкретного цвета в каждом элементе.

/* Фрагмент существующего CSS после подключения Tailwind 4. */
@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --color-card: var(--card);
  --color-card-foreground: var(--card-foreground);
  --color-primary: var(--primary);
  --color-primary-foreground: var(--primary-foreground);
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-border: var(--border);
  --color-input: var(--input);
  --color-ring: var(--ring);
  --radius-lg: var(--radius);
}

Сохраните остальные сопоставления и шкалу радиусов своего проекта. Директива обрабатывается сборкой Tailwind, а обычный браузер не превращает ее в CSS-классы. Подробнее — в официальном руководстве Tailwind по переменным темы. Переключение светлой и темной схемы подключается отдельно; для Vite есть пример ThemeProvider, который управляет классом .dark.

Пример 3. Кнопки с понятной иерархией

Одно действие выделяем цветом, дополнительное оставляем контурным. Состояние результата показываем текстом: посетитель должен понять, произошло ли действие. Здесь кнопка лишь демонстрирует локальный выбор — серверного сохранения нет. Такой небольшой пример полезен для проверки палитры, фокуса и длинной подписи.

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

export function ThemeActions() {
  const [message, setMessage] = useState("");

  return (
    <div className="space-y-3">
      <div className="flex flex-wrap gap-3">
        <Button onClick={() => setMessage("Оформление выбрано")}>
          Использовать оформление
        </Button>
        <Button variant="outline" onClick={() => setMessage("")}>
          Сбросить выбор
        </Button>
      </div>
      <p role="status" className="text-sm text-muted-foreground">
        {message}
      </p>
    </div>
  );
}

Для состояния загрузки блокируйте повторное нажатие и объясняйте его надписью. Для перехода на другую страницу используйте ссылку с соответствующим оформлением. Свойства variant и способы применения приведены в документации Button; варианты Studio можно искать в его каталоге кнопок.

Пример 4. Карточка проекта

Карточка группирует название, статус и краткое пояснение. Отдельные поверхности помогают проверить тему на реальном содержимом. Не делайте всю карточку неочевидной кликабельной областью, если внутри есть несколько действий: отдельная кнопка или ссылка понятнее. Здесь карточка остается обычным информационным блоком.

import { Badge } from "@/components/ui/badge";
import {
  Card, CardContent, CardDescription, CardHeader, CardTitle
} from "@/components/ui/card";

export function ProjectCard() {
  return (
    <Card className="w-full max-w-md">
      <CardHeader className="space-y-3">
        <Badge variant="secondary">В работе</Badge>
        <CardTitle>Личный кабинет клиента</CardTitle>
        <CardDescription>
          Документы, этапы проекта и понятная обратная связь.
        </CardDescription>
      </CardHeader>
      <CardContent>
        <p className="text-sm">Следующий этап: согласование макета.</p>
      </CardContent>
    </Card>
  );
}

max-w-md ограничивает ширину, а w-full позволяет карточке занять доступное место на телефоне. Не назначайте фиксированную высоту ради выравнивания: длинное описание должно помещаться. Больше вариантов есть в официальном каталоге Card.

Пример 5. Форма с подписью и обратной связью

Красивого поля недостаточно: нужны подпись, понятное действие и результат. Используем встроенную проверку обязательного email браузером. Отправка ниже учебная: данные не уходят на сервер. В рабочем продукте подключите обработчик и проверку на сервере, сохранив сообщения об ошибках рядом с полями.

import { useId, useState, type FormEvent } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";

export function ContactPreview() {
  const emailId = useId();
  const [message, setMessage] = useState("");

  function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setMessage("Форма прошла проверку. Это учебный пример без отправки.");
  }

  return (
    <form onSubmit={submit} className="max-w-md space-y-4">
      <div className="space-y-2">
        <Label htmlFor={emailId}>Электронная почта</Label>
        <Input id={emailId} name="email" type="email"
          autoComplete="email" placeholder="name@example.com" required />
      </div>
      <Button type="submit">Проверить форму</Button>
      <p role="status" className="text-sm text-muted-foreground">
        {message}
      </p>
    </form>
  );
}

useId() связывает подпись с конкретным полем даже при нескольких формах на странице. Placeholder дает пример, но не заменяет Label. Проверяйте активное поле и ошибку в обеих схемах. Свойства поля описаны в документации Input.

Пример 6. Вкладки для связанной информации

Вкладки полезны, когда несколько разделов относятся к одному объекту: описание, состав, параметры. Они сокращают видимую длину блока, но скрывают часть информации. Критичные условия заказа лучше показывать сразу. Короткие названия удобнее на узком экране и не требуют горизонтального прокручивания.

import {
  Tabs, TabsContent, TabsList, TabsTrigger
} from "@/components/ui/tabs";

export function ProjectTabs() {
  return (
    <Tabs defaultValue="overview" className="w-full max-w-lg">
      <TabsList className="grid w-full grid-cols-2">
        <TabsTrigger value="overview">Описание</TabsTrigger>
        <TabsTrigger value="details">Состав</TabsTrigger>
      </TabsList>
      <TabsContent value="overview" className="p-4">
        Единая тема для кабинета клиента и страницы проекта.
      </TabsContent>
      <TabsContent value="details" className="p-4">
        Кнопки, карточки, поля формы и понятные статусы.
      </TabsContent>
    </Tabs>
  );
}

Значения value связывают переключатели с содержимым, а defaultValue определяет начальный раздел. Используйте компонент вкладок, чтобы не собирать управление фокусом вручную. Поведение и варианты приведены в документации Tabs.

Как перенести результат в свой проект

Начните с готовой палитры, затем настройте основной цвет, текст и фон. Проверьте кнопку, карточку и форму; после этого переключите тему и повторите проверку. В мастерской скачайте CSS для оформления и JSON для возврата к настройкам. CSS не добавляет поведение React-компонентов, а JSON не является реестром Studio.

В рабочем shadcn-проекте обновите значения в существующих блоках :root и .dark, сохранив подключение Tailwind и дополнительные токены. В официальном генераторе Studio также предусмотрен ручной перенос CSS-переменных; установка сохраненной пользовательской темы одной командой отмечена как PRO. Для больших проектов полезно рассмотреть его расширенные настройки.

Перед публикацией пройдите страницу клавиатурой, проверьте видимый фокус, контраст, перенос длинных названий и форму на телефоне. Готовая библиотека помогает начать, но удобство итоговой страницы зависит от выбранной композиции и содержания. Для следующего шага посмотрите примеры анимации React Bits, генерацию PDF в React или конструктор страницы на Bootstrap 5.