@donkit-ai/design-system 1.4.76 → 1.4.79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -1190
- package/dist/high-contrast.css +1 -1
- package/dist/index.cjs.js +2 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.es.js +416 -414
- package/dist/light.css +8 -1
- package/dist/tokens.css +1 -1
- package/package.json +1 -14
package/README.md
CHANGED
|
@@ -1,1204 +1,24 @@
|
|
|
1
1
|
# Donkit Design System
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Minimal design tokens and React components for Donkit products.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
Установите пакет из npm:
|
|
5
|
+
## Install
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
8
|
npm install @donkit-ai/design-system
|
|
11
9
|
```
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
yarn add @donkit-ai/design-system
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
**Готово!** Дизайн-система установлена и готова к использованию.
|
|
20
|
-
|
|
21
|
-
### Обновление до последней версии
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npm update @donkit-ai/design-system
|
|
25
|
-
# или
|
|
26
|
-
npm install @donkit-ai/design-system@latest
|
|
27
|
-
```
|
|
11
|
+
## Usage
|
|
28
12
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- 🎨 **Дизайн токены** - семантические CSS переменные для цветов, отступов, типографики
|
|
32
|
-
- 🌓 **Две темы** - автоматическое переключение между светлой и темной темой
|
|
33
|
-
- 📱 **Адаптивность** - responsive spacing и typography для mobile/tablet/desktop
|
|
34
|
-
- ⚛️ **React компоненты** - готовые к использованию компоненты
|
|
35
|
-
- 🎯 **Lucide Icons** - фиксированные размеры иконок (20/24/28px, stroke 1.5)
|
|
36
|
-
- 📖 **Интерактивная документация** - страница с примерами всех компонентов
|
|
37
|
-
|
|
38
|
-
## Компоненты
|
|
39
|
-
|
|
40
|
-
- **Button** - кнопки с вариантами (primary, secondary, ghost) и размерами (xs, s, m, l). Поддерживает `href` для рендера как ссылка
|
|
41
|
-
- **Tabs** - вкладки с состоянием selected в четырех размерах (xs, s, m, l). Поддерживает `href` для рендера как ссылка
|
|
42
|
-
- **Input** - текстовые поля с поддержкой иконок, ошибок и подсказок (xs, s, m)
|
|
43
|
-
- **Textarea** - многострочное текстовое поле (xs, s, m)
|
|
44
|
-
- **Select** - выпадающий список с кастомным дизайном (xs, s, m)
|
|
45
|
-
- **Stepper** - числовое поле с кнопками +/- для изменения значения (xs, s, m)
|
|
46
|
-
- **Toggle** - переключатель для включения/выключения опций (xs, s, m, l)
|
|
47
|
-
- **Checkbox** - чекбокс для выбора опций (xs, s, m, l)
|
|
48
|
-
- **Radio** - радиокнопка для выбора одного варианта из группы (xs, s, m, l)
|
|
49
|
-
- **Card** - карточки двух типов: info (информационная, прозрачный фон) и interactive (интерактивная с hover эффектом). Поддерживает `href` для рендера как ссылка
|
|
50
|
-
- **Typography** - H1-H4, P1-P3 компоненты
|
|
51
|
-
- **Code** - inline и block код с monospace шрифтом
|
|
52
|
-
- **Link** - ссылки акцентным цветом, при hover цвет меняется и появляется подчеркивание
|
|
53
|
-
- **Badge** - бейджи для статусов (success, error, warning, accent) в двух размерах (s, m)
|
|
54
|
-
- **Modal** - модальные окна с header и footer
|
|
55
|
-
- **Select** - выпадающий список с кастомным дизайном (s, m)
|
|
56
|
-
|
|
57
|
-
## Использование в проекте
|
|
58
|
-
|
|
59
|
-
### 1. Импорт токенов (обязательно в корне приложения)
|
|
60
|
-
|
|
61
|
-
В главном файле вашего приложения (например, `main.tsx` или `App.tsx`):
|
|
62
|
-
|
|
63
|
-
```javascript
|
|
64
|
-
// Подключите CSS токены ОДИН РАЗ в корне приложения
|
|
13
|
+
```js
|
|
65
14
|
import '@donkit-ai/design-system/tokens.css';
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```javascript
|
|
71
|
-
import { Button, Tabs, Tab, Input, Card, H1, P1, P3, Badge, Code, Link } from '@donkit-ai/design-system';
|
|
72
|
-
import { Mail } from 'lucide-react';
|
|
73
|
-
|
|
74
|
-
function MyComponent() {
|
|
75
|
-
return (
|
|
76
|
-
<Card padding="m">
|
|
77
|
-
<H1>Welcome</H1>
|
|
78
|
-
<P1 secondary>This is a demo</P1>
|
|
79
|
-
<Button
|
|
80
|
-
variant="primary"
|
|
81
|
-
size="m"
|
|
82
|
-
icon={<Mail size={24} strokeWidth={1.5} />}
|
|
83
|
-
>
|
|
84
|
-
Send Email
|
|
85
|
-
</Button>
|
|
86
|
-
</Card>
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Button как ссылка (рендерит <a> вместо <button>)
|
|
91
|
-
// При обычном клике: вызывается onClick (preventDefault автоматический)
|
|
92
|
-
// При Cmd/Ctrl+Click или Middle Click: открывается новая вкладка
|
|
93
|
-
<Button variant="primary" href="/dashboard" onClick={() => navigate('/dashboard')}>
|
|
94
|
-
Go to Dashboard
|
|
95
|
-
</Button>
|
|
96
|
-
|
|
97
|
-
<Button variant="secondary" href="https://example.com">
|
|
98
|
-
Visit Example
|
|
99
|
-
</Button>
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### 3. Иконки
|
|
103
|
-
|
|
104
|
-
Все иконки используются из библиотеки `lucide-react` (уже включена в зависимости).
|
|
105
|
-
|
|
106
|
-
#### Размеры иконок
|
|
107
|
-
|
|
108
|
-
Размеры иконок стандартизированы с помощью констант:
|
|
109
|
-
|
|
110
|
-
```javascript
|
|
111
|
-
import { iconSizes } from '@donkit-ai/design-system';
|
|
112
|
-
|
|
113
|
-
// iconSizes = { 1: 16, 2: 20, 3: 24, 4: 28, 5: 48 }
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
**Соответствие размеров компонентам:**
|
|
117
|
-
|
|
118
|
-
- **16px (`iconSizes[1]`)** — XS-кнопки, XS-табы
|
|
119
|
-
- **20px (`iconSizes[2]`)** — S-кнопки, S-табы, Modal, Accordion
|
|
120
|
-
- **24px (`iconSizes[3]`)** — M-кнопки (default), Input, Alert, Select
|
|
121
|
-
- **28px (`iconSizes[4]`)** — L-кнопки, L-табы
|
|
122
|
-
- **48px (`iconSizes[5]`)** — крупные декоративные иконки
|
|
123
|
-
|
|
124
|
-
**Всегда используется `strokeWidth={1.5}`** для единообразия дизайна.
|
|
125
|
-
|
|
126
|
-
#### Примеры использования
|
|
127
|
-
|
|
128
|
-
```javascript
|
|
129
|
-
import { Mail, Search, Eye, EyeOff, AlertCircle, Check, X } from 'lucide-react';
|
|
130
|
-
import { iconSizes } from '@donkit-ai/design-system';
|
|
131
|
-
|
|
132
|
-
// Small button / Tabs / Modal
|
|
133
|
-
<Button size="s" icon={<Mail size={iconSizes[2]} strokeWidth={1.5} />}>
|
|
134
|
-
Send
|
|
135
|
-
</Button>
|
|
136
|
-
|
|
137
|
-
// Medium button / Input / Alert (default)
|
|
138
|
-
<Button size="m" icon={<Search size={iconSizes[3]} strokeWidth={1.5} />}>
|
|
139
|
-
Search
|
|
140
|
-
</Button>
|
|
141
|
-
<Input icon={<Search size={iconSizes[3]} strokeWidth={1.5} />} placeholder="Search..." />
|
|
142
|
-
|
|
143
|
-
// Large button
|
|
144
|
-
<Button size="l" icon={<Mail size={iconSizes[4]} strokeWidth={1.5} />}>
|
|
145
|
-
Send Email
|
|
146
|
-
</Button>
|
|
147
|
-
|
|
148
|
-
// Крупные декоративные
|
|
149
|
-
<Mail size={iconSizes[5]} strokeWidth={1.5} />
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### 3. Переключение темы
|
|
153
|
-
|
|
154
|
-
```javascript
|
|
155
|
-
// Темная тема (по умолчанию)
|
|
156
|
-
document.documentElement.setAttribute('data-theme', 'dark');
|
|
157
|
-
|
|
158
|
-
// Светлая тема
|
|
159
|
-
document.documentElement.setAttribute('data-theme', 'light');
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
## Дизайн токены
|
|
163
|
-
|
|
164
|
-
### Цвета
|
|
165
|
-
|
|
166
|
-
#### Примитивы (не использовать напрямую)
|
|
167
|
-
- `--color-white`: #F8F9FA
|
|
168
|
-
- `--color-black`: #0E0F11
|
|
169
|
-
- `--color-red`: #EA6464
|
|
170
|
-
|
|
171
|
-
#### Поверхности — solid (меняются в зависимости от темы)
|
|
172
|
-
- `--color-surface-0` — page background
|
|
173
|
-
- `--color-surface-1` — card, panel, sidebar
|
|
174
|
-
- `--color-surface-2` — input, nested element
|
|
175
|
-
- `--color-surface-3` — dropdown, tooltip, popover
|
|
176
|
-
|
|
177
|
-
#### Foreground
|
|
178
|
-
- `--color-fg-primary` — основной текст и иконки
|
|
179
|
-
- `--color-fg-secondary` — вторичный текст
|
|
180
|
-
- `--color-fg-disabled` — disabled состояние
|
|
181
|
-
|
|
182
|
-
#### Interactive States
|
|
183
|
-
Прозрачные наложения. В компонентах реализованы через `::before` псевдоэлемент с `z-index: -1` + `isolation: isolate` на родителе — оверлей рисуется поверх базового фона, но под контентом (текст, иконки).
|
|
184
|
-
- `--color-state-hover` — hover (dark: white/7%, light: black/5%)
|
|
185
|
-
- `--color-state-active` — pressed/active (dark: white/12%, light: black/10%)
|
|
186
|
-
- `--color-state-selected` — selected/checked (dark: white/10%, light: black/8%)
|
|
187
|
-
|
|
188
|
-
#### Borders
|
|
189
|
-
- `--color-border-default` — стандартная граница
|
|
190
|
-
- `--color-border-strong` — hover/выделенная
|
|
191
|
-
- `--color-border-focus` — focus ring
|
|
192
|
-
|
|
193
|
-
#### Accent
|
|
194
|
-
- `--color-accent-default` — акцентный цвет (#EA6464)
|
|
195
|
-
- `--color-accent-hover` — акцент при hover
|
|
196
|
-
- `--color-accent-fg` — текст/иконки на акцентном фоне
|
|
197
|
-
- `--color-accent-bg` — subtle акцентный фон (бейджи)
|
|
198
|
-
|
|
199
|
-
#### Status/Alert
|
|
200
|
-
- `--color-status-info/success/warning/error` — адаптивные цвета для статусов
|
|
201
|
-
- `--color-status-*-bg` — фон для статусных бейджей и алертов
|
|
202
|
-
|
|
203
|
-
### Elevation / Shadows
|
|
204
|
-
|
|
205
|
-
- `--shadow-1` — dropdown, select, popover
|
|
206
|
-
- `--shadow-2` — modal, drawer
|
|
207
|
-
- `--shadow-3` — toast, критические оверлеи
|
|
208
|
-
|
|
209
|
-
### Z-index Scale
|
|
210
|
-
|
|
211
|
-
- `--z-dropdown`: 100
|
|
212
|
-
- `--z-sticky`: 200
|
|
213
|
-
- `--z-drawer`: 300
|
|
214
|
-
- `--z-modal`: 400
|
|
215
|
-
- `--z-toast`: 500
|
|
216
|
-
- `--z-tooltip`: 600
|
|
217
|
-
|
|
218
|
-
### Отступы — 4px grid
|
|
219
|
-
|
|
220
|
-
- `--space-1`: 4px
|
|
221
|
-
- `--space-2`: 8px
|
|
222
|
-
- `--space-3`: 12px
|
|
223
|
-
- `--space-4`: 16px
|
|
224
|
-
- `--space-5`: 20px
|
|
225
|
-
- `--space-6`: 24px
|
|
226
|
-
- `--space-8`: 32px
|
|
227
|
-
- `--space-10`: 40px
|
|
228
|
-
- `--space-12`: 48px
|
|
229
|
-
- `--space-16`: 64px
|
|
230
|
-
|
|
231
|
-
### Border Radius
|
|
232
|
-
|
|
233
|
-
- `--radius-1`: 2px
|
|
234
|
-
- `--radius-2`: 4px
|
|
235
|
-
- `--radius-3`: 6px — кнопки, inputs
|
|
236
|
-
- `--radius-4`: 8px — карточки, модалки
|
|
237
|
-
- `--radius-6`: 12px — drawer, панели
|
|
238
|
-
- `--radius-8`: 16px — крупные контейнеры
|
|
239
|
-
- `--radius-full`: 9999px — pill, аватары
|
|
240
|
-
|
|
241
|
-
### Component Heights
|
|
242
|
-
|
|
243
|
-
| Токен | comfortable | compact | Size |
|
|
244
|
-
|----------------|-------------|---------|------|
|
|
245
|
-
| `--height-1` | 24px | 20px | xs |
|
|
246
|
-
| `--height-2` | 32px | 28px | s |
|
|
247
|
-
| `--height-2-5` | 36px | 32px | sm |
|
|
248
|
-
| `--height-3` | 44px | 36px | m |
|
|
249
|
-
| `--height-4` | 56px | 44px | l |
|
|
250
|
-
|
|
251
|
-
Все компоненты с поддержкой `size="sm"`: `Button`, `Input`, `Tab`, `SegmentedControl`.
|
|
252
|
-
|
|
253
|
-
## Variant attributes
|
|
254
|
-
|
|
255
|
-
Три независимых атрибута — можно вешать на любой контейнер и комбинировать:
|
|
256
|
-
|
|
257
|
-
| Атрибут | Эффект | Токены |
|
|
258
|
-
|---------|--------|--------|
|
|
259
|
-
| `data-corners="sharp"` | Все скругления → 0 | `--radius-1..8: 0` |
|
|
260
|
-
| `data-typography="editorial"` | Mono UI, uppercase, tracking | `--font-ui`, `--ui-tracking`, `--ui-text-transform`, `--btn-*`, `--badge-*` |
|
|
261
|
-
| `data-density="airy"` | Карточки всплывают при hover | `--card-hover-transform: translateY(-3px)` |
|
|
262
|
-
| `data-variant="edgy"` | Shorthand для всех трёх + тёмные поверхности, атмосферные тени | все выше + `--color-surface-*`, `--shadow-*`, `--color-border-*` |
|
|
263
|
-
|
|
264
|
-
### Правила сочетания
|
|
265
|
-
|
|
266
|
-
```
|
|
267
|
-
data-variant="edgy"
|
|
268
|
-
= data-corners="sharp"
|
|
269
|
-
+ data-typography="editorial"
|
|
270
|
-
+ data-density="airy"
|
|
271
|
-
+ surface/border/shadow overrides (landing-specific)
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
Атрибуты **не зависят друг от друга** и применяются к любому вложенному поддереву:
|
|
275
|
-
|
|
276
|
-
```jsx
|
|
277
|
-
// Sharp corners без uppercase — product UI с landing-аккуратностью
|
|
278
|
-
<div data-corners="sharp">
|
|
279
|
-
<Button>Get started</Button>
|
|
280
|
-
<Card>...</Card>
|
|
281
|
-
</div>
|
|
282
|
-
|
|
283
|
-
// Editorial типографика без острых углов — editorial overlay
|
|
284
|
-
<div data-typography="editorial">
|
|
285
|
-
<Tabs>...</Tabs>
|
|
286
|
-
</div>
|
|
287
|
-
|
|
288
|
-
// Полный edgy — landing page
|
|
289
|
-
<div data-variant="edgy">
|
|
290
|
-
<Nav />
|
|
291
|
-
<Hero />
|
|
292
|
-
</div>
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
### Как это работает
|
|
296
|
-
|
|
297
|
-
`data-corners="sharp"` переопределяет CSS-токены `--radius-*: 0` на уровне контейнера. Все компоненты внутри используют `border-radius: var(--radius-N)`, поэтому скругления обнуляются каскадом — без component-level override'ов.
|
|
298
|
-
|
|
299
|
-
`--radius-full` (pill-формы: Toggle, Badge) намеренно **не переопределяется**.
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
|
-
## Density mode
|
|
304
|
-
|
|
305
|
-
Глобальный компактный режим применяется на уровне контейнера через `data-density`:
|
|
306
|
-
|
|
307
|
-
```jsx
|
|
308
|
-
<div data-density="compact">
|
|
309
|
-
{/* все компоненты внутри становятся компактнее */}
|
|
310
|
-
</div>
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
**Правила использования:**
|
|
314
|
-
- `compact` только на **контейнерном уровне** (страница, dashboard, side-panel) — не на отдельных компонентах
|
|
315
|
-
- **Не использовать на mobile** — режим автоматически сбрасывается на viewport < 768px
|
|
316
|
-
- Минимальный hit-area в compact: 28px (`--height-2`) — достаточно для desktop
|
|
317
|
-
|
|
318
|
-
**Что меняется в compact:**
|
|
319
|
-
|
|
320
|
-
| Токен | comfortable | compact |
|
|
321
|
-
|-------------|-------------|---------|
|
|
322
|
-
| `--space-3` | 12px | 8px |
|
|
323
|
-
| `--space-4` | 16px | 12px |
|
|
324
|
-
| `--space-5` | 20px | 16px |
|
|
325
|
-
| `--space-6` | 24px | 20px |
|
|
326
|
-
| `--text-md` | 14px | 13px |
|
|
327
|
-
| `--text-sm` | 12px | 11px |
|
|
328
|
-
|
|
329
|
-
### Типографика (adaptive mobile → tablet+)
|
|
330
|
-
|
|
331
|
-
**Font weights:**
|
|
332
|
-
- `--font-weight-regular`: 400
|
|
333
|
-
- `--font-weight-medium`: 500
|
|
334
|
-
- `--font-weight-semibold`: 600
|
|
335
|
-
|
|
336
|
-
**Размеры:**
|
|
337
|
-
- `--text-4xl`: 32px → 40px (H1)
|
|
338
|
-
- `--text-3xl`: 28px → 36px (H2)
|
|
339
|
-
- `--text-2xl`: 24px → 28px (H3)
|
|
340
|
-
- `--text-xl`: 20px → 24px (H4)
|
|
341
|
-
- `--text-lg`: 16px → 18px (P1, основной текст)
|
|
342
|
-
- `--text-md`: 14px → 16px (P2)
|
|
343
|
-
- `--text-sm`: 12px → 14px (P3, метки)
|
|
344
|
-
|
|
345
|
-
**Letter Spacing:**
|
|
346
|
-
- `--tracking-4xl/3xl/2xl/xl`: 0 (крупные кегли — без трекинга)
|
|
347
|
-
- `--tracking-lg`: 0.02em
|
|
348
|
-
- `--tracking-md`: 0.04em → 0.02em
|
|
349
|
-
- `--tracking-sm`: 0.06em → 0.04em
|
|
350
|
-
|
|
351
|
-
### Переходы
|
|
352
|
-
|
|
353
|
-
- `--transition-fast`: 0.15s ease
|
|
354
|
-
- `--transition-normal`: 0.20s ease
|
|
355
|
-
- `--transition-slow`: 0.30s ease
|
|
356
|
-
|
|
357
|
-
## Disabled States (состояния недоступности)
|
|
358
|
-
|
|
359
|
-
### Правила
|
|
360
|
-
|
|
361
|
-
- **Button disabled** — нейтральный стиль вместо opacity на акцентном цвете: прозрачный фон, `--color-fg-disabled`, стандартная рамка
|
|
362
|
-
- **Input/Select/Textarea disabled** — применяется к wrapper целиком (label + поле + hint/error)
|
|
363
|
-
- **Курсор**: `cursor: not-allowed`
|
|
364
|
-
- **Hover эффекты**: отключаются через `:hover:not(:disabled)`
|
|
365
|
-
|
|
366
|
-
### Примеры
|
|
367
|
-
|
|
368
|
-
```jsx
|
|
369
|
-
<Button variant="primary" disabled>Disabled Button</Button>
|
|
370
|
-
<Input label="Name" value="Cannot edit" disabled />
|
|
371
|
-
<Select label="Choose" options={[...]} disabled />
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
## Структура проекта
|
|
375
|
-
|
|
376
|
-
```
|
|
377
|
-
/src
|
|
378
|
-
/styles
|
|
379
|
-
tokens.css # Дизайн токены
|
|
380
|
-
/components
|
|
381
|
-
Button.jsx/.css # Компонент кнопки
|
|
382
|
-
Tabs.jsx/.css # Компонент вкладок
|
|
383
|
-
Input.jsx/.css # Компонент input
|
|
384
|
-
Card.jsx/.css # Компонент карточки
|
|
385
|
-
Typography.jsx/.css # Типографика
|
|
386
|
-
Code.jsx/.css # Inline и block код
|
|
387
|
-
Link.jsx/.css # Ссылки
|
|
388
|
-
Badge.jsx/.css # Бейджи
|
|
389
|
-
Modal.jsx/.css # Модальное окно
|
|
390
|
-
Select.jsx/.css # Выпадающий список
|
|
391
|
-
/docs
|
|
392
|
-
App.jsx # Страница документации
|
|
393
|
-
main.jsx # Точка входа
|
|
394
|
-
docs.css # Стили документации
|
|
395
|
-
index.js # Экспорт всех компонентов
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
## Примеры использования
|
|
399
|
-
|
|
400
|
-
### Кнопки
|
|
401
|
-
|
|
402
|
-
```jsx
|
|
403
|
-
<Button variant="primary">Primary</Button>
|
|
404
|
-
<Button variant="secondary">Secondary</Button>
|
|
405
|
-
<Button variant="ghost">Ghost</Button>
|
|
406
|
-
|
|
407
|
-
// Размеры с соответствующими иконками
|
|
408
|
-
<Button size="xs" icon={<Mail size={16} strokeWidth={1.5} />}>
|
|
409
|
-
Extra Small
|
|
410
|
-
</Button>
|
|
411
|
-
<Button size="s" icon={<Mail size={20} strokeWidth={1.5} />}>
|
|
412
|
-
Small
|
|
413
|
-
</Button>
|
|
414
|
-
<Button size="m" icon={<Mail size={24} strokeWidth={1.5} />}>
|
|
415
|
-
Medium
|
|
416
|
-
</Button>
|
|
417
|
-
<Button size="l" icon={<Mail size={28} strokeWidth={1.5} />}>
|
|
418
|
-
Large
|
|
419
|
-
</Button>
|
|
420
|
-
|
|
421
|
-
// С fullWidth
|
|
422
|
-
<Button
|
|
423
|
-
variant="primary"
|
|
424
|
-
size="m"
|
|
425
|
-
icon={<Mail size={24} strokeWidth={1.5} />}
|
|
426
|
-
fullWidth
|
|
427
|
-
>
|
|
428
|
-
Send Email
|
|
429
|
-
</Button>
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
### Tabs
|
|
433
|
-
|
|
434
|
-
Вкладки с минималистичным дизайном без border.
|
|
435
|
-
|
|
436
|
-
```jsx
|
|
437
|
-
import { Tabs, Tab } from '@donkit-ai/design-system';
|
|
438
|
-
import { AlertCircle } from 'lucide-react';
|
|
439
|
-
|
|
440
|
-
// Basic tabs
|
|
441
|
-
<Tabs size="m">
|
|
442
|
-
<Tab selected={selectedTab === 'tab1'} onClick={() => setSelectedTab('tab1')}>
|
|
443
|
-
Overview
|
|
444
|
-
</Tab>
|
|
445
|
-
<Tab selected={selectedTab === 'tab2'} onClick={() => setSelectedTab('tab2')}>
|
|
446
|
-
Details
|
|
447
|
-
</Tab>
|
|
448
|
-
<Tab selected={selectedTab === 'tab3'} onClick={() => setSelectedTab('tab3')}>
|
|
449
|
-
Settings
|
|
450
|
-
</Tab>
|
|
451
|
-
</Tabs>
|
|
452
|
-
|
|
453
|
-
// With icons (размер иконки соответствует размеру таба)
|
|
454
|
-
// xs: 16px, small: 20px, medium: 24px, large: 28px
|
|
455
|
-
<Tabs size="s">
|
|
456
|
-
<Tab
|
|
457
|
-
selected={selectedTab === 'alerts'}
|
|
458
|
-
onClick={() => setSelectedTab('alerts')}
|
|
459
|
-
icon={<AlertCircle size={20} strokeWidth={1.5} />}
|
|
460
|
-
>
|
|
461
|
-
Alerts
|
|
462
|
-
</Tab>
|
|
463
|
-
<Tab selected={selectedTab === 'other'} onClick={() => setSelectedTab('other')}>
|
|
464
|
-
Other
|
|
465
|
-
</Tab>
|
|
466
|
-
</Tabs>
|
|
467
|
-
|
|
468
|
-
// Disabled tab
|
|
469
|
-
<Tabs size="m">
|
|
470
|
-
<Tab selected>Active</Tab>
|
|
471
|
-
<Tab disabled>Disabled</Tab>
|
|
472
|
-
</Tabs>
|
|
473
|
-
|
|
474
|
-
// As links (с href) - рендерит <a> вместо <button>
|
|
475
|
-
// При обычном клике: вызывается onClick (preventDefault автоматический)
|
|
476
|
-
// При Cmd/Ctrl+Click или Middle Click: открывается новая вкладка
|
|
477
|
-
<Tabs size="m">
|
|
478
|
-
<Tab selected href="/overview" onClick={() => navigate('/overview')}>
|
|
479
|
-
Overview
|
|
480
|
-
</Tab>
|
|
481
|
-
<Tab href="/details" onClick={() => navigate('/details')}>
|
|
482
|
-
Details
|
|
483
|
-
</Tab>
|
|
484
|
-
<Tab href="/settings" onClick={() => navigate('/settings')}>
|
|
485
|
-
Settings
|
|
486
|
-
</Tab>
|
|
487
|
-
</Tabs>
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
**Стили:**
|
|
491
|
-
- Selected: фон `--color-item-bg-selected`, текст `--color-txt-icon-1`
|
|
492
|
-
- Hover: фон `--color-item-bg-hover`, текст `--color-txt-icon-1`
|
|
493
|
-
- Default: текст `--color-txt-icon-2`
|
|
494
|
-
|
|
495
|
-
**Размеры:** xs, small, medium, large
|
|
496
|
-
|
|
497
|
-
**Дополнительно:** поддержка иконок и disabled состояния
|
|
498
|
-
|
|
499
|
-
### Input
|
|
500
|
-
|
|
501
|
-
```jsx
|
|
502
|
-
// Basic input
|
|
503
|
-
<Input
|
|
504
|
-
label="Email"
|
|
505
|
-
size="m"
|
|
506
|
-
type="email"
|
|
507
|
-
placeholder="email@example.com"
|
|
508
|
-
hint="We'll never share your email"
|
|
509
|
-
/>
|
|
510
|
-
|
|
511
|
-
// Left icon (informational) - size small
|
|
512
|
-
<Input
|
|
513
|
-
label="Search"
|
|
514
|
-
size="s"
|
|
515
|
-
icon={<Search size={20} strokeWidth={1.5} />}
|
|
516
|
-
placeholder="Search..."
|
|
517
|
-
/>
|
|
518
|
-
|
|
519
|
-
// Left icon - size medium
|
|
520
|
-
<Input
|
|
521
|
-
label="Search"
|
|
522
|
-
size="m"
|
|
523
|
-
icon={<Search size={24} strokeWidth={1.5} />}
|
|
524
|
-
placeholder="Search..."
|
|
525
|
-
/>
|
|
526
|
-
|
|
527
|
-
// Right icon (action with hover) - size medium
|
|
528
|
-
<Input
|
|
529
|
-
label="Password"
|
|
530
|
-
size="m"
|
|
531
|
-
type={showPassword ? 'text' : 'password'}
|
|
532
|
-
iconRight={showPassword ? <EyeOff size={24} strokeWidth={1.5} /> : <Eye size={24} strokeWidth={1.5} />}
|
|
533
|
-
onIconRightClick={() => setShowPassword(!showPassword)}
|
|
534
|
-
/>
|
|
535
|
-
|
|
536
|
-
// Error state
|
|
537
|
-
<Input
|
|
538
|
-
label="Name"
|
|
539
|
-
error="This field is required"
|
|
540
|
-
/>
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
**Работа с иконками:**
|
|
544
|
-
- **Иконки слева** (`icon`) - информационные, не интерактивные (email, phone, user, search)
|
|
545
|
-
- **Иконки справа** (`iconRight`) - действия с hover (показать/скрыть пароль, копировать)
|
|
546
|
-
- **Цвет**: по умолчанию `--color-txt-icon-2`, при hover `--color-txt-icon-1`
|
|
547
|
-
- **Обработчик**: используйте `onIconRightClick` для действий правой иконки
|
|
548
|
-
|
|
549
|
-
### Select
|
|
550
|
-
|
|
551
|
-
```jsx
|
|
552
|
-
<Select
|
|
553
|
-
label="Choose option"
|
|
554
|
-
size="m"
|
|
555
|
-
value={value}
|
|
556
|
-
onChange={setValue}
|
|
557
|
-
options={[
|
|
558
|
-
{ value: 'opt1', label: 'Option 1' },
|
|
559
|
-
{ value: 'opt2', label: 'Option 2' },
|
|
560
|
-
]}
|
|
561
|
-
placeholder="Select..."
|
|
562
|
-
/>
|
|
563
|
-
```
|
|
564
|
-
|
|
565
|
-
### Stepper
|
|
15
|
+
// optional:
|
|
16
|
+
// import '@donkit-ai/design-system/light.css';
|
|
17
|
+
// import '@donkit-ai/design-system/high-contrast.css';
|
|
566
18
|
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
```jsx
|
|
570
|
-
// Basic stepper
|
|
571
|
-
<Stepper
|
|
572
|
-
label="Quantity"
|
|
573
|
-
size="m"
|
|
574
|
-
value={quantity}
|
|
575
|
-
onChange={setQuantity}
|
|
576
|
-
min={1}
|
|
577
|
-
max={10}
|
|
578
|
-
step={1}
|
|
579
|
-
/>
|
|
580
|
-
|
|
581
|
-
// Small size
|
|
582
|
-
<Stepper
|
|
583
|
-
label="Price"
|
|
584
|
-
size="s"
|
|
585
|
-
value={price}
|
|
586
|
-
onChange={setPrice}
|
|
587
|
-
min={0}
|
|
588
|
-
max={1000}
|
|
589
|
-
step={10}
|
|
590
|
-
hint="In increments of 10"
|
|
591
|
-
/>
|
|
592
|
-
|
|
593
|
-
// With error
|
|
594
|
-
<Stepper
|
|
595
|
-
label="Age"
|
|
596
|
-
value={age}
|
|
597
|
-
onChange={setAge}
|
|
598
|
-
min={0}
|
|
599
|
-
max={120}
|
|
600
|
-
error="Age is required"
|
|
601
|
-
/>
|
|
602
|
-
|
|
603
|
-
// Disabled
|
|
604
|
-
<Stepper
|
|
605
|
-
label="Fixed value"
|
|
606
|
-
value={50}
|
|
607
|
-
disabled
|
|
608
|
-
/>
|
|
609
|
-
```
|
|
610
|
-
|
|
611
|
-
**Параметры:**
|
|
612
|
-
- `value` - текущее значение (число)
|
|
613
|
-
- `onChange` - функция обработки изменения значения
|
|
614
|
-
- `min` - минимальное значение (default: 0)
|
|
615
|
-
- `max` - максимальное значение (default: 100)
|
|
616
|
-
- `step` - шаг изменения (default: 1)
|
|
617
|
-
- `size` - размер: "s" или "m" (default: "medium")
|
|
618
|
-
- `label` - подпись поля
|
|
619
|
-
- `hint` - подсказка под полем
|
|
620
|
-
- `error` - текст ошибки (показывается вместо hint)
|
|
621
|
-
- `disabled` - отключить поле
|
|
622
|
-
|
|
623
|
-
**Иконки в кнопках:**
|
|
624
|
-
- Small: 16px (Minus, Plus)
|
|
625
|
-
- Medium: 20px (Minus, Plus)
|
|
626
|
-
|
|
627
|
-
### Toggle
|
|
628
|
-
|
|
629
|
-
Переключатель для включения/выключения опций. Размеры привязаны к размерам иконок.
|
|
630
|
-
|
|
631
|
-
```jsx
|
|
632
|
-
// Basic toggle
|
|
633
|
-
<Toggle
|
|
634
|
-
checked={isEnabled}
|
|
635
|
-
onChange={setIsEnabled}
|
|
636
|
-
label="Enable notifications"
|
|
637
|
-
/>
|
|
638
|
-
|
|
639
|
-
// Extra Small size (16px)
|
|
640
|
-
<Toggle
|
|
641
|
-
size="xs"
|
|
642
|
-
checked={isCompact}
|
|
643
|
-
onChange={setIsCompact}
|
|
644
|
-
label="Compact mode"
|
|
645
|
-
/>
|
|
646
|
-
|
|
647
|
-
// Small size (20px)
|
|
648
|
-
<Toggle
|
|
649
|
-
size="s"
|
|
650
|
-
checked={isEnabled}
|
|
651
|
-
onChange={setIsEnabled}
|
|
652
|
-
label="Auto-save"
|
|
653
|
-
/>
|
|
654
|
-
|
|
655
|
-
// Medium size (24px, default)
|
|
656
|
-
<Toggle
|
|
657
|
-
size="m"
|
|
658
|
-
checked={darkMode}
|
|
659
|
-
onChange={setDarkMode}
|
|
660
|
-
label="Dark mode"
|
|
661
|
-
/>
|
|
662
|
-
|
|
663
|
-
// Large size (28px)
|
|
664
|
-
<Toggle
|
|
665
|
-
size="l"
|
|
666
|
-
checked={isEnabled}
|
|
667
|
-
onChange={setIsEnabled}
|
|
668
|
-
label="Enable feature"
|
|
669
|
-
/>
|
|
670
|
-
|
|
671
|
-
// Without label (for tables/cards where context is clear)
|
|
672
|
-
<Toggle
|
|
673
|
-
checked={isEnabled}
|
|
674
|
-
onChange={setIsEnabled}
|
|
675
|
-
/>
|
|
676
|
-
|
|
677
|
-
// Disabled states
|
|
678
|
-
<Toggle
|
|
679
|
-
checked={false}
|
|
680
|
-
onChange={() => {}}
|
|
681
|
-
label="Disabled unchecked"
|
|
682
|
-
disabled
|
|
683
|
-
/>
|
|
684
|
-
|
|
685
|
-
<Toggle
|
|
686
|
-
checked={true}
|
|
687
|
-
onChange={() => {}}
|
|
688
|
-
label="Disabled checked"
|
|
689
|
-
disabled
|
|
690
|
-
/>
|
|
691
|
-
```
|
|
692
|
-
|
|
693
|
-
**Параметры:**
|
|
694
|
-
- `checked` - состояние переключателя (true/false)
|
|
695
|
-
- `onChange` - функция обработки изменения состояния, получает новое значение (boolean)
|
|
696
|
-
- `size` - размер: "xs", "small", "medium" или "large" (default: "medium")
|
|
697
|
-
- `label` - текст подписи (опционально)
|
|
698
|
-
- `disabled` - отключить переключатель
|
|
699
|
-
- `id` - пользовательский ID (по умолчанию генерируется автоматически)
|
|
700
|
-
|
|
701
|
-
**Стиль:**
|
|
702
|
-
- Размеры привязаны к иконкам: xs (16px), small (20px), medium (24px), large (28px)
|
|
703
|
-
- Ширина трека: 1.75x от высоты
|
|
704
|
-
- Включенное состояние: фон `--color-status-success`, border `--color-status-success` (зеленый)
|
|
705
|
-
- Выключенное состояние: фон `--color-item-bg`, border `--color-border`, hover `--color-border-hover`
|
|
706
|
-
|
|
707
|
-
### Checkbox
|
|
708
|
-
|
|
709
|
-
Чекбокс для выбора опций. Размеры привязаны к размерам иконок.
|
|
710
|
-
|
|
711
|
-
```jsx
|
|
712
|
-
// Basic checkbox
|
|
713
|
-
<Checkbox
|
|
714
|
-
checked={isAccepted}
|
|
715
|
-
onChange={setIsAccepted}
|
|
716
|
-
label="Accept terms and conditions"
|
|
717
|
-
/>
|
|
718
|
-
|
|
719
|
-
// Extra Small size (16px)
|
|
720
|
-
<Checkbox
|
|
721
|
-
size="xs"
|
|
722
|
-
checked={isCompact}
|
|
723
|
-
onChange={setIsCompact}
|
|
724
|
-
label="Compact view"
|
|
725
|
-
/>
|
|
726
|
-
|
|
727
|
-
// Small size (20px)
|
|
728
|
-
<Checkbox
|
|
729
|
-
size="s"
|
|
730
|
-
checked={isEnabled}
|
|
731
|
-
onChange={setIsEnabled}
|
|
732
|
-
label="Enable feature"
|
|
733
|
-
/>
|
|
734
|
-
|
|
735
|
-
// Medium size (24px, default)
|
|
736
|
-
<Checkbox
|
|
737
|
-
size="m"
|
|
738
|
-
checked={isSubscribed}
|
|
739
|
-
onChange={setIsSubscribed}
|
|
740
|
-
label="Subscribe to newsletter"
|
|
741
|
-
/>
|
|
742
|
-
|
|
743
|
-
// Large size (28px)
|
|
744
|
-
<Checkbox
|
|
745
|
-
size="l"
|
|
746
|
-
checked={isAccepted}
|
|
747
|
-
onChange={setIsAccepted}
|
|
748
|
-
label="I accept the terms"
|
|
749
|
-
/>
|
|
750
|
-
|
|
751
|
-
// Without label (for tables/lists where context is clear)
|
|
752
|
-
<Checkbox
|
|
753
|
-
checked={isSelected}
|
|
754
|
-
onChange={setIsSelected}
|
|
755
|
-
/>
|
|
756
|
-
|
|
757
|
-
// Disabled states
|
|
758
|
-
<Checkbox
|
|
759
|
-
checked={false}
|
|
760
|
-
onChange={() => {}}
|
|
761
|
-
label="Disabled unchecked"
|
|
762
|
-
disabled
|
|
763
|
-
/>
|
|
764
|
-
|
|
765
|
-
<Checkbox
|
|
766
|
-
checked={true}
|
|
767
|
-
onChange={() => {}}
|
|
768
|
-
label="Disabled checked"
|
|
769
|
-
disabled
|
|
770
|
-
/>
|
|
771
|
-
```
|
|
772
|
-
|
|
773
|
-
**Параметры:**
|
|
774
|
-
- `checked` - состояние чекбокса (true/false)
|
|
775
|
-
- `onChange` - функция обработки изменения состояния, получает новое значение (boolean)
|
|
776
|
-
- `size` - размер: "xs", "small", "medium" или "large" (default: "medium")
|
|
777
|
-
- `label` - текст подписи (опционально)
|
|
778
|
-
- `disabled` - отключить чекбокс
|
|
779
|
-
- `id` - пользовательский ID (по умолчанию генерируется автоматически)
|
|
780
|
-
|
|
781
|
-
**Стиль:**
|
|
782
|
-
- Размеры привязаны к иконкам: xs (16px), small (20px), medium (24px), large (28px)
|
|
783
|
-
- Выбранное состояние: фон `--color-status-success`, border `--color-status-success` (зеленый)
|
|
784
|
-
- Невыбранное состояние: фон `--color-item-bg`, border `--color-border`, hover `--color-border-hover`
|
|
785
|
-
- Иконка галочки (Check) белого цвета при checked
|
|
786
|
-
|
|
787
|
-
### Radio
|
|
788
|
-
|
|
789
|
-
Радиокнопка для выбора одного варианта из группы. Размеры привязаны к размерам иконок.
|
|
790
|
-
|
|
791
|
-
```jsx
|
|
792
|
-
// Basic radio
|
|
793
|
-
<Radio
|
|
794
|
-
checked={selectedOption === 'option1'}
|
|
795
|
-
onChange={() => setSelectedOption('option1')}
|
|
796
|
-
name="options"
|
|
797
|
-
value="option1"
|
|
798
|
-
label="Option 1"
|
|
799
|
-
/>
|
|
800
|
-
|
|
801
|
-
// Extra Small size (16px)
|
|
802
|
-
<Radio
|
|
803
|
-
size="xs"
|
|
804
|
-
checked={size === 'xs'}
|
|
805
|
-
onChange={() => setSize('xs')}
|
|
806
|
-
name="size"
|
|
807
|
-
value="xs"
|
|
808
|
-
label="Extra Small"
|
|
809
|
-
/>
|
|
810
|
-
|
|
811
|
-
// Small size (20px)
|
|
812
|
-
<Radio
|
|
813
|
-
size="s"
|
|
814
|
-
checked={size === 'small'}
|
|
815
|
-
onChange={() => setSize('small')}
|
|
816
|
-
name="size"
|
|
817
|
-
value="small"
|
|
818
|
-
label="Small"
|
|
819
|
-
/>
|
|
820
|
-
|
|
821
|
-
// Medium size (24px, default)
|
|
822
|
-
<Radio
|
|
823
|
-
size="m"
|
|
824
|
-
checked={size === 'medium'}
|
|
825
|
-
onChange={() => setSize('medium')}
|
|
826
|
-
name="size"
|
|
827
|
-
value="medium"
|
|
828
|
-
label="Medium"
|
|
829
|
-
/>
|
|
830
|
-
|
|
831
|
-
// Large size (28px)
|
|
832
|
-
<Radio
|
|
833
|
-
size="l"
|
|
834
|
-
checked={size === 'large'}
|
|
835
|
-
onChange={() => setSize('large')}
|
|
836
|
-
name="size"
|
|
837
|
-
value="large"
|
|
838
|
-
label="Large"
|
|
839
|
-
/>
|
|
840
|
-
|
|
841
|
-
// Radio group example
|
|
842
|
-
<div>
|
|
843
|
-
<Radio
|
|
844
|
-
checked={paymentMethod === 'card'}
|
|
845
|
-
onChange={() => setPaymentMethod('card')}
|
|
846
|
-
name="payment"
|
|
847
|
-
value="card"
|
|
848
|
-
label="Credit Card"
|
|
849
|
-
/>
|
|
850
|
-
<Radio
|
|
851
|
-
checked={paymentMethod === 'paypal'}
|
|
852
|
-
onChange={() => setPaymentMethod('paypal')}
|
|
853
|
-
name="payment"
|
|
854
|
-
value="paypal"
|
|
855
|
-
label="PayPal"
|
|
856
|
-
/>
|
|
857
|
-
<Radio
|
|
858
|
-
checked={paymentMethod === 'bank'}
|
|
859
|
-
onChange={() => setPaymentMethod('bank')}
|
|
860
|
-
name="payment"
|
|
861
|
-
value="bank"
|
|
862
|
-
label="Bank Transfer"
|
|
863
|
-
/>
|
|
864
|
-
</div>
|
|
865
|
-
|
|
866
|
-
// Without label (for tables/lists where context is clear)
|
|
867
|
-
<Radio
|
|
868
|
-
checked={isSelected}
|
|
869
|
-
onChange={() => setIsSelected(true)}
|
|
870
|
-
name="selection"
|
|
871
|
-
value="item1"
|
|
872
|
-
/>
|
|
873
|
-
|
|
874
|
-
// Disabled states
|
|
875
|
-
<Radio
|
|
876
|
-
checked={false}
|
|
877
|
-
onChange={() => {}}
|
|
878
|
-
name="disabled-group"
|
|
879
|
-
value="disabled1"
|
|
880
|
-
label="Disabled unchecked"
|
|
881
|
-
disabled
|
|
882
|
-
/>
|
|
883
|
-
|
|
884
|
-
<Radio
|
|
885
|
-
checked={true}
|
|
886
|
-
onChange={() => {}}
|
|
887
|
-
name="disabled-group"
|
|
888
|
-
value="disabled2"
|
|
889
|
-
label="Disabled checked"
|
|
890
|
-
disabled
|
|
891
|
-
/>
|
|
892
|
-
```
|
|
893
|
-
|
|
894
|
-
**Параметры:**
|
|
895
|
-
- `checked` - состояние радиокнопки (true/false)
|
|
896
|
-
- `onChange` - функция обработки изменения состояния, получает новое значение (boolean)
|
|
897
|
-
- `name` - имя группы радиокнопок (обязательно для группировки)
|
|
898
|
-
- `value` - значение радиокнопки
|
|
899
|
-
- `size` - размер: "xs", "small", "medium" или "large" (default: "medium")
|
|
900
|
-
- `label` - текст подписи (опционально)
|
|
901
|
-
- `disabled` - отключить радиокнопку
|
|
902
|
-
- `id` - пользовательский ID (по умолчанию генерируется автоматически)
|
|
903
|
-
|
|
904
|
-
**Стиль:**
|
|
905
|
-
- Размеры привязаны к иконкам: xs (16px), small (20px), medium (24px), large (28px)
|
|
906
|
-
- Выбранное состояние: фон `--color-status-success`, border `--color-status-success` (зеленый), белая точка внутри
|
|
907
|
-
- Невыбранное состояние: фон `--color-item-bg`, border `--color-border`, hover `--color-border-hover`
|
|
908
|
-
- Круглая форма (border-radius: 50%)
|
|
909
|
-
|
|
910
|
-
### Card
|
|
911
|
-
|
|
912
|
-
Карточки бывают двух типов:
|
|
913
|
-
|
|
914
|
-
```jsx
|
|
915
|
-
// Card Info (по умолчанию)
|
|
916
|
-
// Информационная карточка без интерактивности
|
|
917
|
-
// Прозрачный фон, только border
|
|
918
|
-
<Card padding="m" variant="info">
|
|
919
|
-
<H4>Card Title</H4>
|
|
920
|
-
<P1>Information content</P1>
|
|
921
|
-
</Card>
|
|
922
|
-
|
|
923
|
-
// Card Interactive
|
|
924
|
-
// Интерактивная карточка с hover эффектом
|
|
925
|
-
// При hover меняется фон и border
|
|
926
|
-
<Card padding="l" variant="interactive" onClick={handleClick}>
|
|
927
|
-
<H4>Clickable Card</H4>
|
|
928
|
-
<P1>Interactive content</P1>
|
|
929
|
-
</Card>
|
|
930
|
-
|
|
931
|
-
// Размеры padding
|
|
932
|
-
<Card padding="s">s padding</Card>
|
|
933
|
-
<Card padding="m">m padding</Card>
|
|
934
|
-
<Card padding="l">l padding</Card>
|
|
935
|
-
|
|
936
|
-
// Card как ссылка (рендерит <a> вместо <div>)
|
|
937
|
-
// При обычном клике: вызывается onClick (preventDefault автоматический)
|
|
938
|
-
// При Cmd/Ctrl+Click или Middle Click: открывается новая вкладка
|
|
939
|
-
<Card
|
|
940
|
-
padding="m"
|
|
941
|
-
variant="interactive"
|
|
942
|
-
href="/dashboard"
|
|
943
|
-
onClick={() => navigate('/dashboard')}
|
|
944
|
-
>
|
|
945
|
-
<H4>Dashboard</H4>
|
|
946
|
-
<P1>Go to dashboard page</P1>
|
|
947
|
-
</Card>
|
|
948
|
-
|
|
949
|
-
<Card
|
|
950
|
-
padding="m"
|
|
951
|
-
variant="interactive"
|
|
952
|
-
href="https://example.com"
|
|
953
|
-
>
|
|
954
|
-
<H4>External Link</H4>
|
|
955
|
-
<P1>Visit external site</P1>
|
|
956
|
-
</Card>
|
|
957
|
-
|
|
958
|
-
// Disabled Card Link
|
|
959
|
-
<Card
|
|
960
|
-
padding="m"
|
|
961
|
-
variant="interactive"
|
|
962
|
-
href="/disabled"
|
|
963
|
-
disabled
|
|
964
|
-
>
|
|
965
|
-
<H4>Disabled</H4>
|
|
966
|
-
<P1>This card is disabled</P1>
|
|
967
|
-
</Card>
|
|
968
|
-
```
|
|
969
|
-
|
|
970
|
-
**Стиль:**
|
|
971
|
-
- **variant="info"** (по умолчанию): прозрачный фон, border `--color-border`
|
|
972
|
-
- **variant="interactive"**: фон `--color-item-bg`, при hover фон `--color-item-bg-hover`, курсор pointer
|
|
973
|
-
- Поддержка `href` для рендера как ссылка с умной обработкой кликов
|
|
974
|
-
|
|
975
|
-
### Code
|
|
976
|
-
|
|
977
|
-
```jsx
|
|
978
|
-
// Inline code
|
|
979
|
-
<p>Use <Code>--color-accent</Code> variable</p>
|
|
980
|
-
|
|
981
|
-
// Code block
|
|
982
|
-
<Code block>{`function example() {
|
|
983
|
-
return "Hello World";
|
|
984
|
-
}`}</Code>
|
|
985
|
-
```
|
|
986
|
-
|
|
987
|
-
### Link
|
|
988
|
-
|
|
989
|
-
Ссылки акцентным цветом, подчеркивание появляется при hover.
|
|
990
|
-
|
|
991
|
-
**Стиль:**
|
|
992
|
-
- Цвет: `--color-accent`
|
|
993
|
-
- Без подчеркивания по умолчанию
|
|
994
|
-
- При hover: цвет меняется на `--color-accent-hover` + появляется подчеркивание
|
|
995
|
-
- При active: цвет `--color-accent-hover`
|
|
996
|
-
|
|
997
|
-
### Badge
|
|
998
|
-
|
|
999
|
-
Бейджи для отображения статусов и категорий в двух размерах.
|
|
1000
|
-
|
|
1001
|
-
```jsx
|
|
1002
|
-
// Medium size (default)
|
|
1003
|
-
<Badge variant="success" size="m">Success</Badge>
|
|
1004
|
-
<Badge variant="error" size="m">Error</Badge>
|
|
1005
|
-
<Badge variant="warning" size="m">Warning</Badge>
|
|
1006
|
-
<Badge variant="info" size="m">Info</Badge>
|
|
1007
|
-
|
|
1008
|
-
// Small size
|
|
1009
|
-
<Badge variant="success" size="s">Success</Badge>
|
|
1010
|
-
<Badge variant="error" size="s">Error</Badge>
|
|
1011
|
-
<Badge variant="warning" size="s">Warning</Badge>
|
|
1012
|
-
|
|
1013
|
-
// Variants
|
|
1014
|
-
<Badge variant="default">Default</Badge>
|
|
1015
|
-
<Badge variant="accent">Accent</Badge>
|
|
1016
|
-
```
|
|
1017
|
-
|
|
1018
|
-
**Размеры:**
|
|
1019
|
-
- `small` - компактный размер (font-size: p3, padding: 0 4px, radius: xs)
|
|
1020
|
-
- `medium` - стандартный размер (font-size: p2, padding: 2px 8px, radius: s)
|
|
1021
|
-
|
|
1022
|
-
**Варианты:**
|
|
1023
|
-
- `default` - серый с border
|
|
1024
|
-
- `info` - синий (информация)
|
|
1025
|
-
- `success` - зелёный (успех)
|
|
1026
|
-
- `warning` - жёлтый (предупреждение)
|
|
1027
|
-
- `error` - красный (ошибка)
|
|
1028
|
-
- `accent` - красный акцентный
|
|
1029
|
-
|
|
1030
|
-
Цвета адаптируются для светлой и тёмной темы для обеспечения контраста минимум 4.5:1.
|
|
1031
|
-
|
|
1032
|
-
### Modal
|
|
1033
|
-
|
|
1034
|
-
```jsx
|
|
1035
|
-
<Modal
|
|
1036
|
-
title="Modal Title"
|
|
1037
|
-
onClose={handleClose}
|
|
1038
|
-
size="m"
|
|
1039
|
-
>
|
|
1040
|
-
<P1>Modal content here...</P1>
|
|
1041
|
-
<Input label="Name" placeholder="Enter name" />
|
|
1042
|
-
|
|
1043
|
-
<ModalFooter>
|
|
1044
|
-
<Button variant="secondary" size="m" onClick={handleClose}>
|
|
1045
|
-
Cancel
|
|
1046
|
-
</Button>
|
|
1047
|
-
<Button variant="primary" size="m">
|
|
1048
|
-
Submit
|
|
1049
|
-
</Button>
|
|
1050
|
-
</ModalFooter>
|
|
1051
|
-
</Modal>
|
|
1052
|
-
|
|
1053
|
-
{/* Modal использует иконку закрытия 20px (автоматически) */}
|
|
1054
|
-
```
|
|
1055
|
-
|
|
1056
|
-
---
|
|
1057
|
-
|
|
1058
|
-
## 🛠 Для мейнтейнеров дизайн-системы
|
|
1059
|
-
|
|
1060
|
-
### Публикация в npm
|
|
1061
|
-
|
|
1062
|
-
1. **Внесите изменения** в компоненты или токены
|
|
1063
|
-
|
|
1064
|
-
2. **Обновите версию** в `package.json`:
|
|
1065
|
-
|
|
1066
|
-
```bash
|
|
1067
|
-
npm version patch # 0.2.3 → 0.2.4 (багфиксы)
|
|
1068
|
-
npm version minor # 0.2.3 → 0.3.0 (новые фичи)
|
|
1069
|
-
npm version major # 0.2.3 → 1.0.0 (breaking changes)
|
|
1070
|
-
```
|
|
1071
|
-
|
|
1072
|
-
3. **Создайте тег и запушьте:**
|
|
1073
|
-
|
|
1074
|
-
```bash
|
|
1075
|
-
git push --follow-tags
|
|
1076
|
-
```
|
|
1077
|
-
|
|
1078
|
-
**Готово!** GitLab CI автоматически опубликует новую версию в публичный npm registry.
|
|
1079
|
-
|
|
1080
|
-
### Команда получит обновления
|
|
1081
|
-
|
|
1082
|
-
```bash
|
|
1083
|
-
npm update @donkit-ai/design-system
|
|
1084
|
-
# или
|
|
1085
|
-
npm install @donkit-ai/design-system@latest
|
|
1086
|
-
```
|
|
1087
|
-
|
|
1088
|
-
### Локальная разработка
|
|
1089
|
-
|
|
1090
|
-
Для тестирования изменений локально используйте `npm link`:
|
|
1091
|
-
|
|
1092
|
-
```bash
|
|
1093
|
-
# В папке Donkit-desing-tokens
|
|
1094
|
-
npm link
|
|
1095
|
-
|
|
1096
|
-
# В папке вашего проекта (agent-platform/frontend)
|
|
1097
|
-
npm link @donkit-ai/design-system
|
|
19
|
+
import { Button, Input, Card } from '@donkit-ai/design-system';
|
|
1098
20
|
```
|
|
1099
21
|
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
### Структура версионирования
|
|
1103
|
-
|
|
1104
|
-
- **Главная ветка:** `main` - стабильная версия
|
|
1105
|
-
- **Теги:** `v0.1.0`, `v0.1.2` - релизные версии
|
|
1106
|
-
- **Фичи:** создавайте ветки для больших изменений, мерджите в `main` после ревью
|
|
1107
|
-
|
|
1108
|
-
---
|
|
1109
|
-
|
|
1110
|
-
## Adding a theme
|
|
1111
|
-
|
|
1112
|
-
Donkit DS ships `dark` (default, always in `:root`) plus `light` and `high-contrast` in `src/styles/themes/`. To add your own:
|
|
1113
|
-
|
|
1114
|
-
### 7 шагов
|
|
1115
|
-
|
|
1116
|
-
1. **Скопировать шаблон**
|
|
1117
|
-
```bash
|
|
1118
|
-
cp src/styles/themes/_template.css src/styles/themes/my-theme.css
|
|
1119
|
-
```
|
|
1120
|
-
|
|
1121
|
-
2. **Переименовать атрибут** — заменить `my-theme` на kebab-case название в selector `[data-theme="my-theme"]`
|
|
1122
|
-
|
|
1123
|
-
3. **Заполнить REQUIRED-токены** — 14 обязательных переменных (surface, fg, border, state-overlay, overlay). Без них тема не будет работать:
|
|
1124
|
-
| Группа | Токены |
|
|
1125
|
-
|--------|--------|
|
|
1126
|
-
| Surface | `--color-surface-0..3` |
|
|
1127
|
-
| Foreground | `--color-fg-primary/secondary/disabled` |
|
|
1128
|
-
| Border | `--color-border-light/default/strong/focus` |
|
|
1129
|
-
| State overlay | `--color-state-hover/active/selected` |
|
|
1130
|
-
| Backdrop | `--color-overlay` |
|
|
1131
|
-
|
|
1132
|
-
4. **Оставить OPTIONAL** — shadow, accent, status, data-palette, focus-ring. Не переопределяешь — наследуется от тёмной базы в `:root`.
|
|
1133
|
-
|
|
1134
|
-
5. **Импортировать в проект** после `tokens.css`:
|
|
1135
|
-
```js
|
|
1136
|
-
import '@donkit-ai/design-system/src/styles/tokens.css';
|
|
1137
|
-
import '@donkit-ai/design-system/src/styles/themes/my-theme.css';
|
|
1138
|
-
```
|
|
1139
|
-
Или через CSS:
|
|
1140
|
-
```css
|
|
1141
|
-
@import '@donkit-ai/design-system/src/styles/tokens.css';
|
|
1142
|
-
@import '@donkit-ai/design-system/src/styles/themes/my-theme.css';
|
|
1143
|
-
```
|
|
1144
|
-
|
|
1145
|
-
6. **Добавить в preview** — скопировать колонку в `preview/themes.html`, вставить `data-theme="my-theme"` на `.surface`.
|
|
1146
|
-
|
|
1147
|
-
7. **Прогнать a11y-чеклист**:
|
|
1148
|
-
- [ ] Контраст текста ≥ 4.5:1 (AA), лучше ≥ 7:1 (AAA)
|
|
1149
|
-
- [ ] UI-элементы (бордеры, иконки) ≥ 3:1
|
|
1150
|
-
- [ ] Focus ring чётко виден на всех поверхностях
|
|
1151
|
-
- [ ] Hover overlay различим, но не агрессивен
|
|
1152
|
-
- [ ] Selected отличается от hover визуально
|
|
1153
|
-
- [ ] Overlay/backdrop не слишком плотный и не прозрачный
|
|
1154
|
-
|
|
1155
|
-
### Архитектурный контракт
|
|
1156
|
-
|
|
1157
|
-
```
|
|
1158
|
-
:root ← dark (всегда загружен, база для наследования)
|
|
1159
|
-
[data-theme="light"] ← src/styles/themes/light.css
|
|
1160
|
-
[data-theme="high-contrast"] ← src/styles/themes/high-contrast.css
|
|
1161
|
-
[data-theme="my-theme"] ← твой файл
|
|
1162
|
-
|
|
1163
|
-
[data-variant="edgy"] ← structural, не тема — живёт в tokens.css
|
|
1164
|
-
[data-density="compact"] ← density mode — живёт в tokens.css
|
|
1165
|
-
```
|
|
1166
|
-
|
|
1167
|
-
Темы загружаются unlayered → всегда побеждают `@layer base` из `tokens.css`.
|
|
1168
|
-
|
|
1169
|
-
---
|
|
1170
|
-
|
|
1171
|
-
## Token resilience
|
|
1172
|
-
|
|
1173
|
-
Все структурные токены в компонентах имеют встроенный фолбэк-значение:
|
|
1174
|
-
|
|
1175
|
-
```css
|
|
1176
|
-
/* вместо */
|
|
1177
|
-
height: var(--height-3);
|
|
1178
|
-
|
|
1179
|
-
/* теперь */
|
|
1180
|
-
height: var(--height-3, 44px);
|
|
1181
|
-
```
|
|
1182
|
-
|
|
1183
|
-
Это гарантирует корректный рендер даже если `tokens.css` не подключён или загружается с задержкой.
|
|
1184
|
-
|
|
1185
|
-
### Категории токенов
|
|
1186
|
-
|
|
1187
|
-
| Категория | Примеры | Фолбэк |
|
|
1188
|
-
|-----------|---------|--------|
|
|
1189
|
-
| Radius | `--radius-1..8`, `--radius-full` | `2px`..`9999px` |
|
|
1190
|
-
| Space | `--space-1..16` | `4px`..`64px` |
|
|
1191
|
-
| Height | `--height-1..4`, `--height-2-5` | `24px`..`56px` |
|
|
1192
|
-
| Motion | `--motion-enter/exit/hover` | `0.3s ease`, `0.2s ease` |
|
|
1193
|
-
| Typography | `--text-sm..4xl`, `--font-weight-*` | `12px`..`32px`, `400/500/600` |
|
|
1194
|
-
| Component | `--btn-*`, `--tab-*`, `--badge-radius` | см. tokens.css |
|
|
1195
|
-
|
|
1196
|
-
### Что НЕ имеет фолбэка
|
|
1197
|
-
|
|
1198
|
-
Цветовые (`--color-*`) и тень (`--shadow-*`) токены — намеренно без фолбэка. Отсутствующий цвет должно быть видно сразу, а не скрыто дефолтом.
|
|
1199
|
-
|
|
1200
|
-
---
|
|
1201
|
-
|
|
1202
|
-
## Лицензия
|
|
22
|
+
## Version
|
|
1203
23
|
|
|
1204
|
-
|
|
24
|
+
`1.4.79` — built from the shared design-system source. Brand tokens are selected at package build time; each published package only contains its own brand assets.
|