@drivenets/design-system 0.15.0 → 0.17.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 +32 -0
- package/dist/index.cjs +1092 -381
- package/dist/index.d.cts +886 -1204
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +886 -1204
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1076 -377
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +36 -34
- package/src/components/ds-alert-banner/ds-alert-banner.tsx +16 -6
- package/src/components/ds-autocomplete/ds-autocomplete.figma.ts +36 -0
- package/src/components/ds-autocomplete/ds-autocomplete.tsx +2 -0
- package/src/components/ds-avatar/ds-avatar.figma.ts +30 -0
- package/src/components/ds-avatar/ds-avatar.tsx +6 -1
- package/src/components/ds-avatar/ds-avatar.types.ts +5 -2
- package/src/components/ds-avatar-group/ds-avatar-group.figma.ts +27 -0
- package/src/components/ds-avatar-group/ds-avatar-group.tsx +6 -1
- package/src/components/ds-avatar-group/ds-avatar-group.types.ts +3 -1
- package/src/components/ds-breadcrumb/ds-breadcrumb.figma.ts +19 -0
- package/src/components/ds-breadcrumb/ds-breadcrumb.tsx +2 -0
- package/src/components/ds-button/ds-button.tsx +2 -0
- package/src/components/ds-button-v3/ds-button-v3.figma.ts +3 -3
- package/src/components/ds-button-v3/ds-button-v3.tsx +6 -0
- package/src/components/ds-button-v3/index.ts +2 -0
- package/src/components/ds-card/ds-card.tsx +7 -3
- package/src/components/ds-card/figma/ds-card-content.figma.ts +2 -2
- package/src/components/ds-card/figma/ds-card-footer.figma.ts +2 -2
- package/src/components/ds-card/figma/ds-card-header.figma.ts +2 -2
- package/src/components/ds-card/figma/ds-card.figma.ts +2 -2
- package/src/components/ds-catalog-layout/ds-catalog-layout.figma.ts +51 -0
- package/src/components/ds-catalog-layout/ds-catalog-layout.tsx +15 -6
- package/src/components/ds-checkbox/ds-checkbox-level-2.figma.ts +40 -0
- package/src/components/ds-checkbox/ds-checkbox.figma.ts +45 -0
- package/src/components/ds-checkbox/ds-checkbox.module.scss +1 -1
- package/src/components/ds-checkbox/ds-checkbox.tsx +9 -1
- package/src/components/ds-checkbox-group/ds-checkbox-group.figma.ts +15 -0
- package/src/components/ds-checkbox-group/ds-checkbox-group.tsx +2 -0
- package/src/components/ds-chip/ds-chip.tsx +2 -0
- package/src/components/ds-chip-group/ds-chip-group.tsx +2 -0
- package/src/components/ds-comment-bubble/components/ds-comment-thread/ds-comment-thread.tsx +1 -0
- package/src/components/ds-comment-bubble/components/ds-thread-item/ds-thread-item.tsx +1 -0
- package/src/components/ds-comment-bubble/ds-comment-bubble.tsx +1 -0
- package/src/components/ds-comment-card/ds-comment-card.tsx +1 -0
- package/src/components/ds-comment-indicator/ds-comment-indicator.tsx +1 -0
- package/src/components/ds-comments-drawer/components/comments-filter-modal/index.ts +0 -1
- package/src/components/ds-comments-drawer/ds-comments-drawer.tsx +1 -0
- package/src/components/ds-confirmation/ds-confirmation.tsx +13 -10
- package/src/components/ds-date-input/ds-date-input.tsx +2 -0
- package/src/components/ds-date-picker/ds-date-picker.figma.ts +2 -2
- package/src/components/ds-date-picker/ds-date-picker.tsx +9 -0
- package/src/components/ds-date-picker/ds-date-picker.types.ts +1 -1
- package/src/components/ds-date-range-picker/ds-date-range-picker.tsx +2 -0
- package/src/components/ds-dialog/ds-dialog.tsx +9 -0
- package/src/components/ds-dialog/ds-dialog.types.ts +1 -1
- package/src/components/ds-divider/ds-divider.figma.ts +19 -0
- package/src/components/ds-divider/ds-divider.tsx +2 -0
- package/src/components/ds-drawer/ds-drawer.tsx +19 -8
- package/src/components/ds-drawer/figma/ds-drawer-content.figma.ts +15 -0
- package/src/components/ds-drawer/figma/ds-drawer-footer.figma.ts +19 -0
- package/src/components/ds-drawer/figma/ds-drawer-header.figma.ts +16 -0
- package/src/components/ds-drawer/figma/ds-drawer.figma.ts +36 -0
- package/src/components/ds-dropdown-menu/ds-dropdown-menu.module.scss +12 -3
- package/src/components/ds-dropdown-menu/ds-dropdown-menu.tsx +24 -6
- package/src/components/ds-dropdown-menu/ds-dropdown-menu.types.ts +10 -1
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-footer.figma.ts +11 -0
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-group.figma.ts +23 -0
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-item.figma.ts +29 -0
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-separator.figma.ts +11 -0
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu.figma.ts +24 -0
- package/src/components/ds-expandable-text-input/ds-expandable-text-input.figma.ts +24 -0
- package/src/components/ds-expandable-text-input/ds-expandable-text-input.tsx +1 -0
- package/src/components/ds-file-upload/components/file-upload-item/index.ts +0 -1
- package/src/components/ds-file-upload/ds-file-upload.figma.ts +29 -0
- package/src/components/ds-file-upload/ds-file-upload.tsx +2 -0
- package/src/components/ds-filter-status-icon/ds-filter-status-icon.figma.ts +22 -0
- package/src/components/ds-filter-status-icon/ds-filter-status-icon.tsx +1 -0
- package/src/components/ds-form-control/ds-form-control.figma.ts +2 -2
- package/src/components/ds-form-control/ds-form-control.tsx +16 -11
- package/src/components/ds-grid/index.ts +3 -0
- package/src/components/ds-icon/ds-icon.tsx +2 -0
- package/src/components/ds-icon/figma/ds-icon-material.figma.batch.ts +1 -1
- package/src/components/ds-icon/figma/ds-icon-special.figma.batch.ts +1 -1
- package/src/components/ds-key-value-pair/ds-key-value-pair.figma.ts +24 -0
- package/src/components/ds-key-value-pair/ds-key-value-pair.tsx +2 -0
- package/src/components/ds-loader/ds-loader.figma.ts +11 -0
- package/src/components/ds-loader/ds-loader.tsx +2 -0
- package/src/components/ds-modal/ds-modal.tsx +17 -7
- package/src/components/ds-modal/figma/ds-modal-content.figma.ts +2 -2
- package/src/components/ds-modal/figma/ds-modal-footer.figma.ts +2 -2
- package/src/components/ds-modal/figma/ds-modal-header.figma.ts +2 -2
- package/src/components/ds-modal/figma/ds-modal.figma.ts +2 -2
- package/src/components/ds-number-input/ds-number-input.tsx +3 -0
- package/src/components/ds-panel/ds-panel.figma.ts +16 -0
- package/src/components/ds-panel/index.ts +2 -0
- package/src/components/ds-password-input/ds-password-input.tsx +2 -0
- package/src/components/ds-popover/ds-popover.tsx +9 -0
- package/src/components/ds-popover/figma/ds-popover-content-item.figma.ts +18 -0
- package/src/components/ds-popover/figma/ds-popover-content.figma.ts +15 -0
- package/src/components/ds-popover/figma/ds-popover-footer.figma.ts +19 -0
- package/src/components/ds-popover/figma/ds-popover-header.figma.ts +16 -0
- package/src/components/ds-popover/figma/ds-popover.figma.ts +34 -0
- package/src/components/ds-progress-arc/ds-progress-arc.figma.ts +23 -0
- package/src/components/ds-progress-arc/ds-progress-arc.tsx +2 -0
- package/src/components/ds-progress-donut/ds-progress-donut.figma.ts +45 -0
- package/src/components/ds-progress-donut/ds-progress-donut.tsx +2 -0
- package/src/components/ds-progress-linear/ds-progress-linear.figma.ts +26 -0
- package/src/components/ds-progress-linear/ds-progress-linear.tsx +2 -0
- package/src/components/ds-progress-task-bar/ds-progress-task-bar.figma.ts +2 -2
- package/src/components/ds-progress-task-bar/ds-progress-task-bar.tsx +2 -0
- package/src/components/ds-radio-group/ds-radio-group.tsx +3 -0
- package/src/components/ds-radio-group/figma/ds-radio-group-item.figma.ts +24 -0
- package/src/components/ds-radio-group/figma/ds-radio-group.figma.ts +14 -0
- package/src/components/ds-segment-group/ds-segment-group.tsx +3 -0
- package/src/components/ds-segment-group/figma/ds-segment-group-item.figma.ts +25 -0
- package/src/components/ds-segment-group/figma/ds-segment-group.figma.ts +23 -0
- package/src/components/ds-select/ds-select.figma.ts +2 -2
- package/src/components/ds-select/ds-select.tsx +2 -0
- package/src/components/ds-site-node/ds-site-node.figma.ts +27 -0
- package/src/components/ds-site-node/ds-site-node.module.scss +59 -0
- package/src/components/ds-site-node/ds-site-node.tsx +73 -0
- package/src/components/ds-site-node/ds-site-node.types.ts +36 -0
- package/src/components/ds-site-node/hooks/use-is-overflowing.ts +31 -0
- package/src/components/ds-site-node/index.ts +3 -0
- package/src/components/ds-skeleton/ds-skeleton-circle.tsx +2 -0
- package/src/components/ds-skeleton/ds-skeleton-rect.tsx +2 -0
- package/src/components/ds-skeleton/ds-skeleton-text.tsx +2 -0
- package/src/components/ds-skeleton/ds-skeleton.ts +7 -1
- package/src/components/ds-smart-tabs/ds-smart-tabs.tsx +7 -2
- package/src/components/ds-spinner/ds-spinner.figma.ts +19 -0
- package/src/components/ds-spinner/ds-spinner.tsx +2 -0
- package/src/components/ds-split-button/ds-split-button.figma.ts +2 -2
- package/src/components/ds-split-button/ds-split-button.tsx +6 -0
- package/src/components/ds-status-badge/ds-status-badge.tsx +2 -0
- package/src/components/ds-status-badge-v2/ds-status-badge-v2.figma.ts +2 -2
- package/src/components/ds-status-badge-v2/index.ts +2 -0
- package/src/components/ds-stepper/components/ds-step-content.tsx +2 -0
- package/src/components/ds-stepper/components/ds-step-next-button.tsx +2 -0
- package/src/components/ds-stepper/components/ds-step.tsx +2 -0
- package/src/components/ds-stepper/ds-stepper.figma.ts +38 -0
- package/src/components/ds-stepper/ds-stepper.tsx +1 -0
- package/src/components/ds-system-status/ds-system-status.tsx +2 -0
- package/src/components/ds-table/components/ds-table-group-header-cell/index.ts +0 -1
- package/src/components/ds-table/components/ds-table-header/ds-table-header.module.scss +2 -2
- package/src/components/ds-table/components/ds-table-header/ds-table-header.tsx +2 -4
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-checkbox.tsx +1 -0
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-date.tsx +1 -0
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-number.tsx +1 -0
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-select.tsx +1 -0
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-text.tsx +1 -0
- package/src/components/ds-table/components/edit/ds-table-editable-cell/ds-table-editable-cell.tsx +1 -0
- package/src/components/ds-table/components/edit/ds-table-editing-cell/ds-table-editing-cell.tsx +1 -0
- package/src/components/ds-table/ds-table.module.scss +15 -0
- package/src/components/ds-table/ds-table.tsx +39 -34
- package/src/components/ds-table/ds-table.types.ts +6 -0
- package/src/components/ds-table/figma/ds-table-expandable.figma.ts +2 -2
- package/src/components/ds-table/figma/ds-table.figma.ts +2 -2
- package/src/components/ds-table/index.ts +3 -0
- package/src/components/ds-tabs/components/ds-tabs-content/ds-tabs-content.tsx +2 -0
- package/src/components/ds-tabs/components/ds-tabs-list/ds-tabs-list.tsx +2 -0
- package/src/components/ds-tabs/components/ds-tabs-tab/ds-tabs-tab.tsx +2 -0
- package/src/components/ds-tabs/ds-tabs.tsx +2 -0
- package/src/components/ds-tabs/figma/ds-tabs-tab-vertical.figma.ts +2 -2
- package/src/components/ds-tabs/figma/ds-tabs-tab.figma.ts +2 -2
- package/src/components/ds-tabs/figma/ds-tabs-vertical.figma.ts +2 -2
- package/src/components/ds-tabs/figma/ds-tabs.figma.ts +2 -2
- package/src/components/ds-tag/ds-tag.tsx +2 -0
- package/src/components/ds-tag-filter/ds-tag-filter.tsx +2 -0
- package/src/components/ds-text-input/ds-input-field-v02.figma.ts +87 -0
- package/src/components/ds-text-input/ds-text-input.figma.ts +2 -2
- package/src/components/ds-text-input/ds-text-input.tsx +2 -0
- package/src/components/ds-textarea/ds-textarea.tsx +2 -0
- package/src/components/ds-time-picker/ds-time-picker.figma.ts +2 -2
- package/src/components/ds-time-picker/ds-time-picker.tsx +2 -0
- package/src/components/ds-toast/ds-toast-context.tsx +1 -0
- package/src/components/ds-toast/ds-toast.figma.ts +34 -0
- package/src/components/ds-toast/ds-toast.tsx +3 -0
- package/src/components/ds-toggle/ds-toggle.figma.ts +39 -0
- package/src/components/ds-toggle/ds-toggle.tsx +2 -0
- package/src/components/ds-tooltip/ds-tooltip.figma.ts +16 -0
- package/src/components/ds-tooltip/ds-tooltip.module.scss +8 -1
- package/src/components/ds-tooltip/ds-tooltip.tsx +35 -15
- package/src/components/ds-tooltip/ds-tooltip.types.ts +40 -0
- package/src/components/ds-tree/ds-tree.module.scss +2 -2
- package/src/components/ds-tree/ds-tree.tsx +22 -0
- package/src/components/ds-tree/ds-tree.types.ts +16 -0
- package/src/components/ds-typography/ds-typography.config.ts +1 -1
- package/src/components/ds-typography/ds-typography.figma.ts +63 -0
- package/src/components/ds-typography/ds-typography.module.scss +16 -0
- package/src/components/ds-typography/ds-typography.tsx +64 -7
- package/src/components/ds-typography/ds-typography.types.ts +13 -0
- package/src/components/ds-typography/hooks/use-truncation.ts +151 -0
- package/src/components/ds-user-card/ds-user-card.figma.ts +16 -0
- package/src/components/ds-user-card/ds-user-card.module.scss +25 -0
- package/src/components/ds-user-card/ds-user-card.tsx +31 -0
- package/src/components/ds-user-card/ds-user-card.types.ts +26 -0
- package/src/components/ds-user-card/index.ts +2 -0
- package/src/components/ds-vertical-tabs/ds-vertical-tabs.tsx +17 -4
- package/src/components/ds-workspace-layout/ds-workspace-layout.tsx +19 -8
- package/src/index.ts +2 -0
- package/src/styles/_root.scss +468 -363
- package/src/styles/shared/_dropdown.scss +2 -2
- package/src/styles/styles.scss +0 -3
- package/src/styles/_colors.scss +0 -65
- package/src/styles/_root_new.scss +0 -451
- package/src/styles/_spacing.scss +0 -47
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
import type { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
+
export const tooltipPlacements = [
|
|
4
|
+
'top',
|
|
5
|
+
'top-start',
|
|
6
|
+
'top-end',
|
|
7
|
+
'bottom',
|
|
8
|
+
'bottom-start',
|
|
9
|
+
'bottom-end',
|
|
10
|
+
'left',
|
|
11
|
+
'left-start',
|
|
12
|
+
'left-end',
|
|
13
|
+
'right',
|
|
14
|
+
'right-start',
|
|
15
|
+
'right-end',
|
|
16
|
+
] as const;
|
|
17
|
+
|
|
18
|
+
export type TooltipPlacement = (typeof tooltipPlacements)[number];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Viewport-relative rect (CSS pixels) the tooltip anchors to, instead of the trigger.
|
|
22
|
+
*/
|
|
23
|
+
export interface TooltipAnchorRect {
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
3
30
|
export interface DsTooltipProps {
|
|
4
31
|
/**
|
|
5
32
|
* Tooltip content
|
|
@@ -9,6 +36,19 @@ export interface DsTooltipProps {
|
|
|
9
36
|
* The content to be rendered inside the tooltip
|
|
10
37
|
*/
|
|
11
38
|
children: ReactNode;
|
|
39
|
+
/**
|
|
40
|
+
* Placement relative to the trigger; `-start` / `-end` align to that edge.
|
|
41
|
+
*/
|
|
42
|
+
placement?: TooltipPlacement;
|
|
43
|
+
/**
|
|
44
|
+
* When true the trigger renders but the tooltip never opens.
|
|
45
|
+
*/
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Anchors the tooltip to a virtual rect instead of the trigger, re-evaluated on
|
|
49
|
+
* each reposition. Return `null` to fall back to the trigger.
|
|
50
|
+
*/
|
|
51
|
+
getAnchorRect?: () => TooltipAnchorRect | null;
|
|
12
52
|
/**
|
|
13
53
|
* Props forwarded to nested sub-components.
|
|
14
54
|
*/
|
|
@@ -27,7 +27,7 @@ $transition-duration: 0.2s;
|
|
|
27
27
|
background: var(--background-action-hover-weak);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
&:focus-visible {
|
|
31
31
|
position: relative;
|
|
32
32
|
outline: none;
|
|
33
33
|
background: var(--background-action-hover-weak);
|
|
@@ -56,7 +56,7 @@ $transition-duration: 0.2s;
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
&:hover .itemAction,
|
|
59
|
-
|
|
59
|
+
&:focus-within .itemAction {
|
|
60
60
|
opacity: 1;
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -38,6 +38,9 @@ const DsTreeRoot = <T extends DsTreeNode = DsTreeNode>({
|
|
|
38
38
|
checkedValue,
|
|
39
39
|
defaultCheckedValue,
|
|
40
40
|
onCheckedChange,
|
|
41
|
+
focusedValue,
|
|
42
|
+
defaultFocusedValue,
|
|
43
|
+
onFocusChange,
|
|
41
44
|
typeahead = true,
|
|
42
45
|
lazyMount = true,
|
|
43
46
|
unmountOnExit,
|
|
@@ -56,6 +59,9 @@ const DsTreeRoot = <T extends DsTreeNode = DsTreeNode>({
|
|
|
56
59
|
checkedValue={checkedValue}
|
|
57
60
|
defaultCheckedValue={defaultCheckedValue}
|
|
58
61
|
onCheckedChange={onCheckedChange}
|
|
62
|
+
focusedValue={focusedValue}
|
|
63
|
+
defaultFocusedValue={defaultFocusedValue}
|
|
64
|
+
onFocusChange={onFocusChange}
|
|
59
65
|
typeahead={typeahead}
|
|
60
66
|
lazyMount={lazyMount}
|
|
61
67
|
unmountOnExit={unmountOnExit}
|
|
@@ -153,6 +159,22 @@ const DsTreeItemAction = ({ className, style, children, onClick }: DsTreeItemAct
|
|
|
153
159
|
</button>
|
|
154
160
|
);
|
|
155
161
|
|
|
162
|
+
DsTreeRoot.displayName = 'DsTree.Root';
|
|
163
|
+
DsTreeTree.displayName = 'DsTree.Tree';
|
|
164
|
+
Object.defineProperty(TreeView.NodeProvider, 'displayName', { value: 'DsTree.NodeProvider' });
|
|
165
|
+
Object.defineProperty(TreeView.NodeContext, 'displayName', { value: 'DsTree.NodeContext' });
|
|
166
|
+
DsTreeBranch.displayName = 'DsTree.Branch';
|
|
167
|
+
DsTreeBranchControl.displayName = 'DsTree.BranchControl';
|
|
168
|
+
DsTreeBranchIndicator.displayName = 'DsTree.BranchIndicator';
|
|
169
|
+
DsTreeBranchText.displayName = 'DsTree.BranchText';
|
|
170
|
+
DsTreeBranchContent.displayName = 'DsTree.BranchContent';
|
|
171
|
+
DsTreeBranchIndentGuide.displayName = 'DsTree.BranchIndentGuide';
|
|
172
|
+
DsTreeItem.displayName = 'DsTree.Item';
|
|
173
|
+
DsTreeItemText.displayName = 'DsTree.ItemText';
|
|
174
|
+
DsTreeItemIndicator.displayName = 'DsTree.ItemIndicator';
|
|
175
|
+
DsTreeItemAction.displayName = 'DsTree.ItemAction';
|
|
176
|
+
DsTreeNodeCheckbox.displayName = 'DsTree.NodeCheckbox';
|
|
177
|
+
|
|
156
178
|
export const DsTree = {
|
|
157
179
|
Root: DsTreeRoot,
|
|
158
180
|
Tree: DsTreeTree,
|
|
@@ -115,6 +115,22 @@ export interface DsTreeRootProps<T extends DsTreeNode = DsTreeNode> extends DsTr
|
|
|
115
115
|
*/
|
|
116
116
|
onCheckedChange?: ArkTreeView.RootProps<T>['onCheckedChange'];
|
|
117
117
|
|
|
118
|
+
/**
|
|
119
|
+
* Id of the node with keyboard focus (controlled). Use with `onFocusChange`.
|
|
120
|
+
* When `null`, Ark treats the first node as focused for roving-tabindex purposes.
|
|
121
|
+
*/
|
|
122
|
+
focusedValue?: string | null;
|
|
123
|
+
/**
|
|
124
|
+
* Id of the node focused initially when uncontrolled. When `null` (the Ark
|
|
125
|
+
* default), the first node receives focus for roving-tabindex purposes.
|
|
126
|
+
*/
|
|
127
|
+
defaultFocusedValue?: string | null;
|
|
128
|
+
/**
|
|
129
|
+
* Called when the focused node changes. Receives the Ark focus-change details
|
|
130
|
+
* including the new `focusedValue` (or `null` when nothing is focused).
|
|
131
|
+
*/
|
|
132
|
+
onFocusChange?: ArkTreeView.RootProps<T>['onFocusChange'];
|
|
133
|
+
|
|
118
134
|
/**
|
|
119
135
|
* Whether to enable typeahead navigation — typing characters focuses matching nodes.
|
|
120
136
|
*/
|
|
@@ -30,7 +30,7 @@ export const typographyVariantConfig = {
|
|
|
30
30
|
heading4: { element: 'h4', component: ark.h4 },
|
|
31
31
|
} as const;
|
|
32
32
|
|
|
33
|
-
/** Semantic text colors backed by `--font-*` tokens in `
|
|
33
|
+
/** Semantic text colors backed by `--font-*` tokens in `_root.scss`. */
|
|
34
34
|
export const typographyColors = [
|
|
35
35
|
'main',
|
|
36
36
|
'secondary',
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=39324-248
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-typography
|
|
3
|
+
// component=DsTypography
|
|
4
|
+
import figma from 'figma';
|
|
5
|
+
|
|
6
|
+
const instance = figma.selectedInstance;
|
|
7
|
+
|
|
8
|
+
const variant = instance.getEnum('font-style', {
|
|
9
|
+
heading1: 'heading1',
|
|
10
|
+
heading2: 'heading2',
|
|
11
|
+
heading3: 'heading3',
|
|
12
|
+
heading4: 'heading4',
|
|
13
|
+
'body-md-reg': 'body-md-reg',
|
|
14
|
+
'body-md-md': 'body-md-md',
|
|
15
|
+
'body-md-semi-bold': 'body-md-semi-bold',
|
|
16
|
+
'body-md-bold': 'body-md-bold',
|
|
17
|
+
'body-md-link': 'body-md-link',
|
|
18
|
+
'body-sm-reg': 'body-sm-reg',
|
|
19
|
+
'body-sm-md': 'body-sm-md',
|
|
20
|
+
'body-sm-semi-bold': 'body-sm-semi-bold',
|
|
21
|
+
'body-sm-bold': 'body-sm-bold',
|
|
22
|
+
'body-sm-link': 'body-sm-link',
|
|
23
|
+
'body-xs-reg': 'body-xs-reg',
|
|
24
|
+
'body-xs-md': 'body-xs-md',
|
|
25
|
+
'body-xs-semi-bold': 'body-xs-semi-bold',
|
|
26
|
+
'body-xs-bold': 'body-xs-bold',
|
|
27
|
+
'body-xs-link': 'body-xs-link',
|
|
28
|
+
'code-sm-reg': 'code-sm-reg',
|
|
29
|
+
'code-sm-semi-bold': 'code-sm-semi-bold',
|
|
30
|
+
'code-xs-reg': 'code-xs-reg',
|
|
31
|
+
'code-xs-semi-bold': 'code-xs-semi-bold',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const color = instance.getEnum('color', {
|
|
35
|
+
main: 'main',
|
|
36
|
+
secondary: 'secondary',
|
|
37
|
+
action: 'action',
|
|
38
|
+
'action-hover': 'action-hover',
|
|
39
|
+
'action-secondary': 'action-secondary',
|
|
40
|
+
'action-secondary-hover': 'action-secondary-hover',
|
|
41
|
+
disabled: 'disabled',
|
|
42
|
+
'light-disabled': 'light-disabled',
|
|
43
|
+
'on-action': 'on-action',
|
|
44
|
+
'on-disabled': 'on-disabled',
|
|
45
|
+
placeholder: 'placeholder',
|
|
46
|
+
highlight: 'highlight',
|
|
47
|
+
success: 'success',
|
|
48
|
+
warning: 'warning',
|
|
49
|
+
error: 'error',
|
|
50
|
+
code: 'code',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const textNode = instance.children.find((child): child is figma.TextHandle => child.type === 'TEXT');
|
|
54
|
+
const text = textNode?.textContent ?? 'Text';
|
|
55
|
+
|
|
56
|
+
const colorProp = color === 'main' ? '' : figma.code` color="${color}"`;
|
|
57
|
+
|
|
58
|
+
export default {
|
|
59
|
+
example: figma.code`<DsTypography variant="${variant}"${colorProp}>${text}</DsTypography>`,
|
|
60
|
+
imports: ["import { DsTypography } from '@drivenets/design-system';"],
|
|
61
|
+
id: 'ds-typography',
|
|
62
|
+
metadata: { nestable: true },
|
|
63
|
+
} satisfies figma.Template;
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
@use '../../styles/typography';
|
|
2
2
|
|
|
3
|
+
.truncateSingle {
|
|
4
|
+
display: block;
|
|
5
|
+
max-width: 100%;
|
|
6
|
+
overflow: hidden;
|
|
7
|
+
white-space: nowrap;
|
|
8
|
+
text-overflow: ellipsis;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.truncateMultiline {
|
|
12
|
+
display: -webkit-box;
|
|
13
|
+
-webkit-box-orient: vertical;
|
|
14
|
+
-webkit-line-clamp: var(--ds-typography-line-clamp);
|
|
15
|
+
line-clamp: var(--ds-typography-line-clamp);
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
}
|
|
18
|
+
|
|
3
19
|
.heading1 {
|
|
4
20
|
@include typography.heading1;
|
|
5
21
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { type CSSProperties, useRef } from 'react';
|
|
1
2
|
import classNames from 'classnames';
|
|
2
3
|
import type { DsTypographyProps } from './ds-typography.types';
|
|
3
4
|
import { typographyColors, typographyVariantConfig } from './ds-typography.config';
|
|
5
|
+
import { useTruncation } from './hooks/use-truncation';
|
|
6
|
+
import { mergeRefs } from '../../utils/merge-refs';
|
|
7
|
+
import { DsTooltip } from '../ds-tooltip';
|
|
4
8
|
import styles from './ds-typography.module.scss';
|
|
5
9
|
|
|
6
10
|
const semanticColorSet = new Set<string>(typographyColors);
|
|
@@ -8,6 +12,9 @@ const semanticColorSet = new Set<string>(typographyColors);
|
|
|
8
12
|
const resolveColor = (color: string): string =>
|
|
9
13
|
semanticColorSet.has(color) ? `var(--font-${color})` : color;
|
|
10
14
|
|
|
15
|
+
const resolveLineClamp = (truncate: boolean | number): number =>
|
|
16
|
+
typeof truncate === 'number' ? Math.max(1, Math.floor(truncate)) : 1;
|
|
17
|
+
|
|
11
18
|
/*
|
|
12
19
|
* Design system Typography component that provides consistent text styling
|
|
13
20
|
*/
|
|
@@ -18,25 +25,75 @@ const DsTypography = ({
|
|
|
18
25
|
className,
|
|
19
26
|
style,
|
|
20
27
|
color,
|
|
28
|
+
truncate = false,
|
|
29
|
+
tooltip = false,
|
|
30
|
+
tooltipContent,
|
|
21
31
|
children,
|
|
22
32
|
...props
|
|
23
33
|
}: DsTypographyProps) => {
|
|
24
34
|
const Component = typographyVariantConfig[variant].component;
|
|
25
35
|
|
|
26
|
-
|
|
36
|
+
const internalRef = useRef<HTMLElement>(null);
|
|
37
|
+
|
|
38
|
+
const truncationEnabled = truncate !== false;
|
|
39
|
+
const lineClamp = resolveLineClamp(truncate);
|
|
40
|
+
const isMultiline = truncationEnabled && lineClamp > 1;
|
|
41
|
+
|
|
42
|
+
const tooltipEnabled = truncationEnabled && tooltip;
|
|
43
|
+
const { isTruncated, getAnchorRect } = useTruncation(internalRef, tooltipEnabled, [children, truncate]);
|
|
44
|
+
|
|
45
|
+
let resolvedStyle: CSSProperties | undefined;
|
|
46
|
+
|
|
47
|
+
if (color || isMultiline || style) {
|
|
48
|
+
resolvedStyle = {};
|
|
49
|
+
|
|
50
|
+
if (color) {
|
|
51
|
+
resolvedStyle.color = resolveColor(color);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (isMultiline) {
|
|
55
|
+
Object.assign(resolvedStyle, { '--ds-typography-line-clamp': lineClamp });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (style) {
|
|
59
|
+
Object.assign(resolvedStyle, style);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const truncateClass = truncationEnabled
|
|
64
|
+
? isMultiline
|
|
65
|
+
? styles.truncateMultiline
|
|
66
|
+
: styles.truncateSingle
|
|
67
|
+
: undefined;
|
|
68
|
+
|
|
69
|
+
const element = (
|
|
27
70
|
<Component
|
|
28
|
-
|
|
29
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
30
|
-
// @ts-expect-error
|
|
31
|
-
ref={ref}
|
|
71
|
+
ref={mergeRefs(ref, internalRef)}
|
|
32
72
|
asChild={asChild}
|
|
33
|
-
className={classNames(styles[variant], className)}
|
|
34
|
-
style={
|
|
73
|
+
className={classNames(styles[variant], truncateClass, className)}
|
|
74
|
+
style={resolvedStyle}
|
|
35
75
|
{...props}
|
|
36
76
|
>
|
|
37
77
|
{children}
|
|
38
78
|
</Component>
|
|
39
79
|
);
|
|
80
|
+
|
|
81
|
+
if (!tooltipEnabled) {
|
|
82
|
+
return element;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<DsTooltip
|
|
87
|
+
content={tooltipContent ?? children}
|
|
88
|
+
placement="top"
|
|
89
|
+
disabled={!isTruncated}
|
|
90
|
+
getAnchorRect={getAnchorRect}
|
|
91
|
+
>
|
|
92
|
+
{element}
|
|
93
|
+
</DsTooltip>
|
|
94
|
+
);
|
|
40
95
|
};
|
|
41
96
|
|
|
97
|
+
DsTypography.displayName = 'DsTypography';
|
|
98
|
+
|
|
42
99
|
export default DsTypography;
|
|
@@ -31,6 +31,19 @@ export interface DsTypographyProps {
|
|
|
31
31
|
* When true, composes typography styles onto the child element without extra DOM nodes
|
|
32
32
|
*/
|
|
33
33
|
asChild?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Truncates overflowing text with an ellipsis. A number clamps to that many lines
|
|
36
|
+
* (`true` is a single line). Needs a width-constrained layout context.
|
|
37
|
+
*/
|
|
38
|
+
truncate?: boolean | number;
|
|
39
|
+
/**
|
|
40
|
+
* Reveals the full text in a tooltip on hover/focus, but only while it overflows.
|
|
41
|
+
*/
|
|
42
|
+
tooltip?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Tooltip content override; defaults to `children`.
|
|
45
|
+
*/
|
|
46
|
+
tooltipContent?: React.ReactNode;
|
|
34
47
|
/**
|
|
35
48
|
* The content of the component
|
|
36
49
|
*/
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { type RefObject, useCallback, useLayoutEffect, useState } from 'react';
|
|
2
|
+
import type { TooltipAnchorRect } from '../../ds-tooltip';
|
|
3
|
+
|
|
4
|
+
const OVERFLOW_TOLERANCE_PX = 1;
|
|
5
|
+
const FALLBACK_LINE_HEIGHT_RATIO = 1.2;
|
|
6
|
+
const DEFAULT_FONT_SIZE_PX = 16;
|
|
7
|
+
const ELLIPSIS = '\u2026';
|
|
8
|
+
|
|
9
|
+
interface Truncation {
|
|
10
|
+
isTruncated: boolean;
|
|
11
|
+
getAnchorRect: () => TooltipAnchorRect | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const ellipsisWidthCache = new Map<string, number>();
|
|
15
|
+
let ellipsisMeasureSpan: HTMLSpanElement | null = null;
|
|
16
|
+
|
|
17
|
+
const measureEllipsisWidth = (computed: CSSStyleDeclaration): number => {
|
|
18
|
+
const cacheKey = `${computed.fontStyle}|${computed.fontWeight}|${computed.fontSize}|${computed.fontFamily}|${computed.letterSpacing}`;
|
|
19
|
+
const cached = ellipsisWidthCache.get(cacheKey);
|
|
20
|
+
|
|
21
|
+
if (cached !== undefined) {
|
|
22
|
+
return cached;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
ellipsisMeasureSpan ??= document.createElement('span');
|
|
26
|
+
const span = ellipsisMeasureSpan;
|
|
27
|
+
|
|
28
|
+
span.textContent = ELLIPSIS;
|
|
29
|
+
span.style.position = 'absolute';
|
|
30
|
+
span.style.visibility = 'hidden';
|
|
31
|
+
span.style.whiteSpace = 'pre';
|
|
32
|
+
span.style.fontStyle = computed.fontStyle;
|
|
33
|
+
span.style.fontWeight = computed.fontWeight;
|
|
34
|
+
span.style.fontSize = computed.fontSize;
|
|
35
|
+
span.style.fontFamily = computed.fontFamily;
|
|
36
|
+
span.style.letterSpacing = computed.letterSpacing;
|
|
37
|
+
|
|
38
|
+
document.body.appendChild(span);
|
|
39
|
+
const width = span.getBoundingClientRect().width;
|
|
40
|
+
span.remove();
|
|
41
|
+
|
|
42
|
+
ellipsisWidthCache.set(cacheKey, width);
|
|
43
|
+
return width;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
let measureRange: Range | null = null;
|
|
47
|
+
|
|
48
|
+
const measureFittingPrefixRight = (textNode: Text, maxRight: number): number => {
|
|
49
|
+
measureRange ??= document.createRange();
|
|
50
|
+
const range = measureRange;
|
|
51
|
+
|
|
52
|
+
let low = 0;
|
|
53
|
+
let high = textNode.length;
|
|
54
|
+
let fittingLength = 0;
|
|
55
|
+
|
|
56
|
+
while (low <= high) {
|
|
57
|
+
const mid = (low + high) >>> 1;
|
|
58
|
+
range.setStart(textNode, 0);
|
|
59
|
+
range.setEnd(textNode, mid);
|
|
60
|
+
|
|
61
|
+
if (range.getBoundingClientRect().right <= maxRight) {
|
|
62
|
+
fittingLength = mid;
|
|
63
|
+
low = mid + 1;
|
|
64
|
+
} else {
|
|
65
|
+
high = mid - 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
range.setStart(textNode, 0);
|
|
70
|
+
range.setEnd(textNode, fittingLength);
|
|
71
|
+
return range.getBoundingClientRect().right;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const getFirstTextNode = (element: HTMLElement): Text | null =>
|
|
75
|
+
element.firstChild instanceof Text ? element.firstChild : null;
|
|
76
|
+
|
|
77
|
+
export const useTruncation = (
|
|
78
|
+
ref: RefObject<HTMLElement | null>,
|
|
79
|
+
enabled: boolean,
|
|
80
|
+
deps: readonly unknown[] = [],
|
|
81
|
+
): Truncation => {
|
|
82
|
+
const [isTruncated, setIsTruncated] = useState(false);
|
|
83
|
+
|
|
84
|
+
useLayoutEffect(() => {
|
|
85
|
+
const element = ref.current;
|
|
86
|
+
|
|
87
|
+
if (!enabled || !element) {
|
|
88
|
+
setIsTruncated(false);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const measure = () => {
|
|
93
|
+
const overflowsHorizontally = element.scrollWidth - element.clientWidth > OVERFLOW_TOLERANCE_PX;
|
|
94
|
+
const overflowsVertically = element.scrollHeight - element.clientHeight > OVERFLOW_TOLERANCE_PX;
|
|
95
|
+
|
|
96
|
+
setIsTruncated(overflowsHorizontally || overflowsVertically);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const rafId = requestAnimationFrame(measure);
|
|
100
|
+
|
|
101
|
+
const resizeObserver = new ResizeObserver(() => requestAnimationFrame(measure));
|
|
102
|
+
resizeObserver.observe(element);
|
|
103
|
+
|
|
104
|
+
return () => {
|
|
105
|
+
cancelAnimationFrame(rafId);
|
|
106
|
+
resizeObserver.disconnect();
|
|
107
|
+
};
|
|
108
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
109
|
+
}, [ref, enabled, ...deps]);
|
|
110
|
+
|
|
111
|
+
const getAnchorRect = useCallback((): TooltipAnchorRect | null => {
|
|
112
|
+
const element = ref.current;
|
|
113
|
+
|
|
114
|
+
if (!element) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const rect = element.getBoundingClientRect();
|
|
119
|
+
const computed = getComputedStyle(element);
|
|
120
|
+
|
|
121
|
+
const paddingRight = parseFloat(computed.paddingRight) || 0;
|
|
122
|
+
const borderRight = parseFloat(computed.borderRightWidth) || 0;
|
|
123
|
+
const paddingBottom = parseFloat(computed.paddingBottom) || 0;
|
|
124
|
+
const borderBottom = parseFloat(computed.borderBottomWidth) || 0;
|
|
125
|
+
|
|
126
|
+
const fontSize = parseFloat(computed.fontSize) || DEFAULT_FONT_SIZE_PX;
|
|
127
|
+
const lineHeight = parseFloat(computed.lineHeight) || fontSize * FALLBACK_LINE_HEIGHT_RATIO;
|
|
128
|
+
|
|
129
|
+
const contentRight = rect.right - paddingRight - borderRight;
|
|
130
|
+
const ellipsisWidth = measureEllipsisWidth(computed);
|
|
131
|
+
|
|
132
|
+
const textNode = getFirstTextNode(element);
|
|
133
|
+
const isSingleLine = computed.whiteSpace === 'nowrap';
|
|
134
|
+
|
|
135
|
+
const ellipsisCenterX =
|
|
136
|
+
isSingleLine && textNode
|
|
137
|
+
? measureFittingPrefixRight(textNode, contentRight - ellipsisWidth) + ellipsisWidth / 2
|
|
138
|
+
: contentRight - ellipsisWidth / 2;
|
|
139
|
+
|
|
140
|
+
const lastLineBottom = rect.bottom - paddingBottom - borderBottom;
|
|
141
|
+
|
|
142
|
+
return {
|
|
143
|
+
x: ellipsisCenterX,
|
|
144
|
+
y: lastLineBottom - lineHeight,
|
|
145
|
+
width: 0,
|
|
146
|
+
height: lineHeight,
|
|
147
|
+
};
|
|
148
|
+
}, [ref]);
|
|
149
|
+
|
|
150
|
+
return { isTruncated, getAnchorRect };
|
|
151
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=38540-44159
|
|
2
|
+
// source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-user-card
|
|
3
|
+
// component=DsUserCard
|
|
4
|
+
//
|
|
5
|
+
// `DAP_user-menu-header_v01` (#38540:44159) is a plain composed instance with no
|
|
6
|
+
// variant props, so it maps directly to `DsUserCard`. `name` and `subtitle` are text
|
|
7
|
+
// content and `src` is a photo URL — none are derivable from Figma — so they are
|
|
8
|
+
// emitted as placeholders for the developer to fill in (see `ds-select.figma.ts`).
|
|
9
|
+
import figma from 'figma';
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
example: figma.code`<DsUserCard name="Full Name" subtitle="subtitle" />`,
|
|
13
|
+
imports: ["import { DsUserCard } from '@drivenets/design-system';"],
|
|
14
|
+
id: 'ds-user-card',
|
|
15
|
+
metadata: { nestable: true },
|
|
16
|
+
} satisfies figma.Template;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
.userCard {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
gap: var(--xs);
|
|
5
|
+
padding: var(--sm);
|
|
6
|
+
border-bottom: 1px solid var(--border-secondary);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.text {
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
flex: 1;
|
|
13
|
+
gap: var(--3xs);
|
|
14
|
+
padding-top: var(--4xs);
|
|
15
|
+
min-width: 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.name,
|
|
19
|
+
.subtitle {
|
|
20
|
+
display: block;
|
|
21
|
+
max-width: 100%;
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
white-space: nowrap;
|
|
24
|
+
text-overflow: ellipsis;
|
|
25
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import styles from './ds-user-card.module.scss';
|
|
4
|
+
import type { DsUserCardProps } from './ds-user-card.types';
|
|
5
|
+
import { DsAvatar } from '../ds-avatar';
|
|
6
|
+
import { DsTypography } from '../ds-typography';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @summary Compact identity header pairing an avatar with a name and optional subtitle.
|
|
10
|
+
*
|
|
11
|
+
* Presentational card used as the header of a user menu. Renders a medium
|
|
12
|
+
* `DsAvatar` (initials fallback derived from `name`) beside a two-line text
|
|
13
|
+
* block; both lines truncate with an ellipsis when they overflow.
|
|
14
|
+
*/
|
|
15
|
+
export const DsUserCard: FC<DsUserCardProps> = ({ name, subtitle, src, className, style }) => {
|
|
16
|
+
return (
|
|
17
|
+
<div className={classNames(styles.userCard, className)} style={style}>
|
|
18
|
+
<DsAvatar name={name} src={src} size="md" />
|
|
19
|
+
<div className={styles.text}>
|
|
20
|
+
<DsTypography variant="heading4" color="main" className={styles.name}>
|
|
21
|
+
{name}
|
|
22
|
+
</DsTypography>
|
|
23
|
+
{subtitle && (
|
|
24
|
+
<DsTypography variant="body-xs-reg" color="secondary" className={styles.subtitle}>
|
|
25
|
+
{subtitle}
|
|
26
|
+
</DsTypography>
|
|
27
|
+
)}
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CSSProperties } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface DsUserCardProps {
|
|
4
|
+
/**
|
|
5
|
+
* Full name shown as the title. Also drives the avatar initials fallback,
|
|
6
|
+
* image alt text, and hover tooltip.
|
|
7
|
+
*/
|
|
8
|
+
name: string;
|
|
9
|
+
/**
|
|
10
|
+
* Secondary line rendered under the name, such as an email address or role.
|
|
11
|
+
*/
|
|
12
|
+
subtitle?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Avatar image URL. Falls back to initials derived from `name` when omitted
|
|
15
|
+
* or when the image fails to load.
|
|
16
|
+
*/
|
|
17
|
+
src?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Custom class name applied to the root element.
|
|
20
|
+
*/
|
|
21
|
+
className?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Custom inline styles applied to the root element.
|
|
24
|
+
*/
|
|
25
|
+
style?: CSSProperties;
|
|
26
|
+
}
|
|
@@ -26,7 +26,13 @@ import styles from './ds-vertical-tabs.module.scss';
|
|
|
26
26
|
* </DsVerticalTabs>
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
|
-
const
|
|
29
|
+
const DsVerticalTabsRoot = ({
|
|
30
|
+
value,
|
|
31
|
+
onValueChange,
|
|
32
|
+
className,
|
|
33
|
+
style,
|
|
34
|
+
children,
|
|
35
|
+
}: DsVerticalTabsRootProps) => {
|
|
30
36
|
const handleValueChange = (details: { value: string | null }) => {
|
|
31
37
|
onValueChange?.(details.value);
|
|
32
38
|
};
|
|
@@ -73,8 +79,15 @@ const DsVerticalTabsContent = ({ value, className, children }: DsVerticalTabsCon
|
|
|
73
79
|
);
|
|
74
80
|
};
|
|
75
81
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
DsVerticalTabsList.displayName = 'DsVerticalTabs.List';
|
|
83
|
+
DsVerticalTabsTab.displayName = 'DsVerticalTabs.Tab';
|
|
84
|
+
DsVerticalTabsContent.displayName = 'DsVerticalTabs.Content';
|
|
85
|
+
|
|
86
|
+
const DsVerticalTabs = Object.assign(DsVerticalTabsRoot, {
|
|
87
|
+
displayName: 'DsVerticalTabs',
|
|
88
|
+
List: DsVerticalTabsList,
|
|
89
|
+
Tab: DsVerticalTabsTab,
|
|
90
|
+
Content: DsVerticalTabsContent,
|
|
91
|
+
});
|
|
79
92
|
|
|
80
93
|
export default DsVerticalTabs;
|