@donkit-ai/design-system
v1.4.51
Published
Donkit Design System - minimal design tokens and React components
Downloads
14,959
Readme
Donkit Design System
Минимальная дизайн система на основе дизайн токенов с поддержкой светлой и темной темы.
🚀 Установка
Установите пакет из npm:
npm install @donkit-ai/design-systemили
yarn add @donkit-ai/design-systemГотово! Дизайн-система установлена и готова к использованию.
Обновление до последней версии
npm update @donkit-ai/design-system
# или
npm install @donkit-ai/design-system@latestОсобенности
- 🎨 Дизайн токены - семантические CSS переменные для цветов, отступов, типографики
- 🌓 Две темы - автоматическое переключение между светлой и темной темой
- 📱 Адаптивность - responsive spacing и typography для mobile/tablet/desktop
- ⚛️ React компоненты - готовые к использованию компоненты
- 🎯 Lucide Icons - фиксированные размеры иконок (20/24/28px, stroke 1.5)
- 📖 Интерактивная документация - страница с примерами всех компонентов
Компоненты
- Button - кнопки с вариантами (primary, secondary, ghost) и размерами (xs, s, m, l). Поддерживает
hrefдля рендера как ссылка - Tabs - вкладки с состоянием selected в четырех размерах (xs, s, m, l). Поддерживает
hrefдля рендера как ссылка - Input - текстовые поля с поддержкой иконок, ошибок и подсказок (xs, s, m)
- Textarea - многострочное текстовое поле (xs, s, m)
- Select - выпадающий список с кастомным дизайном (xs, s, m)
- Stepper - числовое поле с кнопками +/- для изменения значения (xs, s, m)
- Toggle - переключатель для включения/выключения опций (xs, s, m, l)
- Checkbox - чекбокс для выбора опций (xs, s, m, l)
- Radio - радиокнопка для выбора одного варианта из группы (xs, s, m, l)
- Card - карточки двух типов: info (информационная, прозрачный фон) и interactive (интерактивная с hover эффектом). Поддерживает
hrefдля рендера как ссылка - Typography - H1-H4, P1-P3 компоненты
- Code - inline и block код с monospace шрифтом
- Link - ссылки акцентным цветом, при hover цвет меняется и появляется подчеркивание
- Badge - бейджи для статусов (success, error, warning, accent) в двух размерах (s, m)
- Modal - модальные окна с header и footer
- Select - выпадающий список с кастомным дизайном (s, m)
Использование в проекте
1. Импорт токенов (обязательно в корне приложения)
В главном файле вашего приложения (например, main.tsx или App.tsx):
// Подключите CSS токены ОДИН РАЗ в корне приложения
import '@donkit-ai/design-system/tokens.css';2. Использование компонентов
import { Button, Tabs, Tab, Input, Card, H1, P1, P3, Badge, Code, Link } from '@donkit-ai/design-system';
import { Mail } from 'lucide-react';
function MyComponent() {
return (
<Card padding="m">
<H1>Welcome</H1>
<P1 secondary>This is a demo</P1>
<Button
variant="primary"
size="m"
icon={<Mail size={24} strokeWidth={1.5} />}
>
Send Email
</Button>
</Card>
);
}
// Button как ссылка (рендерит <a> вместо <button>)
// При обычном клике: вызывается onClick (preventDefault автоматический)
// При Cmd/Ctrl+Click или Middle Click: открывается новая вкладка
<Button variant="primary" href="/dashboard" onClick={() => navigate('/dashboard')}>
Go to Dashboard
</Button>
<Button variant="secondary" href="https://example.com">
Visit Example
</Button>3. Иконки
Все иконки используются из библиотеки lucide-react (уже включена в зависимости).
Размеры иконок
Размеры иконок стандартизированы с помощью констант:
import { iconSizes } from '@donkit-ai/design-system';
// iconSizes = { 1: 16, 2: 20, 3: 24, 4: 28, 5: 48 }Соответствие размеров компонентам:
- 16px (
iconSizes[1]) — XS-кнопки, XS-табы - 20px (
iconSizes[2]) — S-кнопки, S-табы, Modal, Accordion - 24px (
iconSizes[3]) — M-кнопки (default), Input, Alert, Select - 28px (
iconSizes[4]) — L-кнопки, L-табы - 48px (
iconSizes[5]) — крупные декоративные иконки
Всегда используется strokeWidth={1.5} для единообразия дизайна.
Примеры использования
import { Mail, Search, Eye, EyeOff, AlertCircle, Check, X } from 'lucide-react';
import { iconSizes } from '@donkit-ai/design-system';
// Small button / Tabs / Modal
<Button size="s" icon={<Mail size={iconSizes[2]} strokeWidth={1.5} />}>
Send
</Button>
// Medium button / Input / Alert (default)
<Button size="m" icon={<Search size={iconSizes[3]} strokeWidth={1.5} />}>
Search
</Button>
<Input icon={<Search size={iconSizes[3]} strokeWidth={1.5} />} placeholder="Search..." />
// Large button
<Button size="l" icon={<Mail size={iconSizes[4]} strokeWidth={1.5} />}>
Send Email
</Button>
// Крупные декоративные
<Mail size={iconSizes[5]} strokeWidth={1.5} />3. Переключение темы
// Темная тема (по умолчанию)
document.documentElement.setAttribute('data-theme', 'dark');
// Светлая тема
document.documentElement.setAttribute('data-theme', 'light');Дизайн токены
Цвета
Примитивы (не использовать напрямую)
--color-white: #F8F9FA--color-black: #0E0F11--color-red: #EA6464
Поверхности — solid (меняются в зависимости от темы)
--color-surface-0— page background--color-surface-1— card, panel, sidebar--color-surface-2— input, nested element--color-surface-3— dropdown, tooltip, popover
Foreground
--color-fg-primary— основной текст и иконки--color-fg-secondary— вторичный текст--color-fg-disabled— disabled состояние
Interactive States
Прозрачные наложения. В компонентах реализованы через ::before псевдоэлемент с z-index: -1 + isolation: isolate на родителе — оверлей рисуется поверх базового фона, но под контентом (текст, иконки).
--color-state-hover— hover (dark: white/7%, light: black/5%)--color-state-active— pressed/active (dark: white/12%, light: black/10%)--color-state-selected— selected/checked (dark: white/10%, light: black/8%)
Borders
--color-border-default— стандартная граница--color-border-strong— hover/выделенная--color-border-focus— focus ring
Accent
--color-accent-default— акцентный цвет (#EA6464)--color-accent-hover— акцент при hover--color-accent-fg— текст/иконки на акцентном фоне--color-accent-bg— subtle акцентный фон (бейджи)
Status/Alert
--color-status-info/success/warning/error— адаптивные цвета для статусов--color-status-*-bg— фон для статусных бейджей и алертов
Elevation / Shadows
--shadow-1— dropdown, select, popover--shadow-2— modal, drawer--shadow-3— toast, критические оверлеи
Z-index Scale
--z-dropdown: 100--z-sticky: 200--z-drawer: 300--z-modal: 400--z-toast: 500--z-tooltip: 600
Отступы — 4px grid
--space-1: 4px--space-2: 8px--space-3: 12px--space-4: 16px--space-5: 20px--space-6: 24px--space-8: 32px--space-10: 40px--space-12: 48px--space-16: 64px
Border Radius
--radius-1: 2px--radius-2: 4px--radius-3: 6px — кнопки, inputs--radius-4: 8px — карточки, модалки--radius-6: 12px — drawer, панели--radius-8: 16px — крупные контейнеры--radius-full: 9999px — pill, аватары
Component Heights
| Токен | comfortable | compact | Size |
|----------------|-------------|---------|------|
| --height-1 | 24px | 20px | xs |
| --height-2 | 32px | 28px | s |
| --height-2-5 | 36px | 32px | sm |
| --height-3 | 44px | 36px | m |
| --height-4 | 56px | 44px | l |
Все компоненты с поддержкой size="sm": Button, Input, Tab, SegmentedControl.
Variant attributes
Три независимых атрибута — можно вешать на любой контейнер и комбинировать:
| Атрибут | Эффект | Токены |
|---------|--------|--------|
| data-corners="sharp" | Все скругления → 0 | --radius-1..8: 0 |
| data-typography="editorial" | Mono UI, uppercase, tracking | --font-ui, --ui-tracking, --ui-text-transform, --btn-*, --badge-* |
| data-density="airy" | Карточки всплывают при hover | --card-hover-transform: translateY(-3px) |
| data-variant="edgy" | Shorthand для всех трёх + тёмные поверхности, атмосферные тени | все выше + --color-surface-*, --shadow-*, --color-border-* |
Правила сочетания
data-variant="edgy"
= data-corners="sharp"
+ data-typography="editorial"
+ data-density="airy"
+ surface/border/shadow overrides (landing-specific)Атрибуты не зависят друг от друга и применяются к любому вложенному поддереву:
// Sharp corners без uppercase — product UI с landing-аккуратностью
<div data-corners="sharp">
<Button>Get started</Button>
<Card>...</Card>
</div>
// Editorial типографика без острых углов — editorial overlay
<div data-typography="editorial">
<Tabs>...</Tabs>
</div>
// Полный edgy — landing page
<div data-variant="edgy">
<Nav />
<Hero />
</div>Как это работает
data-corners="sharp" переопределяет CSS-токены --radius-*: 0 на уровне контейнера. Все компоненты внутри используют border-radius: var(--radius-N), поэтому скругления обнуляются каскадом — без component-level override'ов.
--radius-full (pill-формы: Toggle, Badge) намеренно не переопределяется.
Density mode
Глобальный компактный режим применяется на уровне контейнера через data-density:
<div data-density="compact">
{/* все компоненты внутри становятся компактнее */}
</div>Правила использования:
compactтолько на контейнерном уровне (страница, dashboard, side-panel) — не на отдельных компонентах- Не использовать на mobile — режим автоматически сбрасывается на viewport < 768px
- Минимальный hit-area в compact: 28px (
--height-2) — достаточно для desktop
Что меняется в compact:
| Токен | comfortable | compact |
|-------------|-------------|---------|
| --space-3 | 12px | 8px |
| --space-4 | 16px | 12px |
| --space-5 | 20px | 16px |
| --space-6 | 24px | 20px |
| --text-md | 14px | 13px |
| --text-sm | 12px | 11px |
Типографика (adaptive mobile → tablet+)
Font weights:
--font-weight-regular: 400--font-weight-medium: 500--font-weight-semibold: 600
Размеры:
--text-4xl: 32px → 40px (H1)--text-3xl: 28px → 36px (H2)--text-2xl: 24px → 28px (H3)--text-xl: 20px → 24px (H4)--text-lg: 16px → 18px (P1, основной текст)--text-md: 14px → 16px (P2)--text-sm: 12px → 14px (P3, метки)
Letter Spacing:
--tracking-4xl/3xl/2xl/xl: 0 (крупные кегли — без трекинга)--tracking-lg: 0.02em--tracking-md: 0.04em → 0.02em--tracking-sm: 0.06em → 0.04em
Переходы
--transition-fast: 0.15s ease--transition-normal: 0.20s ease--transition-slow: 0.30s ease
Disabled States (состояния недоступности)
Правила
- Button disabled — нейтральный стиль вместо opacity на акцентном цвете: прозрачный фон,
--color-fg-disabled, стандартная рамка - Input/Select/Textarea disabled — применяется к wrapper целиком (label + поле + hint/error)
- Курсор:
cursor: not-allowed - Hover эффекты: отключаются через
:hover:not(:disabled)
Примеры
<Button variant="primary" disabled>Disabled Button</Button>
<Input label="Name" value="Cannot edit" disabled />
<Select label="Choose" options={[...]} disabled />Структура проекта
/src
/styles
tokens.css # Дизайн токены
/components
Button.jsx/.css # Компонент кнопки
Tabs.jsx/.css # Компонент вкладок
Input.jsx/.css # Компонент input
Card.jsx/.css # Компонент карточки
Typography.jsx/.css # Типографика
Code.jsx/.css # Inline и block код
Link.jsx/.css # Ссылки
Badge.jsx/.css # Бейджи
Modal.jsx/.css # Модальное окно
Select.jsx/.css # Выпадающий список
/docs
App.jsx # Страница документации
main.jsx # Точка входа
docs.css # Стили документации
index.js # Экспорт всех компонентовПримеры использования
Кнопки
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
// Размеры с соответствующими иконками
<Button size="xs" icon={<Mail size={16} strokeWidth={1.5} />}>
Extra Small
</Button>
<Button size="s" icon={<Mail size={20} strokeWidth={1.5} />}>
Small
</Button>
<Button size="m" icon={<Mail size={24} strokeWidth={1.5} />}>
Medium
</Button>
<Button size="l" icon={<Mail size={28} strokeWidth={1.5} />}>
Large
</Button>
// С fullWidth
<Button
variant="primary"
size="m"
icon={<Mail size={24} strokeWidth={1.5} />}
fullWidth
>
Send Email
</Button>Tabs
Вкладки с минималистичным дизайном без border.
import { Tabs, Tab } from '@donkit-ai/design-system';
import { AlertCircle } from 'lucide-react';
// Basic tabs
<Tabs size="m">
<Tab selected={selectedTab === 'tab1'} onClick={() => setSelectedTab('tab1')}>
Overview
</Tab>
<Tab selected={selectedTab === 'tab2'} onClick={() => setSelectedTab('tab2')}>
Details
</Tab>
<Tab selected={selectedTab === 'tab3'} onClick={() => setSelectedTab('tab3')}>
Settings
</Tab>
</Tabs>
// With icons (размер иконки соответствует размеру таба)
// xs: 16px, small: 20px, medium: 24px, large: 28px
<Tabs size="s">
<Tab
selected={selectedTab === 'alerts'}
onClick={() => setSelectedTab('alerts')}
icon={<AlertCircle size={20} strokeWidth={1.5} />}
>
Alerts
</Tab>
<Tab selected={selectedTab === 'other'} onClick={() => setSelectedTab('other')}>
Other
</Tab>
</Tabs>
// Disabled tab
<Tabs size="m">
<Tab selected>Active</Tab>
<Tab disabled>Disabled</Tab>
</Tabs>
// As links (с href) - рендерит <a> вместо <button>
// При обычном клике: вызывается onClick (preventDefault автоматический)
// При Cmd/Ctrl+Click или Middle Click: открывается новая вкладка
<Tabs size="m">
<Tab selected href="/overview" onClick={() => navigate('/overview')}>
Overview
</Tab>
<Tab href="/details" onClick={() => navigate('/details')}>
Details
</Tab>
<Tab href="/settings" onClick={() => navigate('/settings')}>
Settings
</Tab>
</Tabs>Стили:
- Selected: фон
--color-item-bg-selected, текст--color-txt-icon-1 - Hover: фон
--color-item-bg-hover, текст--color-txt-icon-1 - Default: текст
--color-txt-icon-2
Размеры: xs, small, medium, large
Дополнительно: поддержка иконок и disabled состояния
Input
// Basic input
<Input
label="Email"
size="m"
type="email"
placeholder="[email protected]"
hint="We'll never share your email"
/>
// Left icon (informational) - size small
<Input
label="Search"
size="s"
icon={<Search size={20} strokeWidth={1.5} />}
placeholder="Search..."
/>
// Left icon - size medium
<Input
label="Search"
size="m"
icon={<Search size={24} strokeWidth={1.5} />}
placeholder="Search..."
/>
// Right icon (action with hover) - size medium
<Input
label="Password"
size="m"
type={showPassword ? 'text' : 'password'}
iconRight={showPassword ? <EyeOff size={24} strokeWidth={1.5} /> : <Eye size={24} strokeWidth={1.5} />}
onIconRightClick={() => setShowPassword(!showPassword)}
/>
// Error state
<Input
label="Name"
error="This field is required"
/>Работа с иконками:
- Иконки слева (
icon) - информационные, не интерактивные (email, phone, user, search) - Иконки справа (
iconRight) - действия с hover (показать/скрыть пароль, копировать) - Цвет: по умолчанию
--color-txt-icon-2, при hover--color-txt-icon-1 - Обработчик: используйте
onIconRightClickдля действий правой иконки
Select
<Select
label="Choose option"
size="m"
value={value}
onChange={setValue}
options={[
{ value: 'opt1', label: 'Option 1' },
{ value: 'opt2', label: 'Option 2' },
]}
placeholder="Select..."
/>Stepper
Числовое поле с кнопками увеличения и уменьшения значения.
// Basic stepper
<Stepper
label="Quantity"
size="m"
value={quantity}
onChange={setQuantity}
min={1}
max={10}
step={1}
/>
// Small size
<Stepper
label="Price"
size="s"
value={price}
onChange={setPrice}
min={0}
max={1000}
step={10}
hint="In increments of 10"
/>
// With error
<Stepper
label="Age"
value={age}
onChange={setAge}
min={0}
max={120}
error="Age is required"
/>
// Disabled
<Stepper
label="Fixed value"
value={50}
disabled
/>Параметры:
value- текущее значение (число)onChange- функция обработки изменения значенияmin- минимальное значение (default: 0)max- максимальное значение (default: 100)step- шаг изменения (default: 1)size- размер: "s" или "m" (default: "medium")label- подпись поляhint- подсказка под полемerror- текст ошибки (показывается вместо hint)disabled- отключить поле
Иконки в кнопках:
- Small: 16px (Minus, Plus)
- Medium: 20px (Minus, Plus)
Toggle
Переключатель для включения/выключения опций. Размеры привязаны к размерам иконок.
// Basic toggle
<Toggle
checked={isEnabled}
onChange={setIsEnabled}
label="Enable notifications"
/>
// Extra Small size (16px)
<Toggle
size="xs"
checked={isCompact}
onChange={setIsCompact}
label="Compact mode"
/>
// Small size (20px)
<Toggle
size="s"
checked={isEnabled}
onChange={setIsEnabled}
label="Auto-save"
/>
// Medium size (24px, default)
<Toggle
size="m"
checked={darkMode}
onChange={setDarkMode}
label="Dark mode"
/>
// Large size (28px)
<Toggle
size="l"
checked={isEnabled}
onChange={setIsEnabled}
label="Enable feature"
/>
// Without label (for tables/cards where context is clear)
<Toggle
checked={isEnabled}
onChange={setIsEnabled}
/>
// Disabled states
<Toggle
checked={false}
onChange={() => {}}
label="Disabled unchecked"
disabled
/>
<Toggle
checked={true}
onChange={() => {}}
label="Disabled checked"
disabled
/>Параметры:
checked- состояние переключателя (true/false)onChange- функция обработки изменения состояния, получает новое значение (boolean)size- размер: "xs", "small", "medium" или "large" (default: "medium")label- текст подписи (опционально)disabled- отключить переключательid- пользовательский ID (по умолчанию генерируется автоматически)
Стиль:
- Размеры привязаны к иконкам: xs (16px), small (20px), medium (24px), large (28px)
- Ширина трека: 1.75x от высоты
- Включенное состояние: фон
--color-status-success, border--color-status-success(зеленый) - Выключенное состояние: фон
--color-item-bg, border--color-border, hover--color-border-hover
Checkbox
Чекбокс для выбора опций. Размеры привязаны к размерам иконок.
// Basic checkbox
<Checkbox
checked={isAccepted}
onChange={setIsAccepted}
label="Accept terms and conditions"
/>
// Extra Small size (16px)
<Checkbox
size="xs"
checked={isCompact}
onChange={setIsCompact}
label="Compact view"
/>
// Small size (20px)
<Checkbox
size="s"
checked={isEnabled}
onChange={setIsEnabled}
label="Enable feature"
/>
// Medium size (24px, default)
<Checkbox
size="m"
checked={isSubscribed}
onChange={setIsSubscribed}
label="Subscribe to newsletter"
/>
// Large size (28px)
<Checkbox
size="l"
checked={isAccepted}
onChange={setIsAccepted}
label="I accept the terms"
/>
// Without label (for tables/lists where context is clear)
<Checkbox
checked={isSelected}
onChange={setIsSelected}
/>
// Disabled states
<Checkbox
checked={false}
onChange={() => {}}
label="Disabled unchecked"
disabled
/>
<Checkbox
checked={true}
onChange={() => {}}
label="Disabled checked"
disabled
/>Параметры:
checked- состояние чекбокса (true/false)onChange- функция обработки изменения состояния, получает новое значение (boolean)size- размер: "xs", "small", "medium" или "large" (default: "medium")label- текст подписи (опционально)disabled- отключить чекбоксid- пользовательский ID (по умолчанию генерируется автоматически)
Стиль:
- Размеры привязаны к иконкам: xs (16px), small (20px), medium (24px), large (28px)
- Выбранное состояние: фон
--color-status-success, border--color-status-success(зеленый) - Невыбранное состояние: фон
--color-item-bg, border--color-border, hover--color-border-hover - Иконка галочки (Check) белого цвета при checked
Radio
Радиокнопка для выбора одного варианта из группы. Размеры привязаны к размерам иконок.
// Basic radio
<Radio
checked={selectedOption === 'option1'}
onChange={() => setSelectedOption('option1')}
name="options"
value="option1"
label="Option 1"
/>
// Extra Small size (16px)
<Radio
size="xs"
checked={size === 'xs'}
onChange={() => setSize('xs')}
name="size"
value="xs"
label="Extra Small"
/>
// Small size (20px)
<Radio
size="s"
checked={size === 'small'}
onChange={() => setSize('small')}
name="size"
value="small"
label="Small"
/>
// Medium size (24px, default)
<Radio
size="m"
checked={size === 'medium'}
onChange={() => setSize('medium')}
name="size"
value="medium"
label="Medium"
/>
// Large size (28px)
<Radio
size="l"
checked={size === 'large'}
onChange={() => setSize('large')}
name="size"
value="large"
label="Large"
/>
// Radio group example
<div>
<Radio
checked={paymentMethod === 'card'}
onChange={() => setPaymentMethod('card')}
name="payment"
value="card"
label="Credit Card"
/>
<Radio
checked={paymentMethod === 'paypal'}
onChange={() => setPaymentMethod('paypal')}
name="payment"
value="paypal"
label="PayPal"
/>
<Radio
checked={paymentMethod === 'bank'}
onChange={() => setPaymentMethod('bank')}
name="payment"
value="bank"
label="Bank Transfer"
/>
</div>
// Without label (for tables/lists where context is clear)
<Radio
checked={isSelected}
onChange={() => setIsSelected(true)}
name="selection"
value="item1"
/>
// Disabled states
<Radio
checked={false}
onChange={() => {}}
name="disabled-group"
value="disabled1"
label="Disabled unchecked"
disabled
/>
<Radio
checked={true}
onChange={() => {}}
name="disabled-group"
value="disabled2"
label="Disabled checked"
disabled
/>Параметры:
checked- состояние радиокнопки (true/false)onChange- функция обработки изменения состояния, получает новое значение (boolean)name- имя группы радиокнопок (обязательно для группировки)value- значение радиокнопкиsize- размер: "xs", "small", "medium" или "large" (default: "medium")label- текст подписи (опционально)disabled- отключить радиокнопкуid- пользовательский ID (по умолчанию генерируется автоматически)
Стиль:
- Размеры привязаны к иконкам: xs (16px), small (20px), medium (24px), large (28px)
- Выбранное состояние: фон
--color-status-success, border--color-status-success(зеленый), белая точка внутри - Невыбранное состояние: фон
--color-item-bg, border--color-border, hover--color-border-hover - Круглая форма (border-radius: 50%)
Card
Карточки бывают двух типов:
// Card Info (по умолчанию)
// Информационная карточка без интерактивности
// Прозрачный фон, только border
<Card padding="m" variant="info">
<H4>Card Title</H4>
<P1>Information content</P1>
</Card>
// Card Interactive
// Интерактивная карточка с hover эффектом
// При hover меняется фон и border
<Card padding="l" variant="interactive" onClick={handleClick}>
<H4>Clickable Card</H4>
<P1>Interactive content</P1>
</Card>
// Размеры padding
<Card padding="s">s padding</Card>
<Card padding="m">m padding</Card>
<Card padding="l">l padding</Card>
// Card как ссылка (рендерит <a> вместо <div>)
// При обычном клике: вызывается onClick (preventDefault автоматический)
// При Cmd/Ctrl+Click или Middle Click: открывается новая вкладка
<Card
padding="m"
variant="interactive"
href="/dashboard"
onClick={() => navigate('/dashboard')}
>
<H4>Dashboard</H4>
<P1>Go to dashboard page</P1>
</Card>
<Card
padding="m"
variant="interactive"
href="https://example.com"
>
<H4>External Link</H4>
<P1>Visit external site</P1>
</Card>
// Disabled Card Link
<Card
padding="m"
variant="interactive"
href="/disabled"
disabled
>
<H4>Disabled</H4>
<P1>This card is disabled</P1>
</Card>Стиль:
- variant="info" (по умолчанию): прозрачный фон, border
--color-border - variant="interactive": фон
--color-item-bg, при hover фон--color-item-bg-hover, курсор pointer - Поддержка
hrefдля рендера как ссылка с умной обработкой кликов
Code
// Inline code
<p>Use <Code>--color-accent</Code> variable</p>
// Code block
<Code block>{`function example() {
return "Hello World";
}`}</Code>Link
Ссылки акцентным цветом, подчеркивание появляется при hover.
Стиль:
- Цвет:
--color-accent - Без подчеркивания по умолчанию
- При hover: цвет меняется на
--color-accent-hover+ появляется подчеркивание - При active: цвет
--color-accent-hover
Badge
Бейджи для отображения статусов и категорий в двух размерах.
// Medium size (default)
<Badge variant="success" size="m">Success</Badge>
<Badge variant="error" size="m">Error</Badge>
<Badge variant="warning" size="m">Warning</Badge>
<Badge variant="info" size="m">Info</Badge>
// Small size
<Badge variant="success" size="s">Success</Badge>
<Badge variant="error" size="s">Error</Badge>
<Badge variant="warning" size="s">Warning</Badge>
// Variants
<Badge variant="default">Default</Badge>
<Badge variant="accent">Accent</Badge>Размеры:
small- компактный размер (font-size: p3, padding: 0 4px, radius: xs)medium- стандартный размер (font-size: p2, padding: 2px 8px, radius: s)
Варианты:
default- серый с borderinfo- синий (информация)success- зелёный (успех)warning- жёлтый (предупреждение)error- красный (ошибка)accent- красный акцентный
Цвета адаптируются для светлой и тёмной темы для обеспечения контраста минимум 4.5:1.
Modal
<Modal
title="Modal Title"
onClose={handleClose}
size="m"
>
<P1>Modal content here...</P1>
<Input label="Name" placeholder="Enter name" />
<ModalFooter>
<Button variant="secondary" size="m" onClick={handleClose}>
Cancel
</Button>
<Button variant="primary" size="m">
Submit
</Button>
</ModalFooter>
</Modal>
{/* Modal использует иконку закрытия 20px (автоматически) */}🛠 Для мейнтейнеров дизайн-системы
Публикация в npm
Внесите изменения в компоненты или токены
Обновите версию в
package.json:
npm version patch # 0.2.3 → 0.2.4 (багфиксы)
npm version minor # 0.2.3 → 0.3.0 (новые фичи)
npm version major # 0.2.3 → 1.0.0 (breaking changes)- Создайте тег и запушьте:
git push --follow-tagsГотово! GitLab CI автоматически опубликует новую версию в публичный npm registry.
Команда получит обновления
npm update @donkit-ai/design-system
# или
npm install @donkit-ai/design-system@latestЛокальная разработка
Для тестирования изменений локально используйте npm link:
# В папке Donkit-desing-tokens
npm link
# В папке вашего проекта (agent-platform/frontend)
npm link @donkit-ai/design-systemТеперь изменения в дизайн-системе сразу видны в вашем проекте без переустановки.
Структура версионирования
- Главная ветка:
main- стабильная версия - Теги:
v0.1.0,v0.1.2- релизные версии - Фичи: создавайте ветки для больших изменений, мерджите в
mainпосле ревью
Adding a theme
Donkit DS ships dark (default, always in :root) plus light and high-contrast in src/styles/themes/. To add your own:
7 шагов
Скопировать шаблон
cp src/styles/themes/_template.css src/styles/themes/my-theme.cssПереименовать атрибут — заменить
my-themeна kebab-case название в selector[data-theme="my-theme"]Заполнить REQUIRED-токены — 14 обязательных переменных (surface, fg, border, state-overlay, overlay). Без них тема не будет работать: | Группа | Токены | |--------|--------| | Surface |
--color-surface-0..3| | Foreground |--color-fg-primary/secondary/disabled| | Border |--color-border-light/default/strong/focus| | State overlay |--color-state-hover/active/selected| | Backdrop |--color-overlay|Оставить OPTIONAL — shadow, accent, status, data-palette, focus-ring. Не переопределяешь — наследуется от тёмной базы в
:root.Импортировать в проект после
tokens.css:import '@donkit-ai/design-system/src/styles/tokens.css'; import '@donkit-ai/design-system/src/styles/themes/my-theme.css';Или через CSS:
@import '@donkit-ai/design-system/src/styles/tokens.css'; @import '@donkit-ai/design-system/src/styles/themes/my-theme.css';Добавить в preview — скопировать колонку в
preview/themes.html, вставитьdata-theme="my-theme"на.surface.Прогнать a11y-чеклист:
- [ ] Контраст текста ≥ 4.5:1 (AA), лучше ≥ 7:1 (AAA)
- [ ] UI-элементы (бордеры, иконки) ≥ 3:1
- [ ] Focus ring чётко виден на всех поверхностях
- [ ] Hover overlay различим, но не агрессивен
- [ ] Selected отличается от hover визуально
- [ ] Overlay/backdrop не слишком плотный и не прозрачный
Архитектурный контракт
:root ← dark (всегда загружен, база для наследования)
[data-theme="light"] ← src/styles/themes/light.css
[data-theme="high-contrast"] ← src/styles/themes/high-contrast.css
[data-theme="my-theme"] ← твой файл
[data-variant="edgy"] ← structural, не тема — живёт в tokens.css
[data-density="compact"] ← density mode — живёт в tokens.cssТемы загружаются unlayered → всегда побеждают @layer base из tokens.css.
Token resilience
Все структурные токены в компонентах имеют встроенный фолбэк-значение:
/* вместо */
height: var(--height-3);
/* теперь */
height: var(--height-3, 44px);Это гарантирует корректный рендер даже если tokens.css не подключён или загружается с задержкой.
Категории токенов
| Категория | Примеры | Фолбэк |
|-----------|---------|--------|
| Radius | --radius-1..8, --radius-full | 2px..9999px |
| Space | --space-1..16 | 4px..64px |
| Height | --height-1..4, --height-2-5 | 24px..56px |
| Motion | --motion-enter/exit/hover | 0.3s ease, 0.2s ease |
| Typography | --text-sm..4xl, --font-weight-* | 12px..32px, 400/500/600 |
| Component | --btn-*, --tab-*, --badge-radius | см. tokens.css |
Что НЕ имеет фолбэка
Цветовые (--color-*) и тень (--shadow-*) токены — намеренно без фолбэка. Отсутствующий цвет должно быть видно сразу, а не скрыто дефолтом.
Лицензия
MIT
