@drivenets/design-system 0.17.0 → 0.18.1
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/CHANGELOG.md +24 -0
- package/dist/index.cjs +1797 -805
- package/dist/index.d.cts +117 -53
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +117 -53
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1799 -809
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +3 -3
- package/src/components/ds-alert-banner/ds-alert-banner-global.figma.ts +49 -0
- package/src/components/ds-alert-banner/ds-alert-banner.figma.ts +51 -0
- package/src/components/ds-autocomplete/ds-autocomplete.module.scss +15 -4
- package/src/components/ds-autocomplete/ds-autocomplete.tsx +10 -3
- package/src/components/ds-autocomplete/ds-autocomplete.types.ts +8 -0
- package/src/components/ds-button-v3/ds-button-v3.figma.ts +5 -3
- package/src/components/ds-button-v3/ds-button-v3.module.scss +84 -17
- package/src/components/ds-button-v3/ds-button-v3.tsx +2 -0
- package/src/components/ds-button-v3/ds-button-v3.types.ts +11 -2
- package/src/components/ds-button-v3/ds-button-v4.figma.ts +121 -0
- package/src/components/ds-comment-bubble/ds-comment-bubble.figma.ts +52 -0
- package/src/components/ds-comment-card/ds-comment-card.figma.ts +36 -0
- package/src/components/ds-comment-indicator/ds-comment-indicator.figma.ts +32 -0
- package/src/components/ds-comments-drawer/ds-comments-drawer.figma.ts +19 -0
- package/src/components/ds-select/ds-select.figma.ts +2 -1
- package/src/components/ds-select/ds-select.tsx +6 -1
- package/src/components/ds-select/ds-select.types.ts +2 -1
- package/src/components/ds-slider/ds-slider.figma.ts +29 -0
- package/src/components/ds-slider/ds-slider.module.scss +104 -0
- package/src/components/ds-slider/ds-slider.tsx +118 -0
- package/src/components/ds-slider/ds-slider.types.ts +102 -0
- package/src/components/ds-slider/ds-slider.utils.ts +14 -0
- package/src/components/ds-slider/index.ts +11 -0
- package/src/components/ds-smart-tabs/figma/ds-smart-tabs-tab.figma.ts +83 -0
- package/src/components/ds-smart-tabs/figma/ds-smart-tabs.figma.ts +23 -0
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.module.scss +5 -1
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.tsx +15 -3
- package/src/components/ds-table/components/ds-table-header/ds-table-header.module.scss +15 -1
- package/src/components/ds-table/components/ds-table-header/ds-table-header.tsx +29 -6
- package/src/components/ds-table/components/ds-table-resize-handle/ds-table-resize-handle.module.scss +23 -0
- package/src/components/ds-table/components/ds-table-resize-handle/ds-table-resize-handle.tsx +218 -0
- package/src/components/ds-table/components/ds-table-resize-handle/ds-table-resize-handle.types.ts +14 -0
- package/src/components/ds-table/components/ds-table-resize-handle/index.ts +1 -0
- package/src/components/ds-table/components/ds-table-resize-overlay/ds-table-resize-overlay.module.scss +18 -0
- package/src/components/ds-table/components/ds-table-resize-overlay/ds-table-resize-overlay.tsx +16 -0
- package/src/components/ds-table/components/ds-table-resize-overlay/ds-table-resize-overlay.types.ts +13 -0
- package/src/components/ds-table/components/ds-table-resize-overlay/index.ts +1 -0
- package/src/components/ds-table/components/ds-table-row/ds-table-row.module.scss +1 -1
- package/src/components/ds-table/components/ds-table-row/ds-table-row.tsx +9 -2
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.module.scss +2 -1
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.tsx +9 -2
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-checkbox.tsx +2 -2
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-date.tsx +2 -1
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-number.tsx +2 -1
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-select.tsx +2 -1
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-text.tsx +2 -1
- package/src/components/ds-table/components/edit/ds-table-editing-cell/ds-table-editing-cell.tsx +12 -3
- package/src/components/ds-table/context/ds-table-context.tsx +208 -0
- package/src/components/ds-table/ds-table-defaults.ts +42 -0
- package/src/components/ds-table/ds-table.module.scss +4 -1
- package/src/components/ds-table/ds-table.tsx +139 -214
- package/src/components/ds-table/ds-table.types.ts +53 -47
- package/src/components/ds-table/grouping/utils/column-group.ts +7 -5
- package/src/components/ds-table/hooks/use-cell-editor.ts +5 -1
- package/src/components/ds-table/hooks/use-column-resize.ts +385 -0
- package/src/components/ds-table/hooks/use-editing-state.ts +190 -0
- package/src/components/ds-table/index.ts +1 -0
- package/src/components/ds-table/styles/_variables.scss +2 -1
- package/src/components/ds-table/utils/column-size-meta.augmentation.ts +16 -0
- package/src/components/ds-table/utils/column-size.ts +213 -10
- package/src/components/ds-table/utils/column-size.unit.test.ts +213 -0
- package/src/components/ds-table/utils/constants.ts +28 -0
- package/src/components/ds-table/utils/frozen-body.ts +33 -0
- package/src/components/ds-table/utils/frozen-body.unit.test.ts +44 -0
- package/src/components/ds-table/utils/table-api.ts +42 -0
- package/src/components/ds-table/utils/table-api.unit.test.ts +82 -0
- package/src/components/ds-table/utils/table-columns.tsx +119 -0
- package/src/components/ds-table/utils/table-columns.unit.test.ts +199 -0
- package/src/components/ds-tag/ds-tag.figma.ts +51 -0
- package/src/components/ds-tag-filter/ds-tag-filter.figma.ts +16 -0
- package/src/components/ds-tag-filter/ds-tag-filter.module.scss +7 -35
- package/src/components/ds-tag-filter/ds-tag-filter.tsx +34 -57
- package/src/components/ds-tag-filter/ds-tag-filter.types.ts +2 -1
- package/src/components/ds-tag-filter/hooks/use-tag-overflow-calculation.ts +13 -18
- package/src/components/ds-text-input/ds-input-field-v02.figma.ts +29 -4
- package/src/components/ds-text-input/ds-text-input.figma.ts +3 -2
- package/src/components/ds-text-input/ds-text-input.tsx +1 -0
- package/src/components/ds-text-input/ds-text-input.types.ts +1 -1
- package/src/components/ds-tree/ds-tree.figma.ts +54 -0
- package/src/components/ds-workspace-layout/ds-workspace-layout.figma.ts +99 -0
- package/src/components/ds-workspace-layout/ds-workspace-layout.module.scss +1 -8
- package/src/index.ts +1 -0
- package/src/styles/_gradients.scss +19 -0
- package/src/styles/_root.scss +39 -15
- package/src/styles/_typography.scss +1 -0
- package/src/styles/shared/_input.scss +10 -0
- package/src/styles/styles.scss +1 -0
- package/src/components/ds-table/context/ds-table-context.ts +0 -112
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drivenets/design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.cts",
|
|
@@ -106,8 +106,8 @@
|
|
|
106
106
|
"vitest": "^4.1.10",
|
|
107
107
|
"vitest-browser-react": "^2.1.0",
|
|
108
108
|
"zod": "^4.4.3",
|
|
109
|
-
"@drivenets/
|
|
110
|
-
"@drivenets/
|
|
109
|
+
"@drivenets/vite-plugin-design-system": "0.0.11",
|
|
110
|
+
"@drivenets/eslint-plugin-internal": "0.0.0"
|
|
111
111
|
},
|
|
112
112
|
"scripts": {
|
|
113
113
|
"start": "storybook dev -p 6006",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=15271-7357
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-alert-banner
|
|
3
|
+
// component=DsAlertBanner
|
|
4
|
+
//
|
|
5
|
+
// `DsAlertBannerGlobalV1` is the full-width bar pinned to the top of the viewport. It
|
|
6
|
+
// maps to the same `DsAlertBanner` as the inline card but without `inline` (the
|
|
7
|
+
// default `global` layout) and with no title. See `ds-alert-banner.figma.ts` for the
|
|
8
|
+
// inline variant.
|
|
9
|
+
import figma from 'figma';
|
|
10
|
+
|
|
11
|
+
const instance = figma.selectedInstance;
|
|
12
|
+
|
|
13
|
+
const variant = instance.getEnum('Type', {
|
|
14
|
+
'info neutral': 'info-neutral',
|
|
15
|
+
'info blue': 'info-blue',
|
|
16
|
+
warning: 'warning',
|
|
17
|
+
error: 'error',
|
|
18
|
+
success: 'success',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// The status icon is set automatically by `Type` in Figma; mirror that mapping so the
|
|
22
|
+
// snippet passes the matching `DsIcon` name.
|
|
23
|
+
const icon = instance.getEnum('Type', {
|
|
24
|
+
'info neutral': 'info',
|
|
25
|
+
'info blue': 'info',
|
|
26
|
+
warning: 'warning',
|
|
27
|
+
error: 'error',
|
|
28
|
+
success: 'check_circle',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const closable = instance.getBoolean('Show Dismiss Button');
|
|
32
|
+
const showActions = instance.getBoolean('Show Actions');
|
|
33
|
+
|
|
34
|
+
const closableAttr = closable ? ' closable' : '';
|
|
35
|
+
const actionsBlock = showActions
|
|
36
|
+
? `\n\t<DsAlertBanner.Actions>\n\t\t<DsButtonV3 variant="secondary" size="small">Action</DsButtonV3>\n\t</DsAlertBanner.Actions>`
|
|
37
|
+
: '';
|
|
38
|
+
|
|
39
|
+
export default {
|
|
40
|
+
example: figma.code`<DsAlertBanner open onOpenChange={() => {}} variant="${variant}" icon="${icon}"${closableAttr}>
|
|
41
|
+
<DsAlertBanner.Body>Description</DsAlertBanner.Body>${actionsBlock}
|
|
42
|
+
</DsAlertBanner>`,
|
|
43
|
+
imports: [
|
|
44
|
+
"import { DsAlertBanner } from '@drivenets/design-system';",
|
|
45
|
+
"import { DsButtonV3 } from '@drivenets/design-system';",
|
|
46
|
+
],
|
|
47
|
+
id: 'ds-alert-banner-global',
|
|
48
|
+
metadata: { nestable: false },
|
|
49
|
+
} satisfies figma.Template;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=14850-7088
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-alert-banner
|
|
3
|
+
// component=DsAlertBanner
|
|
4
|
+
//
|
|
5
|
+
// `DsAlertBannerInlineV1` is the inline (bordered card) banner that sits in normal
|
|
6
|
+
// document flow. It maps to the controlled `DsAlertBanner` with `inline`. The
|
|
7
|
+
// full-width, top-of-viewport `DsAlertBannerGlobalV1` maps to the same component
|
|
8
|
+
// without `inline` — see `ds-alert-banner-global.figma.ts`.
|
|
9
|
+
import figma from 'figma';
|
|
10
|
+
|
|
11
|
+
const instance = figma.selectedInstance;
|
|
12
|
+
|
|
13
|
+
const variant = instance.getEnum('Type', {
|
|
14
|
+
'Info Neutral': 'info-neutral',
|
|
15
|
+
'Info Blue': 'info-blue',
|
|
16
|
+
Warning: 'warning',
|
|
17
|
+
Error: 'error',
|
|
18
|
+
Success: 'success',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// The status icon is set automatically by `Type` in Figma; mirror that mapping so the
|
|
22
|
+
// snippet passes the matching `DsIcon` name.
|
|
23
|
+
const icon = instance.getEnum('Type', {
|
|
24
|
+
'Info Neutral': 'info',
|
|
25
|
+
'Info Blue': 'info',
|
|
26
|
+
Warning: 'warning',
|
|
27
|
+
Error: 'error',
|
|
28
|
+
Success: 'check_circle',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const closable = instance.getBoolean('Show Dismiss Button');
|
|
32
|
+
const showTitle = instance.getBoolean('Show Titles');
|
|
33
|
+
const showActions = instance.getBoolean('Show Actions');
|
|
34
|
+
|
|
35
|
+
const closableAttr = closable ? ' closable' : '';
|
|
36
|
+
const titleLine = showTitle ? `\n\t<DsAlertBanner.Title>Title</DsAlertBanner.Title>` : '';
|
|
37
|
+
const actionsBlock = showActions
|
|
38
|
+
? `\n\t<DsAlertBanner.Actions>\n\t\t<DsButtonV3 variant="secondary" size="small">Action</DsButtonV3>\n\t</DsAlertBanner.Actions>`
|
|
39
|
+
: '';
|
|
40
|
+
|
|
41
|
+
export default {
|
|
42
|
+
example: figma.code`<DsAlertBanner open onOpenChange={() => {}} inline variant="${variant}" icon="${icon}"${closableAttr}>${titleLine}
|
|
43
|
+
<DsAlertBanner.Body>Description</DsAlertBanner.Body>${actionsBlock}
|
|
44
|
+
</DsAlertBanner>`,
|
|
45
|
+
imports: [
|
|
46
|
+
"import { DsAlertBanner } from '@drivenets/design-system';",
|
|
47
|
+
"import { DsButtonV3 } from '@drivenets/design-system';",
|
|
48
|
+
],
|
|
49
|
+
id: 'ds-alert-banner',
|
|
50
|
+
metadata: { nestable: false },
|
|
51
|
+
} satisfies figma.Template;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
@use '../../styles/shared/dropdown';
|
|
2
2
|
@use '../../styles/shared/input';
|
|
3
3
|
|
|
4
|
-
$autocomplete-input-height: 36px;
|
|
5
4
|
$autocomplete-max-visible-items: 4;
|
|
6
5
|
$autocomplete-item-height: 38px;
|
|
7
6
|
$autocomplete-dropdown-max-height: calc($autocomplete-max-visible-items * $autocomplete-item-height);
|
|
@@ -29,9 +28,21 @@ $autocomplete-opacity-visible: 1;
|
|
|
29
28
|
display: flex;
|
|
30
29
|
align-items: center;
|
|
31
30
|
gap: var(--3xs);
|
|
32
|
-
height:
|
|
33
|
-
min-height:
|
|
34
|
-
max-height:
|
|
31
|
+
height: input.$input-text-height-default;
|
|
32
|
+
min-height: input.$input-text-height-default;
|
|
33
|
+
max-height: input.$input-text-height-default;
|
|
34
|
+
|
|
35
|
+
&.small {
|
|
36
|
+
height: input.$input-text-height-small;
|
|
37
|
+
min-height: input.$input-text-height-small;
|
|
38
|
+
max-height: input.$input-text-height-small;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&.large {
|
|
42
|
+
height: input.$input-text-height-large;
|
|
43
|
+
min-height: input.$input-text-height-large;
|
|
44
|
+
max-height: input.$input-text-height-large;
|
|
45
|
+
}
|
|
35
46
|
|
|
36
47
|
&[data-focus] {
|
|
37
48
|
border-color: var(--form-control-border-color, var(--border-action-primary)) !important;
|
|
@@ -12,6 +12,7 @@ export const DsAutocomplete = ({
|
|
|
12
12
|
id,
|
|
13
13
|
options = [],
|
|
14
14
|
loading = false,
|
|
15
|
+
size = 'default',
|
|
15
16
|
style,
|
|
16
17
|
className,
|
|
17
18
|
placeholder = 'Start typing to search...',
|
|
@@ -74,7 +75,13 @@ export const DsAutocomplete = ({
|
|
|
74
75
|
onOpenChange={handleOpenChange}
|
|
75
76
|
closeOnSelect
|
|
76
77
|
>
|
|
77
|
-
<Combobox.Control
|
|
78
|
+
<Combobox.Control
|
|
79
|
+
className={classNames(
|
|
80
|
+
styles.control,
|
|
81
|
+
size === 'small' && styles.small,
|
|
82
|
+
size === 'large' && styles.large,
|
|
83
|
+
)}
|
|
84
|
+
>
|
|
78
85
|
{startAdornment && <span className={styles.startAdornment}>{startAdornment}</span>}
|
|
79
86
|
|
|
80
87
|
<Combobox.Input className={styles.input} placeholder={placeholder} />
|
|
@@ -92,13 +99,13 @@ export const DsAutocomplete = ({
|
|
|
92
99
|
combobox.setInputValue('');
|
|
93
100
|
}}
|
|
94
101
|
>
|
|
95
|
-
<DsIcon icon="close" size=
|
|
102
|
+
<DsIcon icon="close" size={size === 'small' ? 'small' : 'medium'} />
|
|
96
103
|
</button>
|
|
97
104
|
)}
|
|
98
105
|
|
|
99
106
|
{showTrigger && (
|
|
100
107
|
<Combobox.Trigger className={styles.trigger} aria-label="Toggle dropdown">
|
|
101
|
-
<DsIcon icon="keyboard_arrow_down" size=
|
|
108
|
+
<DsIcon icon="keyboard_arrow_down" size={size === 'small' ? 'small' : 'medium'} />
|
|
102
109
|
</Combobox.Trigger>
|
|
103
110
|
)}
|
|
104
111
|
</div>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import type { IconName } from '../ds-icon';
|
|
3
3
|
|
|
4
|
+
export const autocompleteSizes = ['small', 'default', 'large'] as const;
|
|
5
|
+
export type AutocompleteSize = (typeof autocompleteSizes)[number];
|
|
6
|
+
|
|
4
7
|
export interface DsAutocompleteOption {
|
|
5
8
|
/**
|
|
6
9
|
* Label to display in the autocomplete dropdown
|
|
@@ -31,6 +34,11 @@ export interface DsAutocompleteProps {
|
|
|
31
34
|
* When true, a loading message is shown in the dropdown.
|
|
32
35
|
*/
|
|
33
36
|
loading?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* The size of the autocomplete control
|
|
39
|
+
* @default 'default'
|
|
40
|
+
*/
|
|
41
|
+
size?: AutocompleteSize;
|
|
34
42
|
|
|
35
43
|
/**
|
|
36
44
|
* Additional styles to apply to the component
|
|
@@ -7,6 +7,7 @@ const instance = figma.selectedInstance;
|
|
|
7
7
|
|
|
8
8
|
const variant = instance.getEnum('buttonType', {
|
|
9
9
|
primary: 'primary',
|
|
10
|
+
'primary-subtle': 'primary-subtle',
|
|
10
11
|
secondary: 'secondary',
|
|
11
12
|
tertiary: 'tertiary',
|
|
12
13
|
});
|
|
@@ -86,13 +87,14 @@ const labelNode = instance.findText('Button', { traverseInstances: true });
|
|
|
86
87
|
const label = labelNode.type === 'TEXT' ? labelNode.textContent : 'Button';
|
|
87
88
|
|
|
88
89
|
const iconProp = icon ? figma.code` icon="${icon}"` : '';
|
|
90
|
+
const disabledProp = disabled ? ' disabled' : '';
|
|
89
91
|
|
|
90
92
|
export default {
|
|
91
93
|
example: iconOnly
|
|
92
|
-
? figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}"
|
|
94
|
+
? figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}"${disabledProp}${iconProp} aria-label="${label}" />`
|
|
93
95
|
: showIcon && icon
|
|
94
|
-
? figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}"
|
|
95
|
-
: figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}"
|
|
96
|
+
? figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}"${disabledProp} icon="${icon}">${label}</DsButtonV3>`
|
|
97
|
+
: figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}"${disabledProp}>${label}</DsButtonV3>`,
|
|
96
98
|
imports: ["import { DsButtonV3 } from '@drivenets/design-system';"],
|
|
97
99
|
id: 'ds-button-v3',
|
|
98
100
|
metadata: { nestable: true },
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
$height-large: 40px;
|
|
4
4
|
$height-medium: 36px;
|
|
5
5
|
$height-small: 28px;
|
|
6
|
-
$border-radius:
|
|
6
|
+
$border-radius: var(--3xs);
|
|
7
|
+
$border-radius-high-emphasis: var(--sm);
|
|
7
8
|
$focus-ring-width: 2px;
|
|
8
9
|
|
|
9
10
|
@mixin focus-ring($outer-color) {
|
|
@@ -34,6 +35,10 @@ $focus-ring-width: 2px;
|
|
|
34
35
|
cursor: not-allowed;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
&[data-high-emphasis] {
|
|
39
|
+
border-radius: $border-radius-high-emphasis;
|
|
40
|
+
}
|
|
41
|
+
|
|
37
42
|
&[data-loading] {
|
|
38
43
|
cursor: default;
|
|
39
44
|
pointer-events: none;
|
|
@@ -126,6 +131,37 @@ $focus-ring-width: 2px;
|
|
|
126
131
|
}
|
|
127
132
|
}
|
|
128
133
|
|
|
134
|
+
.root[data-color='default'][data-variant='primary-subtle'] {
|
|
135
|
+
background-color: var(--background-primary-subtle);
|
|
136
|
+
color: var(--font-action);
|
|
137
|
+
border-color: var(--border-action-primary);
|
|
138
|
+
|
|
139
|
+
&:hover:not(:disabled):not(:active):not([data-selected='true']) {
|
|
140
|
+
background-color: var(--background-primary-subtle-hover);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
&:active:not(:disabled) {
|
|
144
|
+
background-color: var(--background-primary-subtle-active);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
&:focus-visible {
|
|
148
|
+
@include focus-ring(var(--border-action-primary));
|
|
149
|
+
|
|
150
|
+
background-color: var(--background-primary-subtle-hover);
|
|
151
|
+
border-color: var(--border-inverse);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
&[data-selected='true'] {
|
|
155
|
+
background-color: var(--background-primary-subtle-active);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
&:disabled:not([data-loading]) {
|
|
159
|
+
background-color: var(--background-primary-subtle-disabled);
|
|
160
|
+
color: var(--font-disabled);
|
|
161
|
+
border-color: var(--border-disabled);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
129
165
|
.root[data-color='default'][data-variant='secondary'] {
|
|
130
166
|
background-color: var(--background-action-secondary);
|
|
131
167
|
color: var(--font-main);
|
|
@@ -228,19 +264,50 @@ $focus-ring-width: 2px;
|
|
|
228
264
|
}
|
|
229
265
|
}
|
|
230
266
|
|
|
267
|
+
.root[data-color='error'][data-variant='primary-subtle'] {
|
|
268
|
+
background-color: var(--background-error-subtle);
|
|
269
|
+
color: var(--font-error);
|
|
270
|
+
border-color: var(--border-error);
|
|
271
|
+
|
|
272
|
+
&:hover:not(:disabled):not(:active):not([data-selected='true']) {
|
|
273
|
+
background-color: var(--background-error-subtle-hover);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
&:active:not(:disabled) {
|
|
277
|
+
background-color: var(--background-error-subtle-active);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
&:focus-visible {
|
|
281
|
+
@include focus-ring(var(--border-error));
|
|
282
|
+
|
|
283
|
+
background-color: var(--background-error-subtle-hover);
|
|
284
|
+
border-color: var(--border-inverse);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
&[data-selected='true'] {
|
|
288
|
+
background-color: var(--background-error-subtle-active);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
&:disabled:not([data-loading]) {
|
|
292
|
+
background-color: var(--background-error-subtle-disabled);
|
|
293
|
+
color: var(--font-disabled);
|
|
294
|
+
border-color: var(--border-disabled);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
231
298
|
.root[data-color='error'][data-variant='secondary'] {
|
|
232
299
|
background-color: var(--background-action-secondary);
|
|
233
300
|
color: var(--font-error);
|
|
234
|
-
border-color: var(--border-error);
|
|
301
|
+
border-color: var(--border-error-weak);
|
|
235
302
|
|
|
236
303
|
&:hover:not(:disabled):not(:active):not([data-selected='true']) {
|
|
237
304
|
background-color: var(--background-error-secondary-hover);
|
|
238
|
-
border-color: var(--border-error-
|
|
305
|
+
border-color: var(--border-error-medium);
|
|
239
306
|
}
|
|
240
307
|
|
|
241
308
|
&:active:not(:disabled) {
|
|
242
|
-
background-color: var(--background-error-secondary-
|
|
243
|
-
border-color: var(--border-error-
|
|
309
|
+
background-color: var(--background-error-secondary-active);
|
|
310
|
+
border-color: var(--border-error-medium);
|
|
244
311
|
}
|
|
245
312
|
|
|
246
313
|
&:focus-visible {
|
|
@@ -251,8 +318,8 @@ $focus-ring-width: 2px;
|
|
|
251
318
|
}
|
|
252
319
|
|
|
253
320
|
&[data-selected='true'] {
|
|
254
|
-
background-color: var(--background-error-secondary-
|
|
255
|
-
border-color: var(--border-error-
|
|
321
|
+
background-color: var(--background-error-secondary-active);
|
|
322
|
+
border-color: var(--border-error-medium);
|
|
256
323
|
}
|
|
257
324
|
|
|
258
325
|
&:disabled:not([data-loading]) {
|
|
@@ -293,32 +360,32 @@ $focus-ring-width: 2px;
|
|
|
293
360
|
}
|
|
294
361
|
|
|
295
362
|
.root[data-color='light'][data-variant='primary'] {
|
|
296
|
-
background-color: var(--background-light-
|
|
363
|
+
background-color: var(--background-light-subtle);
|
|
297
364
|
color: var(--font-on-action);
|
|
298
|
-
border-color:
|
|
365
|
+
border-color: var(--border-inverse);
|
|
299
366
|
|
|
300
367
|
&:hover:not(:disabled):not(:active):not([data-selected='true']) {
|
|
301
|
-
background-color: var(--background-light-
|
|
368
|
+
background-color: var(--background-light-hover);
|
|
302
369
|
}
|
|
303
370
|
|
|
304
371
|
&:active:not(:disabled) {
|
|
305
|
-
background-color: var(--background-light-
|
|
372
|
+
background-color: var(--background-light-active);
|
|
306
373
|
}
|
|
307
374
|
|
|
308
375
|
&:focus-visible {
|
|
309
|
-
@include focus-ring(var(--
|
|
376
|
+
@include focus-ring(var(--border-action-primary));
|
|
310
377
|
|
|
311
|
-
background-color: var(--background-light-
|
|
312
|
-
border-color: var(--border-action-secondary);
|
|
378
|
+
background-color: var(--background-light-hover);
|
|
313
379
|
}
|
|
314
380
|
|
|
315
381
|
&[data-selected='true'] {
|
|
316
|
-
background-color: var(--background-light-
|
|
382
|
+
background-color: var(--background-light-active);
|
|
317
383
|
}
|
|
318
384
|
|
|
319
385
|
&:disabled:not([data-loading]) {
|
|
320
|
-
background-color:
|
|
321
|
-
color: var(--font-
|
|
386
|
+
background-color: transparent;
|
|
387
|
+
color: var(--font-disabled);
|
|
388
|
+
border-color: var(--border-disabled);
|
|
322
389
|
}
|
|
323
390
|
}
|
|
324
391
|
|
|
@@ -29,6 +29,7 @@ const DsButtonV3 = ({
|
|
|
29
29
|
variant = 'primary',
|
|
30
30
|
size = 'medium',
|
|
31
31
|
selected = false,
|
|
32
|
+
highEmphasis = false,
|
|
32
33
|
type = 'button',
|
|
33
34
|
...rest
|
|
34
35
|
}: DsButtonV3BaseProps) => {
|
|
@@ -48,6 +49,7 @@ const DsButtonV3 = ({
|
|
|
48
49
|
data-variant={variant}
|
|
49
50
|
data-size={size}
|
|
50
51
|
data-selected={selected ? 'true' : undefined}
|
|
52
|
+
data-high-emphasis={highEmphasis ? 'true' : undefined}
|
|
51
53
|
data-icon-only={isIconOnly || undefined}
|
|
52
54
|
data-loading={loading && !disabled ? '' : undefined}
|
|
53
55
|
{...rest}
|
|
@@ -2,7 +2,7 @@ import type { ButtonHTMLAttributes, Ref } from 'react';
|
|
|
2
2
|
import type { IconType } from '../ds-icon';
|
|
3
3
|
import type { ResponsiveValue } from '../../utils/responsive';
|
|
4
4
|
|
|
5
|
-
export const buttonV3Variants = ['primary', 'secondary', 'tertiary'] as const;
|
|
5
|
+
export const buttonV3Variants = ['primary', 'primary-subtle', 'secondary', 'tertiary'] as const;
|
|
6
6
|
export type ButtonV3Variant = (typeof buttonV3Variants)[number];
|
|
7
7
|
|
|
8
8
|
export const buttonV3Colors = ['default', 'error', 'light'] as const;
|
|
@@ -24,7 +24,8 @@ export interface DsButtonV3BaseProps extends ButtonHTMLAttributes<HTMLButtonElem
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Visual variant of the button:
|
|
27
|
-
* - `primary` —
|
|
27
|
+
* - `primary` — highest-emphasis action; filled for `default`/`error`, subtle outline for `color="light"`
|
|
28
|
+
* - `primary-subtle` — subtle-filled, colored border and text (emphasis outline); `default`/`error` only
|
|
28
29
|
* - `secondary` — outlined, medium-emphasis action
|
|
29
30
|
* - `tertiary` — borderless, low-emphasis action (text-like)
|
|
30
31
|
* @default 'primary'
|
|
@@ -44,6 +45,14 @@ export interface DsButtonV3BaseProps extends ButtonHTMLAttributes<HTMLButtonElem
|
|
|
44
45
|
*/
|
|
45
46
|
selected?: boolean;
|
|
46
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Raises the corner radius for high-emphasis surfaces such as
|
|
50
|
+
* Sign in, Landing, and NetGen. Purely a rounding change — does not affect
|
|
51
|
+
* color or priority.
|
|
52
|
+
* @default false
|
|
53
|
+
*/
|
|
54
|
+
highEmphasis?: boolean;
|
|
55
|
+
|
|
47
56
|
/**
|
|
48
57
|
* Leading icon. When set without children, renders as icon-only (square) layout.
|
|
49
58
|
*/
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=39666-40247
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-button-v3
|
|
3
|
+
// component=DsButtonV3
|
|
4
|
+
import figma from 'figma';
|
|
5
|
+
|
|
6
|
+
// Figma ships several button generations; the `DsButtonV4` component set maps onto the
|
|
7
|
+
// same code component as `DsButtonV3` (see ds-button-v3.figma.ts for the older set).
|
|
8
|
+
const instance = figma.selectedInstance;
|
|
9
|
+
|
|
10
|
+
const variant = instance.getEnum('variant', {
|
|
11
|
+
primary: 'primary',
|
|
12
|
+
'primary-subtle': 'primary-subtle',
|
|
13
|
+
secondary: 'secondary',
|
|
14
|
+
tertiary: 'tertiary',
|
|
15
|
+
});
|
|
16
|
+
const color = instance.getEnum('color', {
|
|
17
|
+
default: 'default',
|
|
18
|
+
error: 'error',
|
|
19
|
+
light: 'light',
|
|
20
|
+
});
|
|
21
|
+
const state = instance.getEnum('state', {
|
|
22
|
+
default: 'default',
|
|
23
|
+
hover: 'hover',
|
|
24
|
+
focus: 'focus',
|
|
25
|
+
active: 'active',
|
|
26
|
+
disabled: 'disabled',
|
|
27
|
+
isLoading: 'isLoading',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const disabled = state === 'disabled';
|
|
31
|
+
const loading = state === 'isLoading';
|
|
32
|
+
|
|
33
|
+
const structure = instance.findInstance('Part_ButtonStructureV2', { traverseInstances: true });
|
|
34
|
+
|
|
35
|
+
const size =
|
|
36
|
+
structure.type === 'INSTANCE'
|
|
37
|
+
? (structure.getEnum('size', {
|
|
38
|
+
large: 'large',
|
|
39
|
+
medium: 'medium',
|
|
40
|
+
small: 'small',
|
|
41
|
+
tiny: 'tiny',
|
|
42
|
+
}) ?? 'medium')
|
|
43
|
+
: 'medium';
|
|
44
|
+
|
|
45
|
+
const iconOnly =
|
|
46
|
+
structure.type === 'INSTANCE' ? structure.getEnum('icon-only', { True: true, False: false }) : false;
|
|
47
|
+
|
|
48
|
+
const highEmphasis =
|
|
49
|
+
structure.type === 'INSTANCE' ? structure.getEnum('high-emphasis', { true: true, false: false }) : false;
|
|
50
|
+
|
|
51
|
+
const showIcon = structure.type === 'INSTANCE' ? structure.getBoolean('isIconBefore') : false;
|
|
52
|
+
|
|
53
|
+
// `DsButtonV3.icon` is an icon-name string. Swapped icons keep the placeholder layer
|
|
54
|
+
// name (e.g. `DAP_GM_O_check_circle`), so resolve via Code Connect ID or metadata.
|
|
55
|
+
const toIconName = (name: string): string =>
|
|
56
|
+
name
|
|
57
|
+
.replace(/^DAP_DAP_/, 'DAP_')
|
|
58
|
+
.replace(/^DAP_GM_[OS]_/, '')
|
|
59
|
+
.replace(/^DAP_outline_icon\//, '')
|
|
60
|
+
.replace(/^DAP_/, '')
|
|
61
|
+
.replace(/^\/+/, '')
|
|
62
|
+
.replace(/[\s/]+/g, '_')
|
|
63
|
+
.toLowerCase();
|
|
64
|
+
|
|
65
|
+
const iconNameFromCodeConnectId = (id: string | null): string | undefined => {
|
|
66
|
+
if (!id) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
if (id.startsWith('ds-icon-o-')) {
|
|
70
|
+
return id.slice('ds-icon-o-'.length);
|
|
71
|
+
}
|
|
72
|
+
if (id.startsWith('ds-icon-s-')) {
|
|
73
|
+
return id.slice('ds-icon-s-'.length);
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const resolveIcon = (iconInstance: figma.InstanceHandle): string | undefined => {
|
|
79
|
+
const fromCcId = iconNameFromCodeConnectId(iconInstance.codeConnectId());
|
|
80
|
+
if (fromCcId) {
|
|
81
|
+
return fromCcId;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const iconFromMetadata = iconInstance.executeTemplate().metadata?.props?.icon;
|
|
85
|
+
if (typeof iconFromMetadata === 'string') {
|
|
86
|
+
return iconFromMetadata;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return toIconName(iconInstance.name);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const leadingIcon = structure.type === 'INSTANCE' ? structure.getInstanceSwap('iconBefore') : undefined;
|
|
93
|
+
const iconFromSwap = leadingIcon?.type === 'INSTANCE' ? resolveIcon(leadingIcon) : undefined;
|
|
94
|
+
const iconFromChild =
|
|
95
|
+
structure.type === 'INSTANCE'
|
|
96
|
+
? structure
|
|
97
|
+
.findConnectedInstances((node) => node.codeConnectId()?.startsWith('ds-icon-') ?? false, {
|
|
98
|
+
traverseInstances: true,
|
|
99
|
+
})
|
|
100
|
+
.find((node): node is figma.InstanceHandle => node.type === 'INSTANCE')
|
|
101
|
+
: undefined;
|
|
102
|
+
const icon = iconFromSwap ?? (iconFromChild ? resolveIcon(iconFromChild) : undefined);
|
|
103
|
+
|
|
104
|
+
const labelNode = instance.findText('Button', { traverseInstances: true });
|
|
105
|
+
const label = labelNode.type === 'TEXT' ? labelNode.textContent : 'Button';
|
|
106
|
+
|
|
107
|
+
const iconProp = icon ? figma.code` icon="${icon}"` : '';
|
|
108
|
+
const disabledProp = disabled ? ' disabled' : '';
|
|
109
|
+
const loadingProp = loading ? ' loading' : '';
|
|
110
|
+
const highEmphasisProp = highEmphasis ? ' highEmphasis' : '';
|
|
111
|
+
|
|
112
|
+
export default {
|
|
113
|
+
example: iconOnly
|
|
114
|
+
? figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}"${disabledProp}${loadingProp}${highEmphasisProp}${iconProp} aria-label="${label}" />`
|
|
115
|
+
: showIcon && icon
|
|
116
|
+
? figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}"${disabledProp}${loadingProp}${highEmphasisProp} icon="${icon}">${label}</DsButtonV3>`
|
|
117
|
+
: figma.code`<DsButtonV3 variant="${variant}" color="${color}" size="${size}"${disabledProp}${loadingProp}${highEmphasisProp}>${label}</DsButtonV3>`,
|
|
118
|
+
imports: ["import { DsButtonV3 } from '@drivenets/design-system';"],
|
|
119
|
+
id: 'ds-button-v4',
|
|
120
|
+
metadata: { nestable: true },
|
|
121
|
+
} satisfies figma.Template;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=18638-7430
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-comment-bubble
|
|
3
|
+
// component=DsCommentBubble
|
|
4
|
+
//
|
|
5
|
+
// `DsCommentBubbleV1` is the floating comment bubble. Its Figma `type` axis
|
|
6
|
+
// (`initial` / `start typing` vs `open`) selects between the empty compose state and
|
|
7
|
+
// a thread; in code this is driven by whether the `comment` prop is present, so the
|
|
8
|
+
// snippet emits `comment` / `currentUser` identifier placeholders for the developer to
|
|
9
|
+
// wire to state. The `action required` axis maps to `hideActionRequired` (the
|
|
10
|
+
// `no checkbox` variant hides the control); `State` is visual only and has no prop.
|
|
11
|
+
import figma from 'figma';
|
|
12
|
+
|
|
13
|
+
const instance = figma.selectedInstance;
|
|
14
|
+
|
|
15
|
+
const bubbleType =
|
|
16
|
+
instance.getEnum('type', {
|
|
17
|
+
initial: 'compose',
|
|
18
|
+
'start typing': 'compose',
|
|
19
|
+
open: 'thread',
|
|
20
|
+
}) ?? 'compose';
|
|
21
|
+
|
|
22
|
+
const hideActionRequired =
|
|
23
|
+
instance.getEnum('action required', {
|
|
24
|
+
'no checkbox': true,
|
|
25
|
+
false: false,
|
|
26
|
+
true: false,
|
|
27
|
+
}) ?? false;
|
|
28
|
+
|
|
29
|
+
const hideActionRequiredAttr = hideActionRequired ? '\n\thideActionRequired' : '';
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
example:
|
|
33
|
+
bubbleType === 'thread'
|
|
34
|
+
? figma.code`<DsCommentBubble
|
|
35
|
+
comment={comment}
|
|
36
|
+
currentUser={currentUser}
|
|
37
|
+
value={value}
|
|
38
|
+
onValueChange={setValue}
|
|
39
|
+
onSend={handleSend}
|
|
40
|
+
onClose={handleClose}${hideActionRequiredAttr}
|
|
41
|
+
/>`
|
|
42
|
+
: figma.code`<DsCommentBubble
|
|
43
|
+
currentUser={currentUser}
|
|
44
|
+
value={value}
|
|
45
|
+
onValueChange={setValue}
|
|
46
|
+
onSend={handleSend}
|
|
47
|
+
onClose={handleClose}${hideActionRequiredAttr}
|
|
48
|
+
/>`,
|
|
49
|
+
imports: ["import { DsCommentBubble } from '@drivenets/design-system';"],
|
|
50
|
+
id: 'ds-comment-bubble',
|
|
51
|
+
metadata: { nestable: true },
|
|
52
|
+
} satisfies figma.Template;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=18166-58292
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-comment-card
|
|
3
|
+
// component=DsCommentCard
|
|
4
|
+
//
|
|
5
|
+
// `DsCommentCardV1` composes the inner `Structure_CommentCardV1`. Its `overflow` axis
|
|
6
|
+
// maps directly to the `overflow` prop. The `type` axis is interaction state
|
|
7
|
+
// (default/hover are visual and CSS-driven — only `disabled` maps to a prop),
|
|
8
|
+
// mirroring `ds-card.figma.ts`. The `action required` axis is encoded in the `comment`
|
|
9
|
+
// data (`isActionRequired`), not a prop. `comment` is a data object that is not
|
|
10
|
+
// derivable from Figma, so it is emitted as an identifier placeholder for the
|
|
11
|
+
// developer to wire (see `ds-smart-tabs.figma.ts`).
|
|
12
|
+
import figma from 'figma';
|
|
13
|
+
|
|
14
|
+
const instance = figma.selectedInstance;
|
|
15
|
+
|
|
16
|
+
const state =
|
|
17
|
+
instance.getEnum('type', {
|
|
18
|
+
default: 'default',
|
|
19
|
+
hover: 'default',
|
|
20
|
+
disabled: 'disabled',
|
|
21
|
+
}) ?? 'default';
|
|
22
|
+
|
|
23
|
+
const overflow =
|
|
24
|
+
instance.getEnum('overflow', {
|
|
25
|
+
hidden: 'hidden',
|
|
26
|
+
displayed: 'displayed',
|
|
27
|
+
}) ?? 'hidden';
|
|
28
|
+
|
|
29
|
+
const disabledAttr = state === 'disabled' ? ' disabled' : '';
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
example: figma.code`<DsCommentCard comment={comment} overflow="${overflow}"${disabledAttr} />`,
|
|
33
|
+
imports: ["import { DsCommentCard } from '@drivenets/design-system';"],
|
|
34
|
+
id: 'ds-comment-card',
|
|
35
|
+
metadata: { nestable: true },
|
|
36
|
+
} satisfies figma.Template;
|