Создание интерфейса на компонентах shadcn/ui

В прошлом уроке мы вывели данные из базы Convex в виде простого текста. Чтобы превратить этот список в профессиональный интерфейс стартапа, не нужно быть дизайнером или писать сотни строк CSS. Мы воспользуемся инструментами, которые экономят недели разработки.

Почему мы не пишем CSS с нуля

Для MVP важна скорость проверки гипотез. В современной разработке принят компонентный подход: вы не рисуете каждую кнопку, а собираете интерфейс из готовых, качественных блоков.

Мы будем использовать shadcn/ui. Это не библиотека в привычном смысле, а UI-кит — набор исходного кода элементов. Вы копируете код компонента в свой проект (в папку components/ui) и получаете над ним полный контроль. Нужно изменить логику работы выпадающего списка? Просто откройте файл и поправьте его.

Инструменты дизайна

Для настройки внешнего вида используется Tailwind CSS. Это фреймворк, где стили задаются прямо в коде страницы через короткие классы:

  • flex — выравнивает элементы в ряд.
  • gap-4 — создает отступы.
  • bg-blue-500 — заливает фон синим.
  • rounded-xl — закругляет углы.

В шаблонах Next.js Tailwind уже настроен. Вам остается только комбинировать классы, как конструктор.

Установка первой детали: Кнопка

Вместо копирования кода вручную, используем CLI (командную строку). Введите в терминале:

npx shadcn-ui@latest add button

В проекте появится файл components/ui/button.tsx. Теперь кнопку можно импортировать в любой экран.

Плохо (обычный HTML):

<button style={{backgroundColor: 'blue', borderRadius: '8px', padding: '10px'}}>
  Отправить
</button>

Проблема: такой код трудно менять, он быстро превращается в «спагетти».

Хорошо (shadcn/ui + Tailwind):

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

export default function Page() {
  return (
    <Button variant="default" className="shadow-lg">
      Отправить
    </Button>
  )
}

Практикум: Создаем карточку товара или задачи

Свяжем данные из Convex с красивой версткой. Нам понадобятся компоненты Card (карточка) и Badge (статус-метка).

Добавьте их в проект:

npx shadcn-ui@latest add card badge

Создадим компонент TaskList.tsx, который отобразит данные из базы в виде сетки:

'use client'

import { useQuery } from "convex/react";
import { api } from "../convex/_generated/api";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";

export function TaskList() {
  const tasks = useQuery(api.tasks.get);

  if (!tasks) return <p>Загрузка...</p>;

  return (
    <div className="grid gap-4 p-6"> 
      {tasks.map((task) => (
        <Card key={task._id} className="hover:shadow-md transition-shadow">
          <CardHeader className="flex flex-row items-center justify-between">
            <CardTitle className="text-lg">{task.text}</CardTitle>
            <Badge variant={task.isCompleted ? "default" : "secondary"}>
              {task.isCompleted ? "Готово" : "В работе"}
            </Badge>
          </CardHeader>
          <CardContent>
            <Button size="sm" variant="outline">Редактировать</Button>
          </CardContent>
        </Card>
      ))}
    </div>
  );
}

Итоги урока

  1. Внешний вид: Приложение выглядит как современный SaaS-сервис благодаря выверенным отступам и шрифтам shadcn/ui.
  2. Связь с данными: Мы объединили useQuery и визуальные компоненты. Как только данные в Convex изменятся, интерфейс обновится сам.
  3. Управляемость: Любой элемент можно перекрасить или изменить за секунды через классы Tailwind.

Совет: Установите расширение Tailwind CSS IntelliSense для VS Code. Оно подсказывает названия классов и показывает цвет прямо в редакторе. 💡

Сейчас наше приложение открыто для всех. Чтобы превратить его в настоящий бизнес, нужно разграничить доступ. В следующем уроке мы внедрим авторизацию, чтобы пользователи могли входить через Google или GitHub и работать только со своими данными.