@drivenets/design-system 0.18.1 → 0.20.0
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 +48 -0
- package/dist/index.cjs +17038 -10114
- package/dist/index.d.cts +1355 -444
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1354 -443
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17073 -10172
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +41 -41
- package/src/components/ds-bot-button/ds-bot-button.figma.ts +38 -0
- package/src/components/ds-bot-button/ds-bot-button.module.scss +41 -0
- package/src/components/ds-bot-button/ds-bot-button.tsx +48 -0
- package/src/components/ds-bot-button/ds-bot-button.types.ts +33 -0
- package/src/components/ds-bot-button/index.ts +2 -0
- package/src/components/ds-bot-button/net-gen-logo.tsx +46 -0
- package/src/components/ds-bulk-actions/components/action-button.tsx +42 -0
- package/src/components/ds-bulk-actions/components/menu-entries.tsx +76 -0
- package/src/components/ds-bulk-actions/components/overflow.tsx +75 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.figma.ts +28 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.module.scss +199 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.tsx +220 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.types.ts +170 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.unit.test.ts +195 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.utils.ts +91 -0
- package/src/components/ds-bulk-actions/ds-bulk-actions.utils.unit.test.ts +134 -0
- package/src/components/ds-bulk-actions/hooks/compute-bulk-actions-overflow.ts +85 -0
- package/src/components/ds-bulk-actions/hooks/use-bulk-actions-overflow.ts +153 -0
- package/src/components/ds-bulk-actions/index.ts +18 -0
- package/src/components/ds-button-v3/ds-button-v3.module.scss +2 -2
- package/src/components/ds-catalog-layout/ds-catalog-layout.figma.ts +1 -1
- package/src/components/ds-checkbox/ds-checkbox.figma.ts +3 -0
- package/src/components/ds-checkbox/ds-checkbox.module.scss +102 -20
- package/src/components/ds-checkbox/ds-checkbox.tsx +30 -2
- package/src/components/ds-checkbox/ds-checkbox.types.ts +10 -0
- package/src/components/ds-code-input/collapsed-code-field/collapsed-code-field.module.scss +169 -0
- package/src/components/ds-code-input/collapsed-code-field/collapsed-code-field.tsx +92 -0
- package/src/components/ds-code-input/collapsed-code-field/index.ts +1 -0
- package/src/components/ds-code-input/ds-code-input-panel/ds-code-input-panel.module.scss +110 -0
- package/src/components/ds-code-input/ds-code-input-panel/ds-code-input-panel.tsx +61 -0
- package/src/components/ds-code-input/ds-code-input-panel/index.ts +1 -0
- package/src/components/ds-code-input/ds-code-input.module.scss +25 -0
- package/src/components/ds-code-input/ds-code-input.tsx +401 -0
- package/src/components/ds-code-input/ds-code-input.types.ts +166 -0
- package/src/components/ds-code-input/ds-code-input.utils.ts +94 -0
- package/src/components/ds-code-input/ds-code-input.utils.unit.test.ts +166 -0
- package/src/components/ds-code-input/index.ts +2 -0
- package/src/components/ds-code-input/use-collapsed-viewport.ts +289 -0
- package/src/components/ds-code-input/use-editor-host.ts +87 -0
- package/src/components/ds-dropdown-menu/ds-dropdown-menu.tsx +2 -0
- package/src/components/ds-empty-state/ds-empty-state.module.scss +16 -0
- package/src/components/ds-empty-state/ds-empty-state.tsx +45 -0
- package/src/components/ds-empty-state/ds-empty-state.types.ts +38 -0
- package/src/components/ds-empty-state/index.ts +3 -0
- package/src/components/ds-file-upload/ds-file-upload.tsx +4 -1
- package/src/components/ds-filters-bar/components/ds-filters-bar-builder/ds-filters-bar-builder.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-builder/ds-filters-bar-builder.types.ts +41 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-builder/index.ts +1 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-clear-all.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-conditions/ds-filters-bar-conditions.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-conditions/ds-filters-bar-conditions.types.ts +30 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-conditions/index.ts +1 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-pinned.ts +31 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-query/ds-filters-bar-query.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-query/ds-filters-bar-query.types.ts +22 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-query/index.ts +1 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-saved-filters.ts +19 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-search.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-summary.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-toolbar.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-view-switch.ts +11 -0
- package/src/components/ds-filters-bar/components/ds-filters-bar-view.ts +11 -0
- package/src/components/ds-filters-bar/components/index.ts +11 -0
- package/src/components/ds-filters-bar/ds-filters-bar.context.ts +69 -0
- package/src/components/ds-filters-bar/ds-filters-bar.tsx +120 -0
- package/src/components/ds-filters-bar/ds-filters-bar.types.ts +440 -0
- package/src/components/ds-filters-bar/ds-filters-bar.unit.test.ts +216 -0
- package/src/components/ds-filters-bar/ds-filters-bar.utils.ts +141 -0
- package/src/components/ds-filters-bar/index.ts +1 -0
- package/src/components/ds-form-control/ds-form-control.module.scss +18 -0
- package/src/components/ds-form-control/ds-form-control.tsx +61 -19
- package/src/components/ds-form-control/ds-form-control.types.ts +2 -1
- package/src/components/ds-icon/custom-icons/index.ts +2 -0
- package/src/components/ds-icon/custom-icons/special-adv-filters.tsx +28 -0
- package/src/components/ds-illustration/ds-illustration.figma.ts +34 -0
- package/src/components/ds-illustration/ds-illustration.module.scss +6 -0
- package/src/components/ds-illustration/ds-illustration.tsx +29 -0
- package/src/components/ds-illustration/ds-illustration.types.ts +45 -0
- package/src/components/ds-illustration/illustrations/configuration.tsx +51 -0
- package/src/components/ds-illustration/illustrations/device.tsx +133 -0
- package/src/components/ds-illustration/illustrations/done.tsx +107 -0
- package/src/components/{ds-catalog-layout/catalog-layout-empty-illustration.tsx → ds-illustration/illustrations/empty-inbox.tsx} +10 -14
- package/src/components/ds-illustration/illustrations/error.tsx +86 -0
- package/src/components/ds-illustration/illustrations/go-filter.tsx +51 -0
- package/src/components/ds-illustration/illustrations/illustration-clouds.tsx +10 -0
- package/src/components/ds-illustration/illustrations/index.ts +39 -0
- package/src/components/ds-illustration/illustrations/no-connection.tsx +54 -0
- package/src/components/ds-illustration/illustrations/no-credit-card.tsx +48 -0
- package/src/components/ds-illustration/illustrations/no-device.tsx +61 -0
- package/src/components/ds-illustration/illustrations/no-documents.tsx +52 -0
- package/src/components/ds-illustration/illustrations/no-gps.tsx +57 -0
- package/src/components/ds-illustration/illustrations/no-images.tsx +82 -0
- package/src/components/ds-illustration/illustrations/no-items-cart.tsx +86 -0
- package/src/components/ds-illustration/illustrations/no-messages.tsx +51 -0
- package/src/components/ds-illustration/illustrations/no-search-result.tsx +76 -0
- package/src/components/ds-illustration/illustrations/no-tasks.tsx +61 -0
- package/src/components/ds-illustration/illustrations/site.tsx +80 -0
- package/src/components/ds-illustration/index.ts +3 -0
- package/src/components/ds-main-menu/components/expanded-item/expanded-item.tsx +108 -0
- package/src/components/ds-main-menu/components/expanded-item/expanded-item.types.ts +8 -0
- package/src/components/ds-main-menu/components/expanded-item/index.ts +1 -0
- package/src/components/ds-main-menu/components/menu-graphic/index.ts +1 -0
- package/src/components/ds-main-menu/components/menu-graphic/menu-graphic.tsx +16 -0
- package/src/components/ds-main-menu/components/menu-graphic/menu-graphic.types.ts +7 -0
- package/src/components/ds-main-menu/components/tile-link/index.ts +1 -0
- package/src/components/ds-main-menu/components/tile-link/tile-link.tsx +85 -0
- package/src/components/ds-main-menu/components/tile-link/tile-link.types.ts +8 -0
- package/src/components/ds-main-menu/components/utility-link/index.ts +1 -0
- package/src/components/ds-main-menu/components/utility-link/utility-link.tsx +37 -0
- package/src/components/ds-main-menu/components/utility-link/utility-link.types.ts +7 -0
- package/src/components/ds-main-menu/ds-main-menu.figma.ts +17 -0
- package/src/components/ds-main-menu/ds-main-menu.module.scss +349 -0
- package/src/components/ds-main-menu/ds-main-menu.tsx +102 -0
- package/src/components/ds-main-menu/ds-main-menu.types.ts +86 -0
- package/src/components/ds-main-menu/ds-main-menu.utils.ts +40 -0
- package/src/components/ds-main-menu/index.ts +9 -0
- package/src/components/ds-modal/figma/ds-modal-footer.figma.ts +1 -1
- package/src/components/ds-pin-toggle/ds-pin-toggle.figma.ts +27 -0
- package/src/components/ds-pin-toggle/ds-pin-toggle.module.scss +41 -0
- package/src/components/ds-pin-toggle/ds-pin-toggle.tsx +43 -0
- package/src/components/ds-pin-toggle/ds-pin-toggle.types.ts +29 -0
- package/src/components/ds-pin-toggle/index.ts +2 -0
- package/src/components/ds-popover/components/popover-trigger/index.ts +1 -0
- package/src/components/ds-popover/components/popover-trigger/popover-trigger.tsx +15 -0
- package/src/components/ds-popover/ds-popover.context.ts +18 -0
- package/src/components/ds-popover/ds-popover.hover-intent.ts +65 -0
- package/src/components/ds-popover/ds-popover.tsx +164 -41
- package/src/components/ds-popover/ds-popover.types.ts +65 -0
- package/src/components/ds-popover/ds-popover.utils.ts +60 -0
- package/src/components/ds-popover/ds-popover.utils.unit.test.ts +25 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-delete-confirm.tsx +53 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-name-entry.tsx +64 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-name-modal.tsx +50 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-row/ds-saved-filters-row.module.scss +68 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-row/ds-saved-filters-row.tsx +83 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-row/index.ts +1 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-save.tsx +164 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-trigger/ds-saved-filters-trigger.module.scss +21 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-trigger/ds-saved-filters-trigger.tsx +237 -0
- package/src/components/ds-saved-filters/components/ds-saved-filters-trigger/index.ts +1 -0
- package/src/components/ds-saved-filters/components/index.ts +2 -0
- package/src/components/ds-saved-filters/ds-saved-filters.ts +6 -0
- package/src/components/ds-saved-filters/ds-saved-filters.types.ts +106 -0
- package/src/components/ds-saved-filters/ds-saved-filters.utils.ts +35 -0
- package/src/components/ds-saved-filters/hooks/index.ts +1 -0
- package/src/components/ds-saved-filters/hooks/use-picker-outside-dismiss.ts +42 -0
- package/src/components/ds-saved-filters/index.ts +2 -0
- package/src/components/ds-segment-group/ds-segment-group.module.scss +65 -37
- package/src/components/ds-segment-group/ds-segment-group.tsx +17 -5
- package/src/components/ds-segment-group/ds-segment-group.types.ts +20 -5
- package/src/components/ds-segment-group/figma/ds-segment-group-v2-item.figma.ts +109 -0
- package/src/components/ds-segment-group/figma/ds-segment-group-v2.figma.ts +31 -0
- package/src/components/ds-site-node/ds-site-node.tsx +2 -2
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.module.scss +12 -2
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.tsx +2 -3
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.module.scss +1 -6
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.tsx +6 -3
- package/src/components/ds-table/components/ds-table-header/ds-table-header.module.scss +18 -7
- package/src/components/ds-table/components/ds-table-header/ds-table-header.tsx +27 -21
- package/src/components/ds-table/components/ds-table-header-label.module.scss +12 -0
- package/src/components/ds-table/components/ds-table-header-label.tsx +28 -0
- package/src/components/ds-table/components/ds-table-row/ds-table-row.module.scss +0 -1
- package/src/components/ds-table/context/ds-table-context.tsx +8 -0
- package/src/components/ds-table/ds-table.module.scss +26 -16
- package/src/components/ds-table/ds-table.tsx +46 -14
- package/src/components/ds-table/ds-table.types.ts +33 -3
- package/src/components/ds-table/hooks/use-column-resize.ts +114 -11
- package/src/components/ds-table/hooks/use-scrollbar-spacer.ts +108 -0
- package/src/components/ds-table/hooks/use-scrollbar-spacer.unit.test.ts +26 -0
- package/src/components/ds-table/styles/_variables.scss +0 -2
- package/src/components/ds-table/utils/column-size.ts +274 -1
- package/src/components/ds-table/utils/column-size.unit.test.ts +157 -0
- package/src/components/ds-table/utils/constants.ts +13 -5
- package/src/components/ds-table/utils/table-columns.tsx +27 -13
- package/src/components/ds-table/utils/table-columns.unit.test.ts +44 -0
- package/src/components/ds-tag/ds-tag.figma.ts +23 -3
- package/src/components/ds-tag/ds-tag.module.scss +71 -7
- package/src/components/ds-tag/ds-tag.tsx +115 -14
- package/src/components/ds-tag/ds-tag.types.ts +70 -3
- package/src/components/ds-tag/ds-tag.unit.test.ts +23 -4
- package/src/components/ds-tag/index.ts +2 -2
- package/src/components/ds-text-input/ds-input-field-v02.figma.ts +2 -0
- package/src/components/ds-toggle/ds-toggle.module.scss +18 -0
- package/src/components/ds-toggle/ds-toggle.tsx +15 -9
- package/src/components/ds-toggle/ds-toggle.types.ts +6 -0
- package/src/components/ds-toggle-filter-data/ds-toggle-filter-data.module.scss +69 -0
- package/src/components/ds-toggle-filter-data/ds-toggle-filter-data.tsx +55 -0
- package/src/components/ds-toggle-filter-data/ds-toggle-filter-data.types.ts +43 -0
- package/src/components/ds-toggle-filter-data/index.ts +1 -0
- package/src/components/ds-tooltip/ds-tooltip.module.scss +8 -0
- package/src/components/ds-tooltip/ds-tooltip.tsx +7 -3
- package/src/components/ds-tooltip/ds-tooltip.types.ts +17 -0
- package/src/components/ds-top-bar-navigation/ds-top-bar-navigation.figma.ts +35 -0
- package/src/components/ds-top-bar-navigation/ds-top-bar-navigation.module.scss +150 -0
- package/src/components/ds-top-bar-navigation/ds-top-bar-navigation.tsx +161 -0
- package/src/components/ds-top-bar-navigation/ds-top-bar-navigation.types.ts +117 -0
- package/src/components/ds-top-bar-navigation/index.ts +2 -0
- package/src/components/ds-tree/ds-tree.tsx +10 -10
- package/src/components/ds-tree/ds-tree.types.ts +40 -7
- package/src/index.ts +8 -0
- package/src/utils/use-is-horizontally-overflowing.ts +35 -0
- package/src/components/ds-site-node/hooks/use-is-overflowing.ts +0 -31
- package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.module.scss +0 -112
- package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.tsx +0 -67
- package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.types.ts +0 -41
- package/src/components/ds-table/components/ds-table-bulk-actions/index.ts +0 -2
|
@@ -7,7 +7,18 @@
|
|
|
7
7
|
// is a single variant backed by an internal, non-exposed include/exclude sub-toggle, so it can
|
|
8
8
|
// only be surfaced as one code value — it maps to `variant="include"`; switch to `variant="exclude"`
|
|
9
9
|
// for the exclude case. `label` is content, pulled from the tag text when present, otherwise a
|
|
10
|
-
// placeholder; `value` (required
|
|
10
|
+
// placeholder; `value` (required by `key-value`, `operator-filter` and `query-filter`) is emitted
|
|
11
|
+
// as a placeholder.
|
|
12
|
+
//
|
|
13
|
+
// Three code props are deliberately not derived from this node:
|
|
14
|
+
// - `shape` — the pill radius is not modelled in Figma at all, so `shape="round"` is a code-side
|
|
15
|
+
// choice.
|
|
16
|
+
// - `warning` / `onExpandClick` — the warning ellipse and `Part_expandCollapseBtn_v01` are hidden
|
|
17
|
+
// layers in every variant of this node, so the emitted example leaves both off; add them in code
|
|
18
|
+
// when the design that consumes the tag shows them.
|
|
19
|
+
//
|
|
20
|
+
// `operator-filter` nests a `DsButtonV4` trigger that does not exist in code. The trigger is a
|
|
21
|
+
// consumer-owned slot, so the example emits a `DsSelect` placeholder for the developer to wire.
|
|
11
22
|
import figma from 'figma';
|
|
12
23
|
|
|
13
24
|
const instance = figma.selectedInstance;
|
|
@@ -17,6 +28,8 @@ const variant =
|
|
|
17
28
|
default: 'default',
|
|
18
29
|
'include-exclude': 'include',
|
|
19
30
|
'key-value': 'key-value',
|
|
31
|
+
'operator-filter': 'operator-filter',
|
|
32
|
+
'query-filter': 'query-filter',
|
|
20
33
|
}) ?? 'default';
|
|
21
34
|
|
|
22
35
|
const size = instance.getEnum('Size', { medium: 'medium', small: 'small' }) ?? 'medium';
|
|
@@ -32,10 +45,13 @@ const state = instance.getEnum('State', {
|
|
|
32
45
|
const labelNode = instance.findText('Tag-name', { traverseInstances: true });
|
|
33
46
|
const label = labelNode.type === 'TEXT' ? labelNode.textContent : 'Label';
|
|
34
47
|
|
|
48
|
+
const requiresValue = variant === 'key-value' || variant === 'operator-filter' || variant === 'query-filter';
|
|
49
|
+
|
|
35
50
|
const attrs = [
|
|
36
51
|
`label="${label}"`,
|
|
37
52
|
variant !== 'default' ? `variant="${variant}"` : '',
|
|
38
|
-
|
|
53
|
+
requiresValue ? 'value="Value"' : '',
|
|
54
|
+
variant === 'operator-filter' ? 'slots={{ operator: <DsSelect options={[]} value="" /> }}' : '',
|
|
39
55
|
size === 'small' ? 'size="small"' : '',
|
|
40
56
|
state === 'selected' ? 'selected' : '',
|
|
41
57
|
state === 'disabled' ? 'disabled' : '',
|
|
@@ -45,7 +61,11 @@ const attrs = [
|
|
|
45
61
|
|
|
46
62
|
export default {
|
|
47
63
|
example: figma.code`<DsTag ${attrs} />`,
|
|
48
|
-
imports: [
|
|
64
|
+
imports: [
|
|
65
|
+
variant === 'operator-filter'
|
|
66
|
+
? "import { DsSelect, DsTag } from '@drivenets/design-system';"
|
|
67
|
+
: "import { DsTag } from '@drivenets/design-system';",
|
|
68
|
+
],
|
|
49
69
|
id: 'ds-tag',
|
|
50
70
|
metadata: { nestable: true },
|
|
51
71
|
} satisfies figma.Template;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
@use '../../styles/typography';
|
|
2
2
|
|
|
3
|
+
$warning-dot-size: 8px;
|
|
4
|
+
|
|
3
5
|
.tag {
|
|
4
6
|
--transition-duration: 200ms;
|
|
5
7
|
|
|
@@ -19,6 +21,10 @@
|
|
|
19
21
|
transition-timing-function: ease-out;
|
|
20
22
|
transition-duration: var(--transition-duration);
|
|
21
23
|
|
|
24
|
+
&.round {
|
|
25
|
+
border-radius: 9999px;
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
&.clickable {
|
|
23
29
|
cursor: pointer;
|
|
24
30
|
|
|
@@ -40,7 +46,8 @@
|
|
|
40
46
|
outline-color: var(--border-action-primary);
|
|
41
47
|
}
|
|
42
48
|
|
|
43
|
-
.deleteButton
|
|
49
|
+
.deleteButton,
|
|
50
|
+
.expandButton {
|
|
44
51
|
outline-color: var(--border-action-primary);
|
|
45
52
|
}
|
|
46
53
|
}
|
|
@@ -65,13 +72,20 @@
|
|
|
65
72
|
|
|
66
73
|
.label,
|
|
67
74
|
.key,
|
|
68
|
-
.value
|
|
75
|
+
.value,
|
|
76
|
+
.queryLabel,
|
|
77
|
+
.queryValue {
|
|
69
78
|
color: var(--font-disabled);
|
|
70
79
|
}
|
|
71
80
|
|
|
72
|
-
.variantIcon
|
|
81
|
+
.variantIcon,
|
|
82
|
+
.querySeparator {
|
|
73
83
|
color: var(--font-disabled);
|
|
74
84
|
}
|
|
85
|
+
|
|
86
|
+
.warningDot {
|
|
87
|
+
background: var(--icon-disabled);
|
|
88
|
+
}
|
|
75
89
|
}
|
|
76
90
|
|
|
77
91
|
.deleteButton {
|
|
@@ -93,6 +107,22 @@
|
|
|
93
107
|
}
|
|
94
108
|
}
|
|
95
109
|
|
|
110
|
+
.expandButton {
|
|
111
|
+
flex-shrink: 0;
|
|
112
|
+
display: flex;
|
|
113
|
+
margin-left: var(--3xs);
|
|
114
|
+
outline-color: var(--border-action-secondary);
|
|
115
|
+
user-select: none;
|
|
116
|
+
transition-property: background, color, outline-color;
|
|
117
|
+
transition-timing-function: ease-out;
|
|
118
|
+
transition-duration: var(--transition-duration);
|
|
119
|
+
color: var(--icon-action);
|
|
120
|
+
|
|
121
|
+
&:hover {
|
|
122
|
+
background: var(--background-action-secondary-hover);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
96
126
|
&:hover:not(.disabled) .deleteButton,
|
|
97
127
|
&:focus-within:not(.disabled) .deleteButton,
|
|
98
128
|
&.selected:not(.disabled) .deleteButton {
|
|
@@ -107,17 +137,20 @@
|
|
|
107
137
|
@include typography.ellipsis;
|
|
108
138
|
}
|
|
109
139
|
|
|
110
|
-
.
|
|
140
|
+
.segments {
|
|
111
141
|
min-width: 0;
|
|
112
142
|
}
|
|
113
143
|
|
|
114
144
|
.key {
|
|
115
145
|
flex-shrink: 0;
|
|
116
146
|
color: var(--font-main);
|
|
147
|
+
}
|
|
117
148
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
149
|
+
// `key-value` renders its colon as generated content rather than text so the tag's text
|
|
150
|
+
// content stays the bare label — `getByText('Category')` keeps working for consumers.
|
|
151
|
+
// Scoped to its own class because `operator-filter` shares `.key` and takes no colon.
|
|
152
|
+
.keyColon::after {
|
|
153
|
+
content: ':';
|
|
121
154
|
}
|
|
122
155
|
|
|
123
156
|
.value {
|
|
@@ -126,6 +159,37 @@
|
|
|
126
159
|
color: var(--font-secondary);
|
|
127
160
|
}
|
|
128
161
|
|
|
162
|
+
.operatorSlot {
|
|
163
|
+
flex-shrink: 0;
|
|
164
|
+
display: flex;
|
|
165
|
+
align-items: center;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.queryLabel {
|
|
169
|
+
flex-shrink: 0;
|
|
170
|
+
color: var(--font-main);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.querySeparator {
|
|
174
|
+
flex-shrink: 0;
|
|
175
|
+
color: var(--icon-tertiary);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.queryValue {
|
|
179
|
+
@include typography.ellipsis;
|
|
180
|
+
|
|
181
|
+
color: var(--font-main);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.warningDot {
|
|
185
|
+
flex-shrink: 0;
|
|
186
|
+
width: $warning-dot-size;
|
|
187
|
+
height: $warning-dot-size;
|
|
188
|
+
margin-left: var(--3xs);
|
|
189
|
+
border-radius: 50%;
|
|
190
|
+
background: var(--icon-warning-light);
|
|
191
|
+
}
|
|
192
|
+
|
|
129
193
|
.icon {
|
|
130
194
|
flex-shrink: 0;
|
|
131
195
|
display: flex;
|
|
@@ -16,12 +16,15 @@ const DsTag = ({
|
|
|
16
16
|
className,
|
|
17
17
|
style = {},
|
|
18
18
|
size = 'medium',
|
|
19
|
+
shape = 'default',
|
|
19
20
|
selected = false,
|
|
20
21
|
variant = 'default',
|
|
22
|
+
warning = false,
|
|
21
23
|
disabled = false,
|
|
22
24
|
locale = {},
|
|
23
25
|
onClick,
|
|
24
26
|
onDelete,
|
|
27
|
+
onExpandClick,
|
|
25
28
|
slots,
|
|
26
29
|
...rest
|
|
27
30
|
}: DsTagProps) => {
|
|
@@ -32,6 +35,7 @@ const DsTag = ({
|
|
|
32
35
|
[styles.selected]: selected && !disabled,
|
|
33
36
|
[styles.include]: variant === 'include',
|
|
34
37
|
[styles.exclude]: variant === 'exclude',
|
|
38
|
+
[styles.round]: shape === 'round',
|
|
35
39
|
[styles.disabled]: disabled,
|
|
36
40
|
},
|
|
37
41
|
className,
|
|
@@ -65,6 +69,26 @@ const DsTag = ({
|
|
|
65
69
|
}
|
|
66
70
|
};
|
|
67
71
|
|
|
72
|
+
const handleExpandClick = (event: MouseEvent<HTMLElement>) => {
|
|
73
|
+
event.stopPropagation();
|
|
74
|
+
onExpandClick?.(event);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const handleKeyDownExpand = (event: KeyboardEvent<HTMLElement>) => {
|
|
78
|
+
event.stopPropagation();
|
|
79
|
+
|
|
80
|
+
if (onExpandClick && (event.key === 'Enter' || event.key === ' ')) {
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
onExpandClick(event);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// The operator slot owns a fully-wired control, so neither its clicks nor its keystrokes may
|
|
87
|
+
// reach the tag's own click / delete keyboard shortcuts.
|
|
88
|
+
const stopPropagation = (event: MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement>) => {
|
|
89
|
+
event.stopPropagation();
|
|
90
|
+
};
|
|
91
|
+
|
|
68
92
|
const handleClick = (event: MouseEvent<HTMLElement>) => {
|
|
69
93
|
if (onClick) {
|
|
70
94
|
event.preventDefault();
|
|
@@ -82,6 +106,83 @@ const DsTag = ({
|
|
|
82
106
|
iconVariant = 'do_not_disturb_on';
|
|
83
107
|
}
|
|
84
108
|
|
|
109
|
+
const warningAriaLabel = locale.warningAriaLabel ?? 'Warning';
|
|
110
|
+
|
|
111
|
+
// `role="button"` makes the subtree presentational and the root's own `aria-label` replaces any
|
|
112
|
+
// name computed from it, so the dot's `role="img"` name is pruned on an interactive tag. Fold it
|
|
113
|
+
// into the root name instead, and keep the dot named for the non-interactive case.
|
|
114
|
+
const rootAriaLabel =
|
|
115
|
+
typeof label === 'string' ? (warning ? `${label}, ${warningAriaLabel}` : label) : undefined;
|
|
116
|
+
|
|
117
|
+
const isSmall = size === 'small';
|
|
118
|
+
const regularVariant = isSmall ? 'body-xs-reg' : 'body-sm-reg';
|
|
119
|
+
const mediumVariant = isSmall ? 'body-xs-md' : 'body-sm-md';
|
|
120
|
+
const semiBoldVariant = isSmall ? 'body-xs-semi-bold' : 'body-sm-semi-bold';
|
|
121
|
+
|
|
122
|
+
const renderContent = () => {
|
|
123
|
+
if (variant === 'key-value') {
|
|
124
|
+
return (
|
|
125
|
+
<DsStack direction="row" alignItems="center" gap="var(--3xs)" className={styles.segments}>
|
|
126
|
+
<DsTypography variant={mediumVariant} className={classNames(styles.key, styles.keyColon)}>
|
|
127
|
+
{label}
|
|
128
|
+
</DsTypography>
|
|
129
|
+
<DsTypography variant={regularVariant} className={styles.value}>
|
|
130
|
+
{value}
|
|
131
|
+
</DsTypography>
|
|
132
|
+
</DsStack>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (variant === 'operator-filter') {
|
|
137
|
+
const operatorSlot = slots?.operator;
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<DsStack direction="row" alignItems="center" gap="var(--3xs)" className={styles.segments}>
|
|
141
|
+
<DsTypography variant={mediumVariant} className={styles.key}>
|
|
142
|
+
{label}
|
|
143
|
+
</DsTypography>
|
|
144
|
+
{operatorSlot !== undefined &&
|
|
145
|
+
operatorSlot !== null && (
|
|
146
|
+
// The wrapper is a pure event boundary with no semantics of its own; the slotted
|
|
147
|
+
// control keeps its own. `role="presentation"` is what satisfies
|
|
148
|
+
// jsx-a11y/no-static-element-interactions for a span carrying these handlers.
|
|
149
|
+
<span
|
|
150
|
+
role="presentation"
|
|
151
|
+
className={styles.operatorSlot}
|
|
152
|
+
onClick={stopPropagation}
|
|
153
|
+
onKeyDown={stopPropagation}
|
|
154
|
+
>
|
|
155
|
+
{operatorSlot}
|
|
156
|
+
</span>
|
|
157
|
+
)}
|
|
158
|
+
<DsTypography variant={regularVariant} className={styles.value}>
|
|
159
|
+
{value}
|
|
160
|
+
</DsTypography>
|
|
161
|
+
</DsStack>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (variant === 'query-filter') {
|
|
166
|
+
return (
|
|
167
|
+
<DsStack direction="row" alignItems="center" gap="var(--4xs)" className={styles.segments}>
|
|
168
|
+
<DsTypography variant={regularVariant} className={styles.queryLabel}>
|
|
169
|
+
{label}
|
|
170
|
+
</DsTypography>
|
|
171
|
+
<DsIcon icon="keyboard_arrow_right" size="tiny" aria-hidden className={styles.querySeparator} />
|
|
172
|
+
<DsTypography variant={semiBoldVariant} className={styles.queryValue}>
|
|
173
|
+
{value}
|
|
174
|
+
</DsTypography>
|
|
175
|
+
</DsStack>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<DsTypography variant={regularVariant} className={styles.label}>
|
|
181
|
+
{label}
|
|
182
|
+
</DsTypography>
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
85
186
|
return (
|
|
86
187
|
<div
|
|
87
188
|
ref={ref as Ref<HTMLDivElement>}
|
|
@@ -91,7 +192,7 @@ const DsTag = ({
|
|
|
91
192
|
onKeyDown={disabled ? undefined : handleKeyDownTag}
|
|
92
193
|
role={onClick || onDelete ? 'button' : undefined}
|
|
93
194
|
tabIndex={disabled || (!onClick && !onDelete) ? undefined : 0}
|
|
94
|
-
aria-label={
|
|
195
|
+
aria-label={rootAriaLabel}
|
|
95
196
|
aria-pressed={onClick && selected && !disabled ? 'true' : undefined}
|
|
96
197
|
aria-disabled={disabled}
|
|
97
198
|
{...rest}
|
|
@@ -104,19 +205,19 @@ const DsTag = ({
|
|
|
104
205
|
))}
|
|
105
206
|
</span>
|
|
106
207
|
)}
|
|
107
|
-
{
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
</
|
|
208
|
+
{renderContent()}
|
|
209
|
+
{warning && <span role="img" aria-label={warningAriaLabel} className={styles.warningDot} />}
|
|
210
|
+
{onExpandClick && !disabled && (
|
|
211
|
+
<button
|
|
212
|
+
type="button"
|
|
213
|
+
className={styles.expandButton}
|
|
214
|
+
onClick={handleExpandClick}
|
|
215
|
+
onKeyDown={handleKeyDownExpand}
|
|
216
|
+
aria-label={locale.expandAriaLabel ?? 'Expand'}
|
|
217
|
+
tabIndex={0}
|
|
218
|
+
>
|
|
219
|
+
<DsIcon icon="keyboard_arrow_down" size="tiny" aria-hidden />
|
|
220
|
+
</button>
|
|
120
221
|
)}
|
|
121
222
|
{onDelete && !disabled && (
|
|
122
223
|
<button
|
|
@@ -3,9 +3,19 @@ import type { CSSProperties, KeyboardEvent, MouseEvent, ReactNode, Ref } from 'r
|
|
|
3
3
|
export const tagSizes = ['medium', 'small'] as const;
|
|
4
4
|
export type TagSize = (typeof tagSizes)[number];
|
|
5
5
|
|
|
6
|
-
export const tagVariants = [
|
|
6
|
+
export const tagVariants = [
|
|
7
|
+
'default',
|
|
8
|
+
'include',
|
|
9
|
+
'exclude',
|
|
10
|
+
'key-value',
|
|
11
|
+
'operator-filter',
|
|
12
|
+
'query-filter',
|
|
13
|
+
] as const;
|
|
7
14
|
export type TagVariant = (typeof tagVariants)[number];
|
|
8
15
|
|
|
16
|
+
export const tagShapes = ['default', 'round'] as const;
|
|
17
|
+
export type TagShape = (typeof tagShapes)[number];
|
|
18
|
+
|
|
9
19
|
interface DsTagBaseProps {
|
|
10
20
|
/**
|
|
11
21
|
* Ref to the tag element
|
|
@@ -27,6 +37,14 @@ interface DsTagBaseProps {
|
|
|
27
37
|
* aria-label for the delete button (shown when `onDelete` is provided).
|
|
28
38
|
*/
|
|
29
39
|
deleteAriaLabel?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Accessible name for the warning dot (shown when `warning` is set).
|
|
42
|
+
*/
|
|
43
|
+
warningAriaLabel?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Accessible name for the expand chevron (shown when `onExpandClick` is provided).
|
|
46
|
+
*/
|
|
47
|
+
expandAriaLabel?: string;
|
|
30
48
|
};
|
|
31
49
|
/**
|
|
32
50
|
* Additional styles to apply to the component
|
|
@@ -40,16 +58,33 @@ interface DsTagBaseProps {
|
|
|
40
58
|
* Callback function when the delete icon is clicked
|
|
41
59
|
*/
|
|
42
60
|
onDelete?: (event: MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement>) => void;
|
|
61
|
+
/**
|
|
62
|
+
* Callback function when the expand chevron is clicked. Providing a handler is what renders the
|
|
63
|
+
* chevron — the tag keeps no expanded state of its own, so the consumer owns whatever the
|
|
64
|
+
* chevron reveals.
|
|
65
|
+
*/
|
|
66
|
+
onExpandClick?: (event: MouseEvent<HTMLElement> | KeyboardEvent<HTMLElement>) => void;
|
|
43
67
|
/**
|
|
44
68
|
* Size of the tag
|
|
45
69
|
* @default 'medium'
|
|
46
70
|
*/
|
|
47
71
|
size?: TagSize;
|
|
72
|
+
/**
|
|
73
|
+
* Border radius of the tag: `'default'` (4px) or `'round'` (pill)
|
|
74
|
+
* @default 'default'
|
|
75
|
+
*/
|
|
76
|
+
shape?: TagShape;
|
|
48
77
|
/**
|
|
49
78
|
* Whether the tag is in a selected/pressed state
|
|
50
79
|
* @default false
|
|
51
80
|
*/
|
|
52
81
|
selected?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Whether to render a trailing warning dot. Copy and any tooltip around it belong to the
|
|
84
|
+
* consumer; only the dot's accessible name is configurable, via `locale.warningAriaLabel`.
|
|
85
|
+
* @default false
|
|
86
|
+
*/
|
|
87
|
+
warning?: boolean;
|
|
53
88
|
/**
|
|
54
89
|
* Whether the tag is disabled
|
|
55
90
|
* @default false
|
|
@@ -64,6 +99,14 @@ interface DsTagBaseProps {
|
|
|
64
99
|
* Icon to display at the start of the input
|
|
65
100
|
*/
|
|
66
101
|
icon?: ReactNode;
|
|
102
|
+
/**
|
|
103
|
+
* Fully-wired operator trigger (for example a `DsSelect`) rendered between `label` and
|
|
104
|
+
* `value`. Honoured only by `variant="operator-filter"` and ignored by every other variant.
|
|
105
|
+
*
|
|
106
|
+
* The tag cannot disable an arbitrary node, so `disabled` does not reach the slotted
|
|
107
|
+
* control — pass `disabled` to it yourself.
|
|
108
|
+
*/
|
|
109
|
+
operator?: ReactNode;
|
|
67
110
|
};
|
|
68
111
|
}
|
|
69
112
|
|
|
@@ -79,9 +122,33 @@ interface DsTagStandardProps extends DsTagBaseProps {
|
|
|
79
122
|
interface DsTagKeyValueProps extends DsTagBaseProps {
|
|
80
123
|
variant: 'key-value';
|
|
81
124
|
/**
|
|
82
|
-
* Secondary-colored value rendered after the key (`label`)
|
|
125
|
+
* Secondary-colored value rendered after the key (`label`) and its `:` separator. The key
|
|
126
|
+
* carries the emphasis. Required for the `key-value` variant.
|
|
127
|
+
*/
|
|
128
|
+
value: ReactNode;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
interface DsTagOperatorFilterProps extends DsTagBaseProps {
|
|
132
|
+
variant: 'operator-filter';
|
|
133
|
+
/**
|
|
134
|
+
* Value rendered last, after `label` and the `slots.operator` trigger that sits between them.
|
|
135
|
+
* Required for the `operator-filter` variant.
|
|
136
|
+
*/
|
|
137
|
+
value: ReactNode;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
interface DsTagQueryFilterProps extends DsTagBaseProps {
|
|
141
|
+
variant: 'query-filter';
|
|
142
|
+
/**
|
|
143
|
+
* Emphasized value rendered after `label` and a `keyboard_arrow_right` separator. Emphasis is
|
|
144
|
+
* inverted compared to `key-value`: the value is the strong segment and `label` is regular.
|
|
145
|
+
* Required for the `query-filter` variant.
|
|
83
146
|
*/
|
|
84
147
|
value: ReactNode;
|
|
85
148
|
}
|
|
86
149
|
|
|
87
|
-
export type DsTagProps =
|
|
150
|
+
export type DsTagProps =
|
|
151
|
+
| DsTagStandardProps
|
|
152
|
+
| DsTagKeyValueProps
|
|
153
|
+
| DsTagOperatorFilterProps
|
|
154
|
+
| DsTagQueryFilterProps;
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
/* eslint-disable vitest/expect-expect */
|
|
2
2
|
import type { ReactNode } from 'react';
|
|
3
3
|
import { describe, expectTypeOf, it } from 'vitest';
|
|
4
|
-
import type { DsTagProps, TagVariant } from './ds-tag.types';
|
|
4
|
+
import type { DsTagProps, TagShape, TagVariant } from './ds-tag.types';
|
|
5
5
|
|
|
6
6
|
describe('DsTagProps discriminated union', () => {
|
|
7
|
-
it('includes key-value in the variant union', () => {
|
|
8
|
-
expectTypeOf<TagVariant>().toEqualTypeOf<
|
|
7
|
+
it('includes key-value and the filter variants in the variant union', () => {
|
|
8
|
+
expectTypeOf<TagVariant>().toEqualTypeOf<
|
|
9
|
+
'default' | 'include' | 'exclude' | 'key-value' | 'operator-filter' | 'query-filter'
|
|
10
|
+
>();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('exposes default and round shapes', () => {
|
|
14
|
+
expectTypeOf<TagShape>().toEqualTypeOf<'default' | 'round'>();
|
|
9
15
|
});
|
|
10
16
|
|
|
11
17
|
it('allows standard variants without a value', () => {
|
|
@@ -20,13 +26,26 @@ describe('DsTagProps discriminated union', () => {
|
|
|
20
26
|
expectTypeOf<{ label: string; variant: 'key-value' }>().not.toExtend<DsTagProps>();
|
|
21
27
|
});
|
|
22
28
|
|
|
29
|
+
it('requires a value for the operator-filter variant', () => {
|
|
30
|
+
expectTypeOf<{ label: string; variant: 'operator-filter'; value: string }>().toExtend<DsTagProps>();
|
|
31
|
+
expectTypeOf<{ label: string; variant: 'operator-filter' }>().not.toExtend<DsTagProps>();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('requires a value for the query-filter variant', () => {
|
|
35
|
+
expectTypeOf<{ label: string; variant: 'query-filter'; value: string }>().toExtend<DsTagProps>();
|
|
36
|
+
expectTypeOf<{ label: string; variant: 'query-filter' }>().not.toExtend<DsTagProps>();
|
|
37
|
+
});
|
|
38
|
+
|
|
23
39
|
it('forbids a value on standard variants', () => {
|
|
24
40
|
expectTypeOf<{ label: string; value: string }>().not.toExtend<DsTagProps>();
|
|
25
41
|
expectTypeOf<{ label: string; variant: 'default'; value: string }>().not.toExtend<DsTagProps>();
|
|
26
42
|
expectTypeOf<{ label: string; variant: 'include'; value: string }>().not.toExtend<DsTagProps>();
|
|
43
|
+
expectTypeOf<{ label: string; variant: 'exclude'; value: string }>().not.toExtend<DsTagProps>();
|
|
27
44
|
});
|
|
28
45
|
|
|
29
|
-
it('types
|
|
46
|
+
it('types every value-bearing variant as ReactNode', () => {
|
|
30
47
|
expectTypeOf<Extract<DsTagProps, { variant: 'key-value' }>['value']>().toEqualTypeOf<ReactNode>();
|
|
48
|
+
expectTypeOf<Extract<DsTagProps, { variant: 'operator-filter' }>['value']>().toEqualTypeOf<ReactNode>();
|
|
49
|
+
expectTypeOf<Extract<DsTagProps, { variant: 'query-filter' }>['value']>().toEqualTypeOf<ReactNode>();
|
|
31
50
|
});
|
|
32
51
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { default as DsTag } from './ds-tag';
|
|
2
|
-
export { tagSizes, tagVariants } from './ds-tag.types';
|
|
3
|
-
export type { TagSize, TagVariant, DsTagProps } from './ds-tag.types';
|
|
2
|
+
export { tagShapes, tagSizes, tagVariants } from './ds-tag.types';
|
|
3
|
+
export type { TagShape, TagSize, TagVariant, DsTagProps } from './ds-tag.types';
|
|
@@ -24,6 +24,7 @@ const textInfo: FieldInfo = {
|
|
|
24
24
|
const registry: Record<string, FieldInfo> = {
|
|
25
25
|
text: textInfo,
|
|
26
26
|
textArea: { component: 'DsTextarea', fcMember: 'Textarea' },
|
|
27
|
+
code: { component: 'DsCodeInput', fcMember: 'CodeInput', size: true, large: true, readOnly: true },
|
|
27
28
|
number: { component: 'DsNumberInput', fcMember: 'NumberInput', size: true, readOnly: true },
|
|
28
29
|
password: { component: 'DsPasswordInput', fcMember: 'PasswordInput', size: true, readOnly: true },
|
|
29
30
|
select: {
|
|
@@ -75,6 +76,7 @@ const inputType =
|
|
|
75
76
|
? part.getEnum('inputType', {
|
|
76
77
|
text: 'text',
|
|
77
78
|
'text-area': 'textArea',
|
|
79
|
+
code: 'code',
|
|
78
80
|
select: 'select',
|
|
79
81
|
password: 'password',
|
|
80
82
|
number: 'number',
|
|
@@ -144,6 +144,24 @@
|
|
|
144
144
|
pointer-events: none;
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
// Overlay the native input over the control so `getByRole('checkbox')` clicks
|
|
148
|
+
// land on a real interactive surface. Ark applies `visuallyHiddenStyle` inline
|
|
149
|
+
// (1x1, clipped, off-screen) which Playwright refuses to click; `!important`
|
|
150
|
+
// is required to beat inline-style specificity.
|
|
151
|
+
.hiddenInput {
|
|
152
|
+
position: absolute !important;
|
|
153
|
+
inset-block-start: 0 !important;
|
|
154
|
+
inset-inline-start: 0 !important;
|
|
155
|
+
width: calc(var(--switch-track-width) + var(--thumb-gap) * 2) !important;
|
|
156
|
+
height: calc(var(--thumb-size) + var(--thumb-gap) * 2) !important;
|
|
157
|
+
margin: 0 !important;
|
|
158
|
+
padding: 0 !important;
|
|
159
|
+
clip: auto !important;
|
|
160
|
+
overflow: visible !important;
|
|
161
|
+
opacity: 0 !important;
|
|
162
|
+
cursor: pointer !important;
|
|
163
|
+
}
|
|
164
|
+
|
|
147
165
|
.iconCheck {
|
|
148
166
|
left: var(--icon-spacing);
|
|
149
167
|
}
|
|
@@ -21,6 +21,7 @@ const DsToggle = ({
|
|
|
21
21
|
size = 'default',
|
|
22
22
|
children,
|
|
23
23
|
checked,
|
|
24
|
+
'aria-label': ariaLabel,
|
|
24
25
|
...rest
|
|
25
26
|
}: DsToggleProps) => {
|
|
26
27
|
const isSmall = size === 'small';
|
|
@@ -58,19 +59,24 @@ const DsToggle = ({
|
|
|
58
59
|
<DsIcon icon="close" size={iconSize} className={closeIconClass} />
|
|
59
60
|
</Switch.Control>
|
|
60
61
|
|
|
61
|
-
{label
|
|
62
|
+
{/* An empty Switch.Label would still be the input's aria-labelledby target and override aria-label. */}
|
|
63
|
+
{(label || children) && (
|
|
62
64
|
<Switch.Label>
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{labelInfo
|
|
67
|
-
|
|
65
|
+
{label ? (
|
|
66
|
+
<>
|
|
67
|
+
<DsTypography variant={isSmall ? 'body-xs-md' : 'body-sm-md'}>{label}</DsTypography>
|
|
68
|
+
{!!labelInfo && (
|
|
69
|
+
<DsTypography variant="body-xs-reg" className={styles.labelInfo}>
|
|
70
|
+
{labelInfo}
|
|
71
|
+
</DsTypography>
|
|
72
|
+
)}
|
|
73
|
+
</>
|
|
74
|
+
) : (
|
|
75
|
+
children
|
|
68
76
|
)}
|
|
69
77
|
</Switch.Label>
|
|
70
|
-
) : (
|
|
71
|
-
children
|
|
72
78
|
)}
|
|
73
|
-
<Switch.HiddenInput />
|
|
79
|
+
<Switch.HiddenInput className={styles.hiddenInput} aria-label={ariaLabel} />
|
|
74
80
|
</Switch.Root>
|
|
75
81
|
);
|
|
76
82
|
};
|
|
@@ -52,6 +52,12 @@ export type DsToggleProps = {
|
|
|
52
52
|
* Whether the toggle is disabled
|
|
53
53
|
*/
|
|
54
54
|
disabled?: boolean;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Accessible name for a toggle without a visible `label` or `children`.
|
|
58
|
+
* Ignored by assistive tech when a visible label is rendered.
|
|
59
|
+
*/
|
|
60
|
+
'aria-label'?: string;
|
|
55
61
|
} & (
|
|
56
62
|
| {
|
|
57
63
|
/**
|