PurpleSchool — курсы программирования онлайн
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развития
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • Карьерные пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
    • Backend разработчик Python
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI тренажёр
    • Проекты
PurpleSchool — платформа бесплатных roadmap и курсов для разработчиков
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • AI разработкаИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • PurpleSchool — курсы программирования онлайн
    • Сообщество
    • PurpleПлюс
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Дизайн-система в React с нуля: токены, компоненты и Storybook

    Дизайн-система в React с нуля: токены, компоненты и Storybook

    Аватар автора Дизайн-система в React с нуля: токены, компоненты и Storybook

    Антон Ларичев

    Иконка календаря20 марта 2026
    reacttypescriptcssmiddleИконка уровня middle
    Картинка поста Дизайн-система в React с нуля: токены, компоненты и Storybook

    Введение

    Дизайн-система в React — это набор переиспользуемых компонентов, дизайн-токенов и правил, которые обеспечивают единообразие интерфейса во всём приложении. Без неё каждый разработчик в команде изобретает свои отступы, цвета и размеры кнопок, а продукт превращается в лоскутное одеяло из несогласованных стилей.

    В этой статье разберём, как построить дизайн-систему в React с нуля: от определения дизайн-токенов до создания компонентов и их документирования в Storybook. Рассмотрим практический пример с TypeScript и CSS-переменными.

    Что такое дизайн-токены и зачем они нужны

    Дизайн-токены — это базовые значения визуального языка: цвета, шрифты, отступы, радиусы скруглений, тени. Вместо того чтобы разбрасывать магические числа по коду, токены хранят все значения в одном месте.

    Трёхуровневая структура токенов помогает масштабировать систему:

    // tokens/colors.ts — базовые (core) токены
    export const coreColors = {
      purple100: '#f3e8ff',
      purple500: '#8b5cf6',
      purple900: '#4c1d95',
      gray100: '#f3f4f6',
      gray900: '#111827',
      white: '#ffffff',
    } as const;
    
    // tokens/semantic.ts — семантические токены
    export const semanticColors = {
      textPrimary: coreColors.gray900,
      textSecondary: coreColors.purple900,
      backgroundPrimary: coreColors.white,
      backgroundAccent: coreColors.purple100,
      borderDefault: coreColors.gray100,
      brandPrimary: coreColors.purple500,
    } as const;
    

    Семантические токены не привязаны к конкретному цвету — они описывают назначение. Это позволяет легко добавить тёмную тему, поменяв только маппинг семантических токенов на базовые.

    Как превратить токены в CSS-переменные

    Чтобы дизайн-токены работали в стилях, преобразуем их в CSS-переменные:

    // tokens/cssVariables.ts
    import { semanticColors } from './semantic';
    
    export function applyTokens(element: HTMLElement = document.documentElement) {
      const tokenMap: Record<string, string> = {
        '--color-text-primary': semanticColors.textPrimary,
        '--color-text-secondary': semanticColors.textSecondary,
        '--color-bg-primary': semanticColors.backgroundPrimary,
        '--color-bg-accent': semanticColors.backgroundAccent,
        '--color-border': semanticColors.borderDefault,
        '--color-brand': semanticColors.brandPrimary,
      };
    
      Object.entries(tokenMap).forEach(([key, value]) => {
        element.style.setProperty(key, value);
      });
    }
    

    Теперь в CSS компонентов используем переменные вместо жёстких значений:

    .button-primary {
      background-color: var(--color-brand);
      color: var(--color-bg-primary);
      border-radius: var(--radius-md);
      padding: var(--spacing-sm) var(--spacing-md);
    }
    

    Как создать компоненты дизайн-системы в React

    Компоненты дизайн-системы строятся по принципу Atomic Design: от простых атомов (кнопка, инпут) к молекулам (поле ввода с лейблом) и организмам (форма). Начнём с базового компонента Button.

    // components/Button/Button.tsx
    import React from 'react';
    import styles from './Button.module.css';
    
    type ButtonVariant = 'primary' | 'secondary' | 'ghost';
    type ButtonSize = 'sm' | 'md' | 'lg';
    
    interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
      variant?: ButtonVariant;
      size?: ButtonSize;
      isLoading?: boolean;
    }
    
    export const Button: React.FC<ButtonProps> = ({
      variant = 'primary',
      size = 'md',
      isLoading = false,
      children,
      disabled,
      className,
      ...props
    }) => {
      return (
        <button
          className={`${styles.button} ${styles[variant]} ${styles[size]} ${className ?? ''}`}
          disabled={disabled || isLoading}
          {...props}
        >
          {isLoading ? <span className={styles.spinner} /> : children}
        </button>
      );
    };
    
    /* components/Button/Button.module.css */
    .button {
      font-family: var(--font-family);
      font-weight: 500;
      border: none;
      cursor: pointer;
      transition: background-color 0.2s, opacity 0.2s;
    }
    
    .primary {
      background-color: var(--color-brand);
      color: var(--color-bg-primary);
    }
    
    .secondary {
      background-color: var(--color-bg-accent);
      color: var(--color-text-secondary);
    }
    
    .ghost {
      background-color: transparent;
      color: var(--color-text-primary);
    }
    
    .sm { padding: var(--spacing-xs) var(--spacing-sm); font-size: 14px; }
    .md { padding: var(--spacing-sm) var(--spacing-md); font-size: 16px; }
    .lg { padding: var(--spacing-md) var(--spacing-lg); font-size: 18px; }
    
    .button:disabled {
      opacity: 0.5;
      cursor: not-allowed;
    }
    

    Каждый компонент дизайн-системы использует токены через CSS-переменные. Если дизайнер изменит основной цвет бренда — достаточно обновить один токен, и все компоненты подхватят изменение.

    Как настроить Storybook для React компонентов

    Storybook позволяет разрабатывать и документировать компоненты UI kit изолированно от основного приложения. Установка:

    npx storybook@latest init
    

    После инициализации создаём stories для компонентов:

    // components/Button/Button.stories.tsx
    import type { Meta, StoryObj } from '@storybook/react';
    import { Button } from './Button';
    
    const meta: Meta<typeof Button> = {
      title: 'Components/Button',
      component: Button,
      argTypes: {
        variant: {
          control: 'select',
          options: ['primary', 'secondary', 'ghost'],
        },
        size: {
          control: 'select',
          options: ['sm', 'md', 'lg'],
        },
      },
    };
    
    export default meta;
    type Story = StoryObj<typeof Button>;
    
    // Основной вариант кнопки
    export const Primary: Story = {
      args: {
        children: 'Отправить',
        variant: 'primary',
        size: 'md',
      },
    };
    
    // Вторичный вариант
    export const Secondary: Story = {
      args: {
        children: 'Отмена',
        variant: 'secondary',
      },
    };
    
    // Состояние загрузки
    export const Loading: Story = {
      args: {
        children: 'Сохранение...',
        isLoading: true,
      },
    };
    

    Для документирования токенов используйте аддон storybook-design-token, который автоматически генерирует таблицы цветов, шрифтов и отступов из CSS-переменных:

    npm install storybook-design-token
    

    Частые ошибки при создании дизайн-системы

    Жёсткие значения вместо токенов. Если в компоненте написано color: #8b5cf6 вместо var(--color-brand), при смене темы этот компонент останется прежним. Все визуальные значения должны идти через токены.

    Слишком много вариантов у компонента. Кнопка с 15 пропсами сложнее в поддержке, чем три отдельных компонента. Начинайте с минимального API и расширяйте по мере реальных потребностей.

    Отсутствие документации. Компонент без Story в Storybook — это компонент, который никто не будет переиспользовать. Документируйте каждый компонент сразу при создании.

    Пропуск семантического уровня токенов. Если компоненты ссылаются напрямую на purple500, добавление тёмной темы потребует правок в каждом файле. Семантический слой (brandPrimary) решает эту проблему.

    Заключение

    Дизайн-система в React — это инвестиция, которая окупается с ростом проекта. Начните с определения дизайн-токенов на трёх уровнях (базовые, семантические, компонентные), создайте переиспользуемые компоненты с минимальным API и задокументируйте их в Storybook. Такой подход обеспечит консистентность интерфейса, ускорит разработку и упростит поддержку тем оформления.

    Иконка глаза9

    Комментарии

    0

    Постройте личный план изучения React state менеджер Zustand до уровня Middle — бесплатно!

    React state менеджер Zustand — часть карты развития Frontend

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Vue 3 и Pinia

    Антон Ларичев
    AI-тренажеры
    Практика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Next.js - с нуля

    Антон Ларичев
    AI-тренажеры
    Практика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.7
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    Feature-Sliced Design

    Антон Ларичев
    AI-тренажеры
    Практика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.5
    3 999 ₽ 6 990 ₽
    Подробнее
    Иконка чипа0