@donkit-ai/design-system 0.2.18 → 0.2.19

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
@@ -37,13 +37,16 @@ npm install @donkit-ai/design-system@latest
37
37
 
38
38
  ## Компоненты
39
39
 
40
- - **Button** - кнопки с вариантами (primary, secondary, ghost) и размерами (small, medium, large). Поддерживает `href` для рендера как ссылка
41
- - **Tabs** - вкладки с состоянием selected в трех размерах (small, medium, large). Поддерживает `href` для рендера как ссылка
42
- - **Input** - текстовые поля с поддержкой иконок, ошибок и подсказок (small, medium)
43
- - **Stepper** - числовое поле с кнопками +/- для изменения значения (small, medium)
40
+ - **Button** - кнопки с вариантами (primary, secondary, ghost) и размерами (xs, small, medium, large). Поддерживает `href` для рендера как ссылка
41
+ - **Tabs** - вкладки с состоянием selected в четырех размерах (xs, small, medium, large). Поддерживает `href` для рендера как ссылка
42
+ - **Input** - текстовые поля с поддержкой иконок, ошибок и подсказок (xs, small, medium)
43
+ - **Textarea** - многострочное текстовое поле (xs, small, medium)
44
+ - **Select** - выпадающий список с кастомным дизайном (xs, small, medium)
45
+ - **Stepper** - числовое поле с кнопками +/- для изменения значения (xs, small, medium)
44
46
  - **Toggle** - переключатель для включения/выключения опций (xs, small, medium, large)
45
47
  - **Checkbox** - чекбокс для выбора опций (xs, small, medium, large)
46
- - **Card** - карточки двух типов: info (информационная, прозрачный фон) и interactive (интерактивная с hover эффектом)
48
+ - **Radio** - радиокнопка для выбора одного варианта из группы (xs, small, medium, large)
49
+ - **Card** - карточки двух типов: info (информационная, прозрачный фон) и interactive (интерактивная с hover эффектом). Поддерживает `href` для рендера как ссылка
47
50
  - **Typography** - H1-H4, P1-P3 компоненты
48
51
  - **Code** - inline и block код с monospace шрифтом
49
52
  - **Link** - ссылки акцентным цветом, при hover цвет меняется и появляется подчеркивание
@@ -113,20 +116,25 @@ import { iconSizes } from '@donkit-ai/design-system';
113
116
  **Соответствие размеров компонентам:**
114
117
 
115
118
  - **16px (xs)** - очень мелкие элементы
119
+ - Extra Small кнопки (`size="xs"`)
120
+ - Extra Small табы (`size="xs"`)
121
+
116
122
  - **20px (s)** - компактные элементы
117
123
  - Small кнопки (`size="small"`)
118
- - Tabs (вкладки)
124
+ - Small табы (`size="small"`)
119
125
  - Modal (иконка закрытия)
120
126
  - Accordion, CodeAccordion
121
127
 
122
128
  - **24px (m)** - стандартные элементы
123
129
  - Medium кнопки (`size="medium"`, по умолчанию)
130
+ - Medium табы (`size="medium"`)
124
131
  - Input (иконки в полях ввода)
125
132
  - Alert (иконки статусов)
126
133
  - Select (иконка выпадающего списка)
127
134
 
128
135
  - **28px (l)** - крупные элементы
129
136
  - Large кнопки (`size="large"`)
137
+ - Large табы (`size="large"`)
130
138
 
131
139
  - **48px (xl)** - очень крупные элементы
132
140
 
@@ -334,6 +342,9 @@ document.documentElement.setAttribute('data-theme', 'light');
334
342
  <Button variant="ghost">Ghost</Button>
335
343
 
336
344
  // Размеры с соответствующими иконками
345
+ <Button size="xs" icon={<Mail size={16} strokeWidth={1.5} />}>
346
+ Extra Small
347
+ </Button>
337
348
  <Button size="small" icon={<Mail size={20} strokeWidth={1.5} />}>
338
349
  Small
339
350
  </Button>
@@ -376,7 +387,8 @@ import { AlertCircle } from 'lucide-react';
376
387
  </Tab>
377
388
  </Tabs>
378
389
 
379
- // With icons (всегда 20px для Tabs)
390
+ // With icons (размер иконки соответствует размеру таба)
391
+ // xs: 16px, small: 20px, medium: 24px, large: 28px
380
392
  <Tabs size="small">
381
393
  <Tab
382
394
  selected={selectedTab === 'alerts'}
@@ -417,7 +429,7 @@ import { AlertCircle } from 'lucide-react';
417
429
  - Hover: фон `--color-item-bg-hover`, текст `--color-txt-icon-1`
418
430
  - Default: текст `--color-txt-icon-2`
419
431
 
420
- **Размеры:** small, medium, large
432
+ **Размеры:** xs, small, medium, large
421
433
 
422
434
  **Дополнительно:** поддержка иконок и disabled состояния
423
435
 
@@ -709,6 +721,129 @@ import { AlertCircle } from 'lucide-react';
709
721
  - Невыбранное состояние: фон `--color-item-bg`, border `--color-border`, hover `--color-border-hover`
710
722
  - Иконка галочки (Check) белого цвета при checked
711
723
 
724
+ ### Radio
725
+
726
+ Радиокнопка для выбора одного варианта из группы. Размеры привязаны к размерам иконок.
727
+
728
+ ```jsx
729
+ // Basic radio
730
+ <Radio
731
+ checked={selectedOption === 'option1'}
732
+ onChange={() => setSelectedOption('option1')}
733
+ name="options"
734
+ value="option1"
735
+ label="Option 1"
736
+ />
737
+
738
+ // Extra Small size (16px)
739
+ <Radio
740
+ size="xs"
741
+ checked={size === 'xs'}
742
+ onChange={() => setSize('xs')}
743
+ name="size"
744
+ value="xs"
745
+ label="Extra Small"
746
+ />
747
+
748
+ // Small size (20px)
749
+ <Radio
750
+ size="small"
751
+ checked={size === 'small'}
752
+ onChange={() => setSize('small')}
753
+ name="size"
754
+ value="small"
755
+ label="Small"
756
+ />
757
+
758
+ // Medium size (24px, default)
759
+ <Radio
760
+ size="medium"
761
+ checked={size === 'medium'}
762
+ onChange={() => setSize('medium')}
763
+ name="size"
764
+ value="medium"
765
+ label="Medium"
766
+ />
767
+
768
+ // Large size (28px)
769
+ <Radio
770
+ size="large"
771
+ checked={size === 'large'}
772
+ onChange={() => setSize('large')}
773
+ name="size"
774
+ value="large"
775
+ label="Large"
776
+ />
777
+
778
+ // Radio group example
779
+ <div>
780
+ <Radio
781
+ checked={paymentMethod === 'card'}
782
+ onChange={() => setPaymentMethod('card')}
783
+ name="payment"
784
+ value="card"
785
+ label="Credit Card"
786
+ />
787
+ <Radio
788
+ checked={paymentMethod === 'paypal'}
789
+ onChange={() => setPaymentMethod('paypal')}
790
+ name="payment"
791
+ value="paypal"
792
+ label="PayPal"
793
+ />
794
+ <Radio
795
+ checked={paymentMethod === 'bank'}
796
+ onChange={() => setPaymentMethod('bank')}
797
+ name="payment"
798
+ value="bank"
799
+ label="Bank Transfer"
800
+ />
801
+ </div>
802
+
803
+ // Without label (for tables/lists where context is clear)
804
+ <Radio
805
+ checked={isSelected}
806
+ onChange={() => setIsSelected(true)}
807
+ name="selection"
808
+ value="item1"
809
+ />
810
+
811
+ // Disabled states
812
+ <Radio
813
+ checked={false}
814
+ onChange={() => {}}
815
+ name="disabled-group"
816
+ value="disabled1"
817
+ label="Disabled unchecked"
818
+ disabled
819
+ />
820
+
821
+ <Radio
822
+ checked={true}
823
+ onChange={() => {}}
824
+ name="disabled-group"
825
+ value="disabled2"
826
+ label="Disabled checked"
827
+ disabled
828
+ />
829
+ ```
830
+
831
+ **Параметры:**
832
+ - `checked` - состояние радиокнопки (true/false)
833
+ - `onChange` - функция обработки изменения состояния, получает новое значение (boolean)
834
+ - `name` - имя группы радиокнопок (обязательно для группировки)
835
+ - `value` - значение радиокнопки
836
+ - `size` - размер: "xs", "small", "medium" или "large" (default: "medium")
837
+ - `label` - текст подписи (опционально)
838
+ - `disabled` - отключить радиокнопку
839
+ - `id` - пользовательский ID (по умолчанию генерируется автоматически)
840
+
841
+ **Стиль:**
842
+ - Размеры привязаны к иконкам: xs (16px), small (20px), medium (24px), large (28px)
843
+ - Выбранное состояние: фон `--color-status-success`, border `--color-status-success` (зеленый), белая точка внутри
844
+ - Невыбранное состояние: фон `--color-item-bg`, border `--color-border`, hover `--color-border-hover`
845
+ - Круглая форма (border-radius: 50%)
846
+
712
847
  ### Card
713
848
 
714
849
  Карточки бывают двух типов:
@@ -734,11 +869,45 @@ import { AlertCircle } from 'lucide-react';
734
869
  <Card padding="small">Small padding</Card>
735
870
  <Card padding="medium">Medium padding</Card>
736
871
  <Card padding="large">Large padding</Card>
872
+
873
+ // Card как ссылка (рендерит <a> вместо <div>)
874
+ // При обычном клике: вызывается onClick (preventDefault автоматический)
875
+ // При Cmd/Ctrl+Click или Middle Click: открывается новая вкладка
876
+ <Card
877
+ padding="medium"
878
+ variant="interactive"
879
+ href="/dashboard"
880
+ onClick={() => navigate('/dashboard')}
881
+ >
882
+ <H4>Dashboard</H4>
883
+ <P1>Go to dashboard page</P1>
884
+ </Card>
885
+
886
+ <Card
887
+ padding="medium"
888
+ variant="interactive"
889
+ href="https://example.com"
890
+ >
891
+ <H4>External Link</H4>
892
+ <P1>Visit external site</P1>
893
+ </Card>
894
+
895
+ // Disabled Card Link
896
+ <Card
897
+ padding="medium"
898
+ variant="interactive"
899
+ href="/disabled"
900
+ disabled
901
+ >
902
+ <H4>Disabled</H4>
903
+ <P1>This card is disabled</P1>
904
+ </Card>
737
905
  ```
738
906
 
739
907
  **Стиль:**
740
908
  - **variant="info"** (по умолчанию): прозрачный фон, border `--color-border`
741
- - **variant="interactive"**: фон `--color-item-bg`, при hover фон `--color-item-bg-hover` и border `--color-border-hover`, курсор pointer
909
+ - **variant="interactive"**: фон `--color-item-bg`, при hover фон `--color-item-bg-hover`, курсор pointer
910
+ - Поддержка `href` для рендера как ссылка с умной обработкой кликов
742
911
 
743
912
  ### Code
744
913
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@donkit-ai/design-system",
3
- "version": "0.2.18",
3
+ "version": "0.2.19",
4
4
  "description": "Donkit Design System - minimal design tokens and React components",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -61,6 +61,13 @@
61
61
  }
62
62
 
63
63
  /* Sizes */
64
+ .ds-button--xs {
65
+ height: var(--height-xs);
66
+ padding: 0 calc(var(--height-xs) / 2);
67
+ font-size: var(--font-size-p3);
68
+ border-radius: var(--radius-xs);
69
+ }
70
+
64
71
  .ds-button--small {
65
72
  height: var(--height-s);
66
73
  padding: 0 calc(var(--height-s) / 2);
@@ -3,6 +3,8 @@
3
3
  border-radius: var(--radius-s);
4
4
  border: 1px solid var(--color-border);
5
5
  transition: border-color var(--transition-normal), background-color var(--transition-normal);
6
+ text-decoration: none;
7
+ color: inherit;
6
8
  }
7
9
 
8
10
  .ds-card--interactive {
@@ -11,10 +13,16 @@
11
13
  border: none;
12
14
  }
13
15
 
14
- .ds-card--interactive:hover {
16
+ .ds-card--interactive:hover:not([aria-disabled="true"]) {
15
17
  background-color: var(--color-item-bg-hover);
16
18
  }
17
19
 
20
+ .ds-card[aria-disabled="true"] {
21
+ opacity: 0.5;
22
+ cursor: not-allowed;
23
+ pointer-events: none;
24
+ }
25
+
18
26
  .ds-card--none {
19
27
  padding: 0;
20
28
  }
@@ -7,10 +7,12 @@ export function Card({
7
7
  variant = 'info',
8
8
  hover = false, // deprecated, use variant="interactive"
9
9
  onClick,
10
+ href,
11
+ disabled = false,
10
12
  ...props
11
13
  }) {
12
14
  const cardVariant = hover ? 'interactive' : variant;
13
- const isInteractive = cardVariant === 'interactive' || onClick;
15
+ const isInteractive = cardVariant === 'interactive' || onClick || href;
14
16
 
15
17
  const className = [
16
18
  'ds-card',
@@ -18,10 +20,41 @@ export function Card({
18
20
  isInteractive && 'ds-card--interactive',
19
21
  ].filter(Boolean).join(' ');
20
22
 
23
+ // Render as link if href is provided
24
+ if (href) {
25
+ const handleClick = (e) => {
26
+ if (disabled) {
27
+ e.preventDefault();
28
+ return;
29
+ }
30
+ // При Cmd/Ctrl+Click или Middle Click — пусть браузер откроет новую вкладку
31
+ if (e.metaKey || e.ctrlKey || e.button === 1) {
32
+ return;
33
+ }
34
+ // Обычный клик — preventDefault и вызов onClick
35
+ e.preventDefault();
36
+ onClick?.(e);
37
+ };
38
+
39
+ return (
40
+ <a
41
+ className={className}
42
+ href={disabled ? undefined : href}
43
+ onClick={handleClick}
44
+ aria-disabled={disabled ? 'true' : undefined}
45
+ {...props}
46
+ >
47
+ {children}
48
+ </a>
49
+ );
50
+ }
51
+
52
+ // Render as button if interactive with onClick
21
53
  const Element = isInteractive && onClick ? 'button' : 'div';
22
54
  const interactiveProps = isInteractive && onClick ? {
23
55
  type: 'button',
24
56
  onClick,
57
+ disabled,
25
58
  } : {};
26
59
 
27
60
  return (
@@ -58,6 +58,13 @@
58
58
  }
59
59
 
60
60
  /* Sizes */
61
+ .ds-input--xs {
62
+ height: var(--height-xs);
63
+ padding: 0 calc(var(--height-xs) / 4);
64
+ font-size: var(--font-size-p3);
65
+ border-radius: var(--radius-xs);
66
+ }
67
+
61
68
  .ds-input--small {
62
69
  height: var(--height-s);
63
70
  padding: 0 calc(var(--height-s) / 4);
@@ -72,6 +79,10 @@
72
79
  border-radius: var(--radius-s);
73
80
  }
74
81
 
82
+ .ds-input--with-icon.ds-input--xs {
83
+ padding-left: calc(var(--height-xs) / 4 + 16px + var(--height-xs) / 4);
84
+ }
85
+
75
86
  .ds-input--with-icon.ds-input--small {
76
87
  padding-left: calc(var(--height-s) / 4 + 20px + var(--height-s) / 4);
77
88
  }
@@ -80,6 +91,10 @@
80
91
  padding-left: calc(var(--height-m) / 4 + 24px + var(--height-m) / 4);
81
92
  }
82
93
 
94
+ .ds-input--with-icon-right.ds-input--xs {
95
+ padding-right: calc(var(--height-xs) / 4 + 16px + var(--height-xs) / 4);
96
+ }
97
+
83
98
  .ds-input--with-icon-right.ds-input--small {
84
99
  padding-right: calc(var(--height-s) / 4 + 20px + var(--height-s) / 4);
85
100
  }
@@ -96,6 +111,10 @@
96
111
  pointer-events: none;
97
112
  }
98
113
 
114
+ .ds-input-icon--xs {
115
+ left: 6px;
116
+ }
117
+
99
118
  .ds-input-icon--small {
100
119
  left: 8px;
101
120
  }
@@ -121,6 +140,10 @@
121
140
  color: var(--color-txt-icon-1);
122
141
  }
123
142
 
143
+ .ds-input-icon-right--xs {
144
+ right: 6px;
145
+ }
146
+
124
147
  .ds-input-icon-right--small {
125
148
  right: 8px;
126
149
  }
@@ -0,0 +1,115 @@
1
+ .ds-radio {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--space-s);
5
+ cursor: pointer;
6
+ }
7
+
8
+ .ds-radio--disabled {
9
+ opacity: 0.5;
10
+ cursor: not-allowed;
11
+ }
12
+
13
+ .ds-radio__input {
14
+ position: absolute;
15
+ opacity: 0;
16
+ pointer-events: none;
17
+ }
18
+
19
+ .ds-radio__circle {
20
+ position: relative;
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ background-color: var(--color-item-bg);
25
+ border: 1px solid var(--color-border);
26
+ transition: background-color var(--transition-normal), border-color var(--transition-normal);
27
+ flex-shrink: 0;
28
+ border-radius: 50%;
29
+ }
30
+
31
+ .ds-radio__input:checked + .ds-radio__circle {
32
+ background-color: var(--color-status-success);
33
+ border-color: var(--color-status-success);
34
+ }
35
+
36
+ .ds-radio__input:not(:checked) + .ds-radio__circle:hover {
37
+ border-color: var(--color-border-hover);
38
+ }
39
+
40
+ .ds-radio__dot {
41
+ background-color: var(--color-white);
42
+ border-radius: 50%;
43
+ opacity: 0;
44
+ transition: opacity var(--transition-normal);
45
+ }
46
+
47
+ .ds-radio__input:checked + .ds-radio__circle .ds-radio__dot {
48
+ opacity: 1;
49
+ }
50
+
51
+ .ds-radio__label {
52
+ font-size: var(--font-size-p1);
53
+ color: var(--color-txt-icon-1);
54
+ user-select: none;
55
+ }
56
+
57
+ /* Extra Small */
58
+ .ds-radio--xs .ds-radio__circle {
59
+ width: var(--icon-xs);
60
+ height: var(--icon-xs);
61
+ }
62
+
63
+ .ds-radio--xs .ds-radio__dot {
64
+ width: 6px;
65
+ height: 6px;
66
+ }
67
+
68
+ .ds-radio--xs .ds-radio__label {
69
+ font-size: var(--font-size-p3);
70
+ }
71
+
72
+ /* Small */
73
+ .ds-radio--small .ds-radio__circle {
74
+ width: var(--icon-s);
75
+ height: var(--icon-s);
76
+ }
77
+
78
+ .ds-radio--small .ds-radio__dot {
79
+ width: 8px;
80
+ height: 8px;
81
+ }
82
+
83
+ .ds-radio--small .ds-radio__label {
84
+ font-size: var(--font-size-p2);
85
+ }
86
+
87
+ /* Medium */
88
+ .ds-radio--medium .ds-radio__circle {
89
+ width: var(--icon-m);
90
+ height: var(--icon-m);
91
+ }
92
+
93
+ .ds-radio--medium .ds-radio__dot {
94
+ width: 10px;
95
+ height: 10px;
96
+ }
97
+
98
+ .ds-radio--medium .ds-radio__label {
99
+ font-size: var(--font-size-p1);
100
+ }
101
+
102
+ /* Large */
103
+ .ds-radio--large .ds-radio__circle {
104
+ width: var(--icon-l);
105
+ height: var(--icon-l);
106
+ }
107
+
108
+ .ds-radio--large .ds-radio__dot {
109
+ width: 12px;
110
+ height: 12px;
111
+ }
112
+
113
+ .ds-radio--large .ds-radio__label {
114
+ font-size: var(--font-size-p1);
115
+ }
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import './Radio.css';
3
+
4
+ export function Radio({
5
+ checked = false,
6
+ onChange,
7
+ size = 'medium',
8
+ disabled = false,
9
+ label,
10
+ name,
11
+ value,
12
+ id,
13
+ ...props
14
+ }) {
15
+ const radioId = id || `radio-${React.useId()}`;
16
+
17
+ const className = [
18
+ 'ds-radio',
19
+ `ds-radio--${size}`,
20
+ disabled && 'ds-radio--disabled',
21
+ ].filter(Boolean).join(' ');
22
+
23
+ return (
24
+ <label className={className} htmlFor={radioId}>
25
+ <input
26
+ type="radio"
27
+ id={radioId}
28
+ className="ds-radio__input"
29
+ checked={checked}
30
+ onChange={(e) => onChange?.(e.target.checked)}
31
+ disabled={disabled}
32
+ name={name}
33
+ value={value}
34
+ {...props}
35
+ />
36
+ <span className="ds-radio__circle">
37
+ <span className="ds-radio__dot" />
38
+ </span>
39
+ {label && <span className="ds-radio__label">{label}</span>}
40
+ </label>
41
+ );
42
+ }
@@ -60,6 +60,13 @@
60
60
  }
61
61
 
62
62
  /* Sizes */
63
+ .ds-select-trigger--xs {
64
+ height: var(--height-xs);
65
+ padding: 0 calc(var(--height-xs) / 4);
66
+ font-size: var(--font-size-p3);
67
+ border-radius: var(--radius-xs);
68
+ }
69
+
63
70
  .ds-select-trigger--small {
64
71
  height: var(--height-s);
65
72
  padding: 0 calc(var(--height-s) / 4);
@@ -53,7 +53,7 @@ export function Select({
53
53
  }, [isOpen]);
54
54
 
55
55
  const selectedOption = options.find(opt => opt.value === value);
56
- const iconSize = size === 'small' ? iconSizes.s : iconSizes.m;
56
+ const iconSize = size === 'xs' ? iconSizes.xs : size === 'small' ? iconSizes.s : iconSizes.m;
57
57
 
58
58
  return (
59
59
  <div className={`ds-select-wrapper ${fullWidth ? 'ds-select-wrapper--full' : ''} ${disabled ? 'ds-select-wrapper--disabled' : ''}`}>
@@ -98,6 +98,22 @@
98
98
 
99
99
  /* Sizes */
100
100
 
101
+ /* Extra Small */
102
+ .ds-stepper--xs {
103
+ height: var(--height-xs);
104
+ }
105
+
106
+ .ds-stepper--xs .ds-stepper-button {
107
+ width: var(--height-xs);
108
+ padding: 0;
109
+ }
110
+
111
+ .ds-stepper--xs .ds-stepper-input {
112
+ font-size: var(--font-size-p3);
113
+ letter-spacing: var(--letter-spacing-p3);
114
+ padding: 0 var(--space-xs);
115
+ }
116
+
101
117
  /* Small */
102
118
  .ds-stepper--small {
103
119
  height: var(--height-s);
@@ -57,7 +57,7 @@ export function Stepper({
57
57
  disabled && 'ds-stepper--disabled',
58
58
  ].filter(Boolean).join(' ');
59
59
 
60
- const iconSize = size === 'small' ? iconSizes.s : iconSizes.m;
60
+ const iconSize = size === 'xs' ? iconSizes.xs : size === 'small' ? iconSizes.s : iconSizes.m;
61
61
 
62
62
  return (
63
63
  <div className={className}>
@@ -37,6 +37,13 @@
37
37
  }
38
38
 
39
39
  /* Sizes */
40
+ .ds-tab--xs {
41
+ height: var(--height-xs);
42
+ padding: 0 calc(var(--height-xs) / 2);
43
+ font-size: var(--font-size-p3);
44
+ border-radius: var(--radius-xs);
45
+ }
46
+
40
47
  .ds-tab--small {
41
48
  height: var(--height-s);
42
49
  padding: 0 calc(var(--height-s) / 2);
@@ -87,6 +87,12 @@
87
87
  }
88
88
 
89
89
  /* Sizes */
90
+ .ds-textarea--xs {
91
+ padding: var(--space-xs);
92
+ font-size: var(--font-size-p3);
93
+ border-radius: var(--radius-xs);
94
+ }
95
+
90
96
  .ds-textarea--small {
91
97
  padding: var(--space-xs) var(--space-s);
92
98
  font-size: var(--font-size-p2);
package/src/index.js CHANGED
@@ -21,3 +21,4 @@ export { CodeAccordion } from './components/CodeAccordion';
21
21
  export { Tooltip } from './components/Tooltip';
22
22
  export { Toggle } from './components/Toggle';
23
23
  export { Checkbox } from './components/Checkbox';
24
+ export { Radio } from './components/Radio';
@@ -171,6 +171,7 @@
171
171
  /* =====================================
172
172
  * 5) Component heights
173
173
  * ===================================*/
174
+ --height-xs: 24px;
174
175
  --height-s: 32px;
175
176
  --height-m: 44px;
176
177
  --height-l: 56px;