@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 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
- ### 2. Использование компонентов
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
- MIT
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.