tharaday 0.7.2 → 0.7.3
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/.storybook/main.ts +1 -1
- package/.storybook/preview.ts +0 -2
- package/.storybook/vitest.setup.ts +2 -0
- package/dist/ds.css +1 -1
- package/dist/ds.js +873 -805
- package/dist/ds.umd.cjs +1 -1
- package/dist/src/components/Tree/Tree.d.ts +1 -1
- package/dist/src/components/Tree/Tree.stories.d.ts +1 -1
- package/dist/src/components/Tree/TreeItem.d.ts +1 -1
- package/dist/src/components/Tree/TreeItem.types.d.ts +6 -0
- package/package.json +8 -1
- package/src/components/Accordion/Accordion.test.tsx +82 -0
- package/src/components/Avatar/Avatar.test.tsx +36 -0
- package/src/components/Badge/Badge.test.tsx +15 -0
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +96 -0
- package/src/components/Checkbox/Checkbox.module.css +7 -7
- package/src/components/Checkbox/Checkbox.test.tsx +68 -0
- package/src/components/Dropdown/Dropdown.test.tsx +104 -0
- package/src/components/Input/Input.test.tsx +61 -0
- package/src/components/List/List.module.css +12 -12
- package/src/components/List/List.test.tsx +46 -0
- package/src/components/Modal/Modal.module.css +5 -5
- package/src/components/Modal/Modal.test.tsx +86 -0
- package/src/components/NavBar/NavBar.module.css +3 -3
- package/src/components/Notification/Notification.module.css +6 -6
- package/src/components/Notification/Notification.test.tsx +38 -0
- package/src/components/Pagination/Pagination.test.tsx +70 -0
- package/src/components/ProgressBar/ProgressBar.test.tsx +58 -0
- package/src/components/RadioButton/RadioButton.test.tsx +51 -0
- package/src/components/Select/Select.test.tsx +64 -0
- package/src/components/Slider/Slider.test.tsx +49 -0
- package/src/components/Stepper/Step.module.css +2 -2
- package/src/components/Stepper/Stepper.test.tsx +51 -0
- package/src/components/Switch/Switch.test.tsx +53 -0
- package/src/components/Table/Table.test.tsx +78 -0
- package/src/components/Tabs/Tabs.test.tsx +83 -0
- package/src/components/Textarea/Textarea.test.tsx +56 -0
- package/src/components/Tree/Tree.test.tsx +116 -0
- package/src/components/Tree/Tree.tsx +65 -1
- package/src/components/Tree/TreeItem.module.css +20 -26
- package/src/components/Tree/TreeItem.tsx +144 -79
- package/src/components/Tree/TreeItem.types.ts +6 -0
- package/src/styles/semantic.css +3 -0
- package/src/styles/tokens.css +15 -0
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import type { KeyboardEvent } from 'react';
|
|
2
4
|
import type { TreeProps } from './Tree.types';
|
|
3
5
|
import styles from './Tree.module.css';
|
|
4
6
|
import { TreeItem } from './TreeItem';
|
|
@@ -11,14 +13,76 @@ export const Tree = ({
|
|
|
11
13
|
collapseIcon,
|
|
12
14
|
...props
|
|
13
15
|
}: TreeProps) => {
|
|
16
|
+
const treeRef = useRef<HTMLDivElement>(null);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const first = treeRef.current?.querySelector<HTMLElement>('[role="treeitem"]');
|
|
20
|
+
if (first) {
|
|
21
|
+
first.tabIndex = 0;
|
|
22
|
+
}
|
|
23
|
+
}, []);
|
|
24
|
+
|
|
25
|
+
const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
|
|
26
|
+
const tree = treeRef.current;
|
|
27
|
+
if (!tree) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const items = Array.from(tree.querySelectorAll<HTMLElement>('[role="treeitem"]'));
|
|
31
|
+
if (items.length === 0) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const current = items.find((el) => el.tabIndex === 0) ?? items[0];
|
|
35
|
+
const idx = items.indexOf(current);
|
|
36
|
+
|
|
37
|
+
switch (e.key) {
|
|
38
|
+
case 'ArrowDown':
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
if (idx < items.length - 1) {
|
|
41
|
+
current.tabIndex = -1;
|
|
42
|
+
items[idx + 1].tabIndex = 0;
|
|
43
|
+
items[idx + 1].focus();
|
|
44
|
+
}
|
|
45
|
+
break;
|
|
46
|
+
case 'ArrowUp':
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
if (idx > 0) {
|
|
49
|
+
current.tabIndex = -1;
|
|
50
|
+
items[idx - 1].tabIndex = 0;
|
|
51
|
+
items[idx - 1].focus();
|
|
52
|
+
}
|
|
53
|
+
break;
|
|
54
|
+
case 'Home':
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
current.tabIndex = -1;
|
|
57
|
+
items[0].tabIndex = 0;
|
|
58
|
+
items[0].focus();
|
|
59
|
+
break;
|
|
60
|
+
case 'End':
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
current.tabIndex = -1;
|
|
63
|
+
items[items.length - 1].tabIndex = 0;
|
|
64
|
+
items[items.length - 1].focus();
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
14
69
|
return (
|
|
15
|
-
<div
|
|
70
|
+
<div
|
|
71
|
+
ref={treeRef}
|
|
72
|
+
role="tree"
|
|
73
|
+
className={clsx(styles.root, className)}
|
|
74
|
+
onKeyDown={handleKeyDown}
|
|
75
|
+
{...props}
|
|
76
|
+
>
|
|
16
77
|
<TreeItem
|
|
17
78
|
data={data}
|
|
18
79
|
defaultExpanded={defaultExpanded}
|
|
19
80
|
expandIcon={expandIcon}
|
|
20
81
|
collapseIcon={collapseIcon}
|
|
21
82
|
isRoot
|
|
83
|
+
level={1}
|
|
84
|
+
setSize={1}
|
|
85
|
+
posInSet={1}
|
|
22
86
|
/>
|
|
23
87
|
</div>
|
|
24
88
|
);
|
|
@@ -1,25 +1,32 @@
|
|
|
1
|
-
.
|
|
2
|
-
|
|
3
|
-
padding-left: var(--ds-space-4);
|
|
4
|
-
margin: 0;
|
|
1
|
+
.item {
|
|
2
|
+
outline: none;
|
|
5
3
|
}
|
|
6
4
|
|
|
7
|
-
.item {
|
|
8
|
-
|
|
5
|
+
.item:focus-visible > .itemHeader {
|
|
6
|
+
box-shadow:
|
|
7
|
+
0 0 0 2px var(--ds-ring-offset),
|
|
8
|
+
0 0 0 4px var(--ds-ring);
|
|
9
|
+
border-radius: var(--ds-radius-sm);
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
.itemHeader {
|
|
12
13
|
display: flex;
|
|
13
14
|
align-items: center;
|
|
14
15
|
min-height: var(--ds-space-6);
|
|
16
|
+
padding: 0 var(--ds-space-1);
|
|
17
|
+
border-radius: var(--ds-radius-sm);
|
|
18
|
+
cursor: default;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
.
|
|
18
|
-
background: none;
|
|
19
|
-
border: none;
|
|
20
|
-
padding: 0;
|
|
21
|
-
margin: 0;
|
|
21
|
+
.branch > .itemHeader {
|
|
22
22
|
cursor: pointer;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.itemHeader:hover {
|
|
26
|
+
background-color: var(--ds-surface-1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.toggleIcon {
|
|
23
30
|
display: inline-flex;
|
|
24
31
|
align-items: center;
|
|
25
32
|
justify-content: center;
|
|
@@ -27,11 +34,6 @@
|
|
|
27
34
|
width: var(--ds-space-5);
|
|
28
35
|
height: var(--ds-space-5);
|
|
29
36
|
flex-shrink: 0;
|
|
30
|
-
transition: transform var(--ds-transition-fast);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.toggleButton:hover {
|
|
34
|
-
color: var(--ds-text-1);
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
.key {
|
|
@@ -50,14 +52,6 @@
|
|
|
50
52
|
margin-left: var(--ds-space-1);
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
.
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.expanded {
|
|
58
|
-
display: block;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.rootList {
|
|
62
|
-
padding-left: 0;
|
|
55
|
+
.childGroup {
|
|
56
|
+
padding-left: var(--ds-space-4);
|
|
63
57
|
}
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
import type { FocusEvent, KeyboardEvent, MouseEvent } from 'react';
|
|
3
4
|
import type { TreeItemProps } from './TreeItem.types';
|
|
4
5
|
import styles from './TreeItem.module.css';
|
|
5
6
|
|
|
7
|
+
function focusTreeItem(item: HTMLElement) {
|
|
8
|
+
const tree = item.closest('[role="tree"]');
|
|
9
|
+
if (!tree) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
tree.querySelectorAll<HTMLElement>('[role="treeitem"]').forEach((el) => {
|
|
13
|
+
el.tabIndex = -1;
|
|
14
|
+
});
|
|
15
|
+
item.tabIndex = 0;
|
|
16
|
+
item.focus();
|
|
17
|
+
}
|
|
18
|
+
|
|
6
19
|
export const TreeItem = ({
|
|
7
20
|
data,
|
|
8
21
|
label,
|
|
@@ -10,14 +23,91 @@ export const TreeItem = ({
|
|
|
10
23
|
expandIcon,
|
|
11
24
|
collapseIcon,
|
|
12
25
|
isRoot,
|
|
26
|
+
level,
|
|
27
|
+
setSize,
|
|
28
|
+
posInSet,
|
|
13
29
|
}: TreeItemProps) => {
|
|
14
30
|
const [isExpanded, setIsExpanded] = useState(isRoot ? true : (defaultExpanded ?? false));
|
|
31
|
+
const itemRef = useRef<HTMLDivElement>(null);
|
|
15
32
|
|
|
16
33
|
const isObject = data !== null && typeof data === 'object';
|
|
17
34
|
const hasChildren =
|
|
18
|
-
isObject && (Array.isArray(data) ? data.length > 0 : Object.keys(data).length > 0);
|
|
35
|
+
isObject && (Array.isArray(data) ? data.length > 0 : Object.keys(data as object).length > 0);
|
|
36
|
+
|
|
37
|
+
const childLevel = isRoot ? level : level + 1;
|
|
38
|
+
|
|
39
|
+
const getChildren = (): { key: string; value: unknown }[] => {
|
|
40
|
+
if (!isObject) {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
if (Array.isArray(data)) {
|
|
44
|
+
return (data as unknown[]).map((v, i) => ({ key: String(i), value: v }));
|
|
45
|
+
}
|
|
46
|
+
return Object.entries(data as Record<string, unknown>).map(([k, v]) => ({ key: k, value: v }));
|
|
47
|
+
};
|
|
19
48
|
|
|
20
|
-
const
|
|
49
|
+
const children = getChildren();
|
|
50
|
+
|
|
51
|
+
const handleClick = (e: MouseEvent) => {
|
|
52
|
+
e.stopPropagation();
|
|
53
|
+
if (hasChildren) {
|
|
54
|
+
setIsExpanded((prev) => !prev);
|
|
55
|
+
}
|
|
56
|
+
if (itemRef.current) {
|
|
57
|
+
focusTreeItem(itemRef.current);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const handleFocus = (e: FocusEvent) => {
|
|
62
|
+
e.stopPropagation();
|
|
63
|
+
if (!itemRef.current) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const tree = itemRef.current.closest('[role="tree"]');
|
|
67
|
+
if (!tree) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
tree.querySelectorAll<HTMLElement>('[role="treeitem"]').forEach((el) => {
|
|
71
|
+
el.tabIndex = -1;
|
|
72
|
+
});
|
|
73
|
+
itemRef.current.tabIndex = 0;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const handleKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
|
|
77
|
+
switch (e.key) {
|
|
78
|
+
case 'Enter':
|
|
79
|
+
case ' ':
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
if (hasChildren) {
|
|
82
|
+
setIsExpanded((prev) => !prev);
|
|
83
|
+
}
|
|
84
|
+
break;
|
|
85
|
+
case 'ArrowRight':
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
e.stopPropagation();
|
|
88
|
+
if (hasChildren && !isExpanded) {
|
|
89
|
+
setIsExpanded(true);
|
|
90
|
+
} else if (hasChildren && isExpanded) {
|
|
91
|
+
const firstChild = itemRef.current?.querySelector<HTMLElement>('[role="treeitem"]');
|
|
92
|
+
if (firstChild) {
|
|
93
|
+
focusTreeItem(firstChild);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
case 'ArrowLeft':
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
e.stopPropagation();
|
|
100
|
+
if (hasChildren && isExpanded) {
|
|
101
|
+
setIsExpanded(false);
|
|
102
|
+
} else {
|
|
103
|
+
const parent = itemRef.current?.parentElement?.closest<HTMLElement>('[role="treeitem"]');
|
|
104
|
+
if (parent) {
|
|
105
|
+
focusTreeItem(parent);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
21
111
|
|
|
22
112
|
const defaultExpandIcon = (
|
|
23
113
|
<svg
|
|
@@ -49,98 +139,73 @@ export const TreeItem = ({
|
|
|
49
139
|
</svg>
|
|
50
140
|
);
|
|
51
141
|
|
|
52
|
-
const
|
|
142
|
+
const renderLeafContent = () => {
|
|
53
143
|
if (data === undefined) {
|
|
54
144
|
return <span className={styles.empty}>undefined</span>;
|
|
55
145
|
}
|
|
56
|
-
|
|
57
146
|
if (data === null) {
|
|
58
147
|
return <span className={styles.empty}>null</span>;
|
|
59
148
|
}
|
|
60
|
-
|
|
61
149
|
if (typeof data !== 'object') {
|
|
62
150
|
return <span className={styles.value}>{String(data)}</span>;
|
|
63
151
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (data.length === 0) {
|
|
67
|
-
return <span className={styles.empty}>[]</span>;
|
|
68
|
-
}
|
|
69
|
-
return (
|
|
70
|
-
<ul
|
|
71
|
-
className={clsx(
|
|
72
|
-
styles.list,
|
|
73
|
-
styles.collapsibleContent,
|
|
74
|
-
isExpanded && styles.expanded,
|
|
75
|
-
isRoot && styles.rootList
|
|
76
|
-
)}
|
|
77
|
-
>
|
|
78
|
-
{data.map((item, index) => (
|
|
79
|
-
<li key={index} className={styles.item}>
|
|
80
|
-
<TreeItem
|
|
81
|
-
data={item}
|
|
82
|
-
defaultExpanded={defaultExpanded}
|
|
83
|
-
expandIcon={expandIcon}
|
|
84
|
-
collapseIcon={collapseIcon}
|
|
85
|
-
/>
|
|
86
|
-
</li>
|
|
87
|
-
))}
|
|
88
|
-
</ul>
|
|
89
|
-
);
|
|
152
|
+
if (Array.isArray(data) && (data as unknown[]).length === 0) {
|
|
153
|
+
return <span className={styles.empty}>[]</span>;
|
|
90
154
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return <span className={styles.empty}>{}</span>;
|
|
155
|
+
if (!Array.isArray(data) && Object.keys(data as object).length === 0) {
|
|
156
|
+
return <span className={styles.empty}>{'{}'}</span>;
|
|
94
157
|
}
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<ul
|
|
98
|
-
className={clsx(
|
|
99
|
-
styles.list,
|
|
100
|
-
styles.collapsibleContent,
|
|
101
|
-
isExpanded && styles.expanded,
|
|
102
|
-
isRoot && styles.rootList
|
|
103
|
-
)}
|
|
104
|
-
>
|
|
105
|
-
{Object.entries(data).map(([key, value]) => (
|
|
106
|
-
<li key={key} className={styles.item}>
|
|
107
|
-
<TreeItem
|
|
108
|
-
label={key}
|
|
109
|
-
data={value}
|
|
110
|
-
defaultExpanded={defaultExpanded}
|
|
111
|
-
expandIcon={expandIcon}
|
|
112
|
-
collapseIcon={collapseIcon}
|
|
113
|
-
/>
|
|
114
|
-
</li>
|
|
115
|
-
))}
|
|
116
|
-
</ul>
|
|
117
|
-
);
|
|
158
|
+
return null;
|
|
118
159
|
};
|
|
119
160
|
|
|
161
|
+
const childrenNodes = children.map((child, index) => (
|
|
162
|
+
<TreeItem
|
|
163
|
+
key={child.key}
|
|
164
|
+
label={Array.isArray(data) ? undefined : child.key}
|
|
165
|
+
data={child.value}
|
|
166
|
+
defaultExpanded={defaultExpanded}
|
|
167
|
+
expandIcon={expandIcon}
|
|
168
|
+
collapseIcon={collapseIcon}
|
|
169
|
+
level={childLevel}
|
|
170
|
+
setSize={children.length}
|
|
171
|
+
posInSet={index + 1}
|
|
172
|
+
/>
|
|
173
|
+
));
|
|
174
|
+
|
|
175
|
+
if (isRoot) {
|
|
176
|
+
return hasChildren ? <>{childrenNodes}</> : <>{renderLeafContent()}</>;
|
|
177
|
+
}
|
|
178
|
+
|
|
120
179
|
return (
|
|
121
|
-
<div
|
|
122
|
-
{
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
180
|
+
<div
|
|
181
|
+
ref={itemRef}
|
|
182
|
+
role="treeitem"
|
|
183
|
+
aria-expanded={hasChildren ? isExpanded : undefined}
|
|
184
|
+
aria-level={level}
|
|
185
|
+
aria-setsize={setSize}
|
|
186
|
+
aria-posinset={posInSet}
|
|
187
|
+
tabIndex={-1}
|
|
188
|
+
className={clsx(styles.item, hasChildren && styles.branch)}
|
|
189
|
+
onClick={handleClick}
|
|
190
|
+
onFocus={handleFocus}
|
|
191
|
+
onKeyDown={handleKeyDown}
|
|
192
|
+
>
|
|
193
|
+
<div className={styles.itemHeader}>
|
|
194
|
+
<span className={styles.toggleIcon} aria-hidden="true">
|
|
195
|
+
{hasChildren
|
|
196
|
+
? isExpanded
|
|
197
|
+
? (collapseIcon ?? defaultCollapseIcon)
|
|
198
|
+
: (expandIcon ?? defaultExpandIcon)
|
|
199
|
+
: null}
|
|
200
|
+
</span>
|
|
201
|
+
{label !== undefined && <span className={styles.key}>{label}:</span>}
|
|
202
|
+
{!hasChildren && renderLeafContent()}
|
|
203
|
+
</div>
|
|
204
|
+
{hasChildren && isExpanded && (
|
|
205
|
+
<div role="group" className={styles.childGroup}>
|
|
206
|
+
{childrenNodes}
|
|
140
207
|
</div>
|
|
141
208
|
)}
|
|
142
|
-
{hasChildren && renderContent()}
|
|
143
|
-
{isRoot && !hasChildren && <div className={styles.itemHeader}>{renderContent()}</div>}
|
|
144
209
|
</div>
|
|
145
210
|
);
|
|
146
211
|
};
|
|
@@ -13,4 +13,10 @@ export interface TreeItemProps {
|
|
|
13
13
|
collapseIcon?: ReactNode;
|
|
14
14
|
/** Whether the tree item is a root element */
|
|
15
15
|
isRoot?: boolean;
|
|
16
|
+
/** ARIA level (depth in the tree, 1-based) */
|
|
17
|
+
level: number;
|
|
18
|
+
/** Total number of siblings at this level */
|
|
19
|
+
setSize: number;
|
|
20
|
+
/** 1-based position among siblings */
|
|
21
|
+
posInSet: number;
|
|
16
22
|
}
|
package/src/styles/semantic.css
CHANGED
|
@@ -50,6 +50,9 @@
|
|
|
50
50
|
--ds-border-default: var(--ds-border-1);
|
|
51
51
|
--ds-surface-disabled: var(--ds-ref-surface-disabled);
|
|
52
52
|
|
|
53
|
+
/* Overlay */
|
|
54
|
+
--ds-overlay: rgba(0, 0, 0, 0.5);
|
|
55
|
+
|
|
53
56
|
/* Skeleton */
|
|
54
57
|
--ds-skeleton: var(--ds-ref-skeleton);
|
|
55
58
|
--ds-skeleton-highlight: var(--ds-ref-skeleton-highlight);
|
package/src/styles/tokens.css
CHANGED
|
@@ -258,8 +258,19 @@
|
|
|
258
258
|
--ds-space-14: 3.5rem; /* 56px */
|
|
259
259
|
--ds-space-16: 4rem; /* 64px */
|
|
260
260
|
|
|
261
|
+
/* --- CONTENT WIDTH SCALE --- */
|
|
262
|
+
|
|
263
|
+
--ds-content-width-sm: 25rem; /* 400px — notifications, small modals */
|
|
264
|
+
--ds-content-width-md: 37.5rem; /* 600px — default modal */
|
|
265
|
+
--ds-content-width-lg: 50rem; /* 800px — large modal */
|
|
266
|
+
--ds-content-width-xl: 62.5rem; /* 1000px — xl modal */
|
|
267
|
+
--ds-content-width-2xl: 75rem; /* 1200px — page/nav max-width */
|
|
268
|
+
|
|
261
269
|
/* --- BORDERS & SHADOWS --- */
|
|
262
270
|
|
|
271
|
+
--ds-border-width: 0.0625rem; /* 1px */
|
|
272
|
+
--ds-border-width-2: 0.125rem; /* 2px */
|
|
273
|
+
|
|
263
274
|
--ds-radius-sm: 0.25rem;
|
|
264
275
|
--ds-radius-md: 0.5rem;
|
|
265
276
|
--ds-radius-lg: 1rem;
|
|
@@ -269,6 +280,10 @@
|
|
|
269
280
|
--ds-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
270
281
|
--ds-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
271
282
|
|
|
283
|
+
/* --- COMPONENT TOKENS --- */
|
|
284
|
+
|
|
285
|
+
--ds-checkbox-size: 1.125rem; /* 18px — checkbox and radio control box */
|
|
286
|
+
|
|
272
287
|
/* --- ANIMATION --- */
|
|
273
288
|
|
|
274
289
|
--ds-transition-fast: 150ms ease;
|