@donkit-ai/design-system 0.2.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/README.md +795 -0
- package/package.json +40 -0
- package/src/components/Accordion.css +43 -0
- package/src/components/Accordion.jsx +35 -0
- package/src/components/Alert.css +98 -0
- package/src/components/Alert.jsx +46 -0
- package/src/components/Badge.css +57 -0
- package/src/components/Badge.jsx +25 -0
- package/src/components/Button.css +94 -0
- package/src/components/Button.jsx +40 -0
- package/src/components/Card.css +32 -0
- package/src/components/Card.jsx +37 -0
- package/src/components/Code.css +30 -0
- package/src/components/Code.jsx +27 -0
- package/src/components/CodeAccordion.css +59 -0
- package/src/components/CodeAccordion.jsx +35 -0
- package/src/components/Input.css +140 -0
- package/src/components/Input.jsx +55 -0
- package/src/components/Link.css +18 -0
- package/src/components/Link.jsx +21 -0
- package/src/components/Modal.css +66 -0
- package/src/components/Modal.jsx +71 -0
- package/src/components/Select.css +150 -0
- package/src/components/Select.jsx +117 -0
- package/src/components/Stepper.css +163 -0
- package/src/components/Stepper.jsx +103 -0
- package/src/components/Tabs.css +92 -0
- package/src/components/Tabs.jsx +41 -0
- package/src/components/Textarea.css +80 -0
- package/src/components/Textarea.jsx +41 -0
- package/src/components/Typography.css +74 -0
- package/src/components/Typography.jsx +42 -0
- package/src/index.js +19 -0
- package/src/styles/tokens.css +278 -0
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@donkit-ai/design-system",
|
|
3
|
+
"version": "0.2.3",
|
|
4
|
+
"description": "Donkit Design System - minimal design tokens and React components",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./tokens.css": "./src/styles/tokens.css",
|
|
10
|
+
"./components/*": "./src/components/*.jsx"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"src/components",
|
|
14
|
+
"src/styles",
|
|
15
|
+
"src/index.js",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"dev": "vite",
|
|
20
|
+
"build": "vite build",
|
|
21
|
+
"preview": "vite preview"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"react": ">=18.0.0 <21.0.0",
|
|
25
|
+
"react-dom": ">=18.0.0 <21.0.0"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"lucide-react": "^0.445.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@vitejs/plugin-react": "^4.3.1",
|
|
32
|
+
"vite": "^5.4.0",
|
|
33
|
+
"react": "^19.0.0",
|
|
34
|
+
"react-dom": "^19.0.0"
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "https://gitlab.com/donkit-ai/platform/design/design-system.git"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
.ds-accordion {
|
|
2
|
+
border: 1px solid var(--color-border);
|
|
3
|
+
border-radius: var(--radius-s);
|
|
4
|
+
overflow: hidden;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.ds-accordion__header {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: space-between;
|
|
11
|
+
width: 100%;
|
|
12
|
+
padding: var(--space-m);
|
|
13
|
+
background-color: var(--color-item-bg);
|
|
14
|
+
border: none;
|
|
15
|
+
color: var(--color-txt-icon-1);
|
|
16
|
+
font-size: var(--font-size-h4);
|
|
17
|
+
font-family: inherit;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
transition: background-color var(--transition-normal);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.ds-accordion__header:hover {
|
|
23
|
+
background-color: var(--color-item-bg-hover);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.ds-accordion__title {
|
|
27
|
+
font-weight: 400;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ds-accordion__icon {
|
|
31
|
+
flex-shrink: 0;
|
|
32
|
+
color: var(--color-txt-icon-2);
|
|
33
|
+
transition: transform var(--transition-normal);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.ds-accordion__icon--expanded {
|
|
37
|
+
transform: rotate(180deg);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.ds-accordion__content {
|
|
41
|
+
padding: var(--space-m);
|
|
42
|
+
border-top: 1px solid var(--color-border);
|
|
43
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { ChevronDown } from 'lucide-react';
|
|
3
|
+
import './Accordion.css';
|
|
4
|
+
|
|
5
|
+
export function Accordion({
|
|
6
|
+
children,
|
|
7
|
+
title,
|
|
8
|
+
defaultExpanded = false,
|
|
9
|
+
...props
|
|
10
|
+
}) {
|
|
11
|
+
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div className="ds-accordion" {...props}>
|
|
15
|
+
<button
|
|
16
|
+
type="button"
|
|
17
|
+
className="ds-accordion__header"
|
|
18
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
19
|
+
aria-expanded={isExpanded}
|
|
20
|
+
>
|
|
21
|
+
<span className="ds-accordion__title">{title}</span>
|
|
22
|
+
<ChevronDown
|
|
23
|
+
size={20}
|
|
24
|
+
strokeWidth={1.5}
|
|
25
|
+
className={`ds-accordion__icon ${isExpanded ? 'ds-accordion__icon--expanded' : ''}`}
|
|
26
|
+
/>
|
|
27
|
+
</button>
|
|
28
|
+
{isExpanded && (
|
|
29
|
+
<div className="ds-accordion__content">
|
|
30
|
+
{children}
|
|
31
|
+
</div>
|
|
32
|
+
)}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
.ds-alert {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: flex-start;
|
|
4
|
+
gap: var(--space-s);
|
|
5
|
+
padding: var(--space-s);
|
|
6
|
+
border-radius: var(--radius-s);
|
|
7
|
+
border: 1px solid;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.ds-alert--no-title {
|
|
11
|
+
align-items: center;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.ds-alert__icon {
|
|
15
|
+
flex-shrink: 0;
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.ds-alert:not(.ds-alert--no-title) .ds-alert__icon {
|
|
22
|
+
margin-top: 2px;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.ds-alert__content {
|
|
26
|
+
flex: 1;
|
|
27
|
+
min-width: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ds-alert__title {
|
|
31
|
+
font-size: var(--font-size-p1);
|
|
32
|
+
font-weight: 400;
|
|
33
|
+
margin-bottom: var(--space-xs);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.ds-alert__message {
|
|
37
|
+
font-size: var(--font-size-p2);
|
|
38
|
+
line-height: 1.5;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.ds-alert__close {
|
|
42
|
+
flex-shrink: 0;
|
|
43
|
+
background: none;
|
|
44
|
+
border: none;
|
|
45
|
+
color: inherit;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
padding: 0;
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: center;
|
|
50
|
+
justify-content: center;
|
|
51
|
+
opacity: 0.7;
|
|
52
|
+
transition: opacity var(--transition-normal);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.ds-alert__close:hover {
|
|
56
|
+
opacity: 1;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Variants */
|
|
60
|
+
.ds-alert--info {
|
|
61
|
+
background-color: var(--color-status-info-bg);
|
|
62
|
+
border-color: var(--color-status-info);
|
|
63
|
+
color: var(--color-status-info);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.ds-alert--info .ds-alert__message {
|
|
67
|
+
color: var(--color-txt-icon-1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.ds-alert--success {
|
|
71
|
+
background-color: var(--color-status-success-bg);
|
|
72
|
+
border-color: var(--color-status-success);
|
|
73
|
+
color: var(--color-status-success);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.ds-alert--success .ds-alert__message {
|
|
77
|
+
color: var(--color-txt-icon-1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.ds-alert--warning {
|
|
81
|
+
background-color: var(--color-status-warning-bg);
|
|
82
|
+
border-color: var(--color-status-warning);
|
|
83
|
+
color: var(--color-status-warning);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.ds-alert--warning .ds-alert__message {
|
|
87
|
+
color: var(--color-txt-icon-1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.ds-alert--error {
|
|
91
|
+
background-color: var(--color-status-error-bg);
|
|
92
|
+
border-color: var(--color-status-error);
|
|
93
|
+
color: var(--color-status-error);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.ds-alert--error .ds-alert__message {
|
|
97
|
+
color: var(--color-txt-icon-1);
|
|
98
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Info, CheckCircle, AlertTriangle, XCircle, X } from 'lucide-react';
|
|
3
|
+
import './Alert.css';
|
|
4
|
+
|
|
5
|
+
const ICON_MAP = {
|
|
6
|
+
info: Info,
|
|
7
|
+
success: CheckCircle,
|
|
8
|
+
warning: AlertTriangle,
|
|
9
|
+
error: XCircle,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function Alert({
|
|
13
|
+
children,
|
|
14
|
+
variant = 'info',
|
|
15
|
+
title,
|
|
16
|
+
onClose,
|
|
17
|
+
role,
|
|
18
|
+
...props
|
|
19
|
+
}) {
|
|
20
|
+
const Icon = ICON_MAP[variant];
|
|
21
|
+
const alertRole = role || (variant === 'error' ? 'alert' : 'status');
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<div className={`ds-alert ds-alert--${variant} ${!title ? 'ds-alert--no-title' : ''}`} role={alertRole} {...props}>
|
|
25
|
+
{Icon && (
|
|
26
|
+
<div className="ds-alert__icon">
|
|
27
|
+
<Icon size={24} strokeWidth={1.5} />
|
|
28
|
+
</div>
|
|
29
|
+
)}
|
|
30
|
+
<div className="ds-alert__content">
|
|
31
|
+
{title && <div className="ds-alert__title">{title}</div>}
|
|
32
|
+
{children && <div className="ds-alert__message">{children}</div>}
|
|
33
|
+
</div>
|
|
34
|
+
{onClose && (
|
|
35
|
+
<button
|
|
36
|
+
type="button"
|
|
37
|
+
className="ds-alert__close"
|
|
38
|
+
onClick={onClose}
|
|
39
|
+
aria-label="Close alert"
|
|
40
|
+
>
|
|
41
|
+
<X size={24} strokeWidth={1.5} />
|
|
42
|
+
</button>
|
|
43
|
+
)}
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
.ds-badge {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
white-space: nowrap;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* Sizes */
|
|
9
|
+
.ds-badge--small {
|
|
10
|
+
padding: 0 4px;
|
|
11
|
+
font-size: var(--font-size-p3);
|
|
12
|
+
letter-spacing: var(--letter-spacing-p3);
|
|
13
|
+
border-radius: var(--radius-xs);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.ds-badge--medium {
|
|
17
|
+
padding: 2px var(--space-xs);
|
|
18
|
+
font-size: var(--font-size-p2);
|
|
19
|
+
letter-spacing: var(--letter-spacing-p2);
|
|
20
|
+
border-radius: var(--radius-s);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.ds-badge--default {
|
|
24
|
+
background-color: var(--color-item-bg);
|
|
25
|
+
color: var(--color-txt-icon-2);
|
|
26
|
+
border: 1px solid var(--color-txt-icon-2);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.ds-badge--info {
|
|
30
|
+
background-color: var(--color-status-info-bg);
|
|
31
|
+
color: var(--color-status-info);
|
|
32
|
+
border: 1px solid var(--color-status-info);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.ds-badge--success {
|
|
36
|
+
background-color: var(--color-status-success-bg);
|
|
37
|
+
color: var(--color-status-success);
|
|
38
|
+
border: 1px solid var(--color-status-success);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.ds-badge--warning {
|
|
42
|
+
background-color: var(--color-status-warning-bg);
|
|
43
|
+
color: var(--color-status-warning);
|
|
44
|
+
border: 1px solid var(--color-status-warning);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.ds-badge--error {
|
|
48
|
+
background-color: var(--color-status-error-bg);
|
|
49
|
+
color: var(--color-status-error);
|
|
50
|
+
border: 1px solid var(--color-status-error);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.ds-badge--accent {
|
|
54
|
+
background-color: var(--color-red-10);
|
|
55
|
+
color: var(--color-accent);
|
|
56
|
+
border: 1px solid var(--color-accent);
|
|
57
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './Badge.css';
|
|
3
|
+
|
|
4
|
+
export function Badge({
|
|
5
|
+
children,
|
|
6
|
+
variant = 'default',
|
|
7
|
+
size = 'medium',
|
|
8
|
+
role,
|
|
9
|
+
...props
|
|
10
|
+
}) {
|
|
11
|
+
const className = [
|
|
12
|
+
'ds-badge',
|
|
13
|
+
`ds-badge--${variant}`,
|
|
14
|
+
`ds-badge--${size}`,
|
|
15
|
+
].filter(Boolean).join(' ');
|
|
16
|
+
|
|
17
|
+
// Use role="status" for informational badges (info, success, warning, error)
|
|
18
|
+
const badgeRole = role || (['info', 'success', 'warning', 'error'].includes(variant) ? 'status' : undefined);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<span className={className} role={badgeRole} {...props}>
|
|
22
|
+
{children}
|
|
23
|
+
</span>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
.ds-button {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
gap: var(--space-xs);
|
|
5
|
+
font-size: var(--font-size-p1);
|
|
6
|
+
font-weight: 400;
|
|
7
|
+
font-family: inherit;
|
|
8
|
+
line-height: 1;
|
|
9
|
+
border: none;
|
|
10
|
+
cursor: pointer;
|
|
11
|
+
transition: background-color var(--transition-normal),
|
|
12
|
+
border-color var(--transition-normal),
|
|
13
|
+
opacity var(--transition-normal);
|
|
14
|
+
white-space: nowrap;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ds-button:disabled {
|
|
18
|
+
opacity: 0.5;
|
|
19
|
+
cursor: not-allowed;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.ds-button__icon {
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Variants */
|
|
29
|
+
.ds-button--primary {
|
|
30
|
+
color: var(--color-white);
|
|
31
|
+
background-color: var(--color-accent);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.ds-button--primary:hover:not(:disabled) {
|
|
35
|
+
background-color: var(--color-accent-hover);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.ds-button--secondary {
|
|
39
|
+
color: var(--color-txt-icon-1);
|
|
40
|
+
background-color: transparent;
|
|
41
|
+
border: 1px solid var(--color-border);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.ds-button--secondary:hover:not(:disabled) {
|
|
45
|
+
background-color: var(--color-item-bg-hover);
|
|
46
|
+
border-color: var(--color-border-hover);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.ds-button--ghost {
|
|
50
|
+
color: var(--color-txt-icon-2);
|
|
51
|
+
background-color: transparent;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.ds-button--ghost:hover:not(:disabled) {
|
|
55
|
+
background-color: var(--color-item-bg-hover);
|
|
56
|
+
color: var(--color-txt-icon-1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Sizes */
|
|
60
|
+
.ds-button--small {
|
|
61
|
+
height: calc(20px + var(--space-xs) * 2);
|
|
62
|
+
padding: 0 var(--space-s);
|
|
63
|
+
font-size: var(--font-size-p2);
|
|
64
|
+
border-radius: var(--radius-xs);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.ds-button--medium {
|
|
68
|
+
height: calc(24px + var(--space-s) * 2);
|
|
69
|
+
padding: 0 var(--space-s);
|
|
70
|
+
font-size: var(--font-size-p1);
|
|
71
|
+
border-radius: var(--radius-s);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.ds-button--large {
|
|
75
|
+
height: calc(28px + var(--space-m) * 2);
|
|
76
|
+
padding: 0 var(--space-m);
|
|
77
|
+
font-size: var(--font-size-h4);
|
|
78
|
+
border-radius: var(--radius-s);
|
|
79
|
+
gap: var(--space-s);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Full width */
|
|
83
|
+
.ds-button--full {
|
|
84
|
+
width: 100%;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Icon only */
|
|
89
|
+
.ds-button--icon-only {
|
|
90
|
+
aspect-ratio: 1;
|
|
91
|
+
justify-content: center;
|
|
92
|
+
padding-left: 0;
|
|
93
|
+
padding-right: 0;
|
|
94
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './Button.css';
|
|
3
|
+
|
|
4
|
+
export function Button({
|
|
5
|
+
children,
|
|
6
|
+
variant = 'primary',
|
|
7
|
+
size = 'medium',
|
|
8
|
+
fullWidth = false,
|
|
9
|
+
icon,
|
|
10
|
+
disabled = false,
|
|
11
|
+
onClick,
|
|
12
|
+
type = 'button',
|
|
13
|
+
'aria-label': ariaLabel,
|
|
14
|
+
...props
|
|
15
|
+
}) {
|
|
16
|
+
const isIconOnly = icon && !children;
|
|
17
|
+
|
|
18
|
+
const className = [
|
|
19
|
+
'ds-button',
|
|
20
|
+
`ds-button--${variant}`,
|
|
21
|
+
`ds-button--${size}`,
|
|
22
|
+
fullWidth && 'ds-button--full',
|
|
23
|
+
isIconOnly && 'ds-button--icon-only',
|
|
24
|
+
].filter(Boolean).join(' ');
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<button
|
|
28
|
+
type={type}
|
|
29
|
+
className={className}
|
|
30
|
+
disabled={disabled}
|
|
31
|
+
onClick={onClick}
|
|
32
|
+
aria-label={ariaLabel}
|
|
33
|
+
{...props}
|
|
34
|
+
>
|
|
35
|
+
{icon && !isIconOnly && <span className="ds-button__icon" aria-hidden="true">{icon}</span>}
|
|
36
|
+
{children}
|
|
37
|
+
{isIconOnly && <span className="ds-button__icon" aria-hidden="true">{icon}</span>}
|
|
38
|
+
</button>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
.ds-card {
|
|
2
|
+
background-color: transparent;
|
|
3
|
+
border-radius: var(--radius-s);
|
|
4
|
+
border: 1px solid var(--color-border);
|
|
5
|
+
transition: border-color var(--transition-normal), background-color var(--transition-normal);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.ds-card--interactive {
|
|
9
|
+
cursor: pointer;
|
|
10
|
+
background-color: var(--color-item-bg);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.ds-card--interactive:hover {
|
|
14
|
+
border-color: var(--color-border-hover);
|
|
15
|
+
background-color: var(--color-item-bg-hover);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.ds-card--none {
|
|
19
|
+
padding: 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.ds-card--small {
|
|
23
|
+
padding: var(--space-s);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.ds-card--medium {
|
|
27
|
+
padding: var(--space-m);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ds-card--large {
|
|
31
|
+
padding: var(--space-l);
|
|
32
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './Card.css';
|
|
3
|
+
|
|
4
|
+
export function Card({
|
|
5
|
+
children,
|
|
6
|
+
padding = 'medium',
|
|
7
|
+
variant = 'info',
|
|
8
|
+
hover = false, // deprecated, use variant="interactive"
|
|
9
|
+
onClick,
|
|
10
|
+
...props
|
|
11
|
+
}) {
|
|
12
|
+
const cardVariant = hover ? 'interactive' : variant;
|
|
13
|
+
const isInteractive = cardVariant === 'interactive' || onClick;
|
|
14
|
+
|
|
15
|
+
const className = [
|
|
16
|
+
'ds-card',
|
|
17
|
+
`ds-card--${padding}`,
|
|
18
|
+
isInteractive && 'ds-card--interactive',
|
|
19
|
+
].filter(Boolean).join(' ');
|
|
20
|
+
|
|
21
|
+
const Element = isInteractive && onClick ? 'button' : 'div';
|
|
22
|
+
const interactiveProps = isInteractive && onClick ? {
|
|
23
|
+
type: 'button',
|
|
24
|
+
onClick,
|
|
25
|
+
} : {};
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Element
|
|
29
|
+
className={className}
|
|
30
|
+
role={isInteractive && !onClick ? 'article' : undefined}
|
|
31
|
+
{...interactiveProps}
|
|
32
|
+
{...props}
|
|
33
|
+
>
|
|
34
|
+
{children}
|
|
35
|
+
</Element>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
.ds-code-inline {
|
|
2
|
+
font-family: 'Fira Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
|
|
3
|
+
font-size: 0.9em;
|
|
4
|
+
background-color: var(--color-code-bg);
|
|
5
|
+
color: var(--color-txt-icon-1);
|
|
6
|
+
padding: 2px 6px;
|
|
7
|
+
border-radius: var(--radius-s);
|
|
8
|
+
white-space: nowrap;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.ds-code-block {
|
|
12
|
+
font-family: 'Fira Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
|
|
13
|
+
font-size: var(--font-size-p2);
|
|
14
|
+
background-color: var(--color-code-bg);
|
|
15
|
+
color: var(--color-txt-icon-1);
|
|
16
|
+
padding: var(--space-s);
|
|
17
|
+
border-radius: var(--radius-s);
|
|
18
|
+
overflow-x: auto;
|
|
19
|
+
line-height: 1.6;
|
|
20
|
+
margin: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.ds-code-block code {
|
|
24
|
+
background: none;
|
|
25
|
+
border: none;
|
|
26
|
+
padding: 0;
|
|
27
|
+
font-family: inherit;
|
|
28
|
+
font-size: inherit;
|
|
29
|
+
color: inherit;
|
|
30
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { CodeAccordion } from './CodeAccordion';
|
|
3
|
+
import './Code.css';
|
|
4
|
+
|
|
5
|
+
export function Code({ children, block = false, collapsible = false, title = 'Code', defaultExpanded = false, ...props }) {
|
|
6
|
+
if (block) {
|
|
7
|
+
if (collapsible) {
|
|
8
|
+
return (
|
|
9
|
+
<CodeAccordion title={title} defaultExpanded={defaultExpanded} {...props}>
|
|
10
|
+
{children}
|
|
11
|
+
</CodeAccordion>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<pre className="ds-code-block" {...props}>
|
|
17
|
+
<code>{children}</code>
|
|
18
|
+
</pre>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<code className="ds-code-inline" {...props}>
|
|
24
|
+
{children}
|
|
25
|
+
</code>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
.ds-code-accordion {
|
|
2
|
+
border: 1px solid var(--color-border);
|
|
3
|
+
border-radius: var(--radius-s);
|
|
4
|
+
overflow: hidden;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.ds-code-accordion__header {
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: space-between;
|
|
11
|
+
width: 100%;
|
|
12
|
+
padding: var(--space-xs);
|
|
13
|
+
background-color: var(--color-item-bg);
|
|
14
|
+
border: none;
|
|
15
|
+
color: var(--color-txt-icon-1);
|
|
16
|
+
font-size: var(--font-size-p1);
|
|
17
|
+
font-family: inherit;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
transition: background-color var(--transition-normal);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.ds-code-accordion__header:hover {
|
|
23
|
+
background-color: var(--color-item-bg-hover);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.ds-code-accordion__title {
|
|
27
|
+
font-weight: 400;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ds-code-accordion__icon {
|
|
31
|
+
flex-shrink: 0;
|
|
32
|
+
color: var(--color-txt-icon-2);
|
|
33
|
+
transition: transform var(--transition-normal);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.ds-code-accordion__icon--expanded {
|
|
37
|
+
transform: rotate(180deg);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.ds-code-accordion__content {
|
|
41
|
+
font-family: 'Fira Mono', 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
|
|
42
|
+
font-size: var(--font-size-p2);
|
|
43
|
+
background-color: var(--color-code-bg);
|
|
44
|
+
color: var(--color-txt-icon-1);
|
|
45
|
+
padding: var(--space-xs);
|
|
46
|
+
border-top: 1px solid var(--color-border);
|
|
47
|
+
overflow-x: auto;
|
|
48
|
+
line-height: 1.6;
|
|
49
|
+
margin: 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.ds-code-accordion__content code {
|
|
53
|
+
background: none;
|
|
54
|
+
border: none;
|
|
55
|
+
padding: 0;
|
|
56
|
+
font-family: inherit;
|
|
57
|
+
font-size: inherit;
|
|
58
|
+
color: inherit;
|
|
59
|
+
}
|