@drivenets/design-system 0.14.0 → 0.16.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.
Files changed (193) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +1 -1
  3. package/dist/index.cjs +1239 -262
  4. package/dist/index.d.cts +904 -1169
  5. package/dist/index.d.cts.map +1 -1
  6. package/dist/index.d.ts +904 -1169
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +1221 -258
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.min.css +1 -1
  11. package/package.json +15 -12
  12. package/src/components/ds-alert-banner/ds-alert-banner.tsx +11 -2
  13. package/src/components/ds-autocomplete/ds-autocomplete.figma.ts +36 -0
  14. package/src/components/ds-autocomplete/ds-autocomplete.tsx +2 -0
  15. package/src/components/ds-avatar/ds-avatar.figma.ts +30 -0
  16. package/src/components/ds-avatar/ds-avatar.tsx +6 -1
  17. package/src/components/ds-avatar/ds-avatar.types.ts +5 -2
  18. package/src/components/ds-avatar-group/ds-avatar-group.figma.ts +27 -0
  19. package/src/components/ds-avatar-group/ds-avatar-group.tsx +6 -1
  20. package/src/components/ds-avatar-group/ds-avatar-group.types.ts +3 -1
  21. package/src/components/ds-breadcrumb/ds-breadcrumb.figma.ts +19 -0
  22. package/src/components/ds-breadcrumb/ds-breadcrumb.tsx +2 -0
  23. package/src/components/ds-button/ds-button.tsx +2 -0
  24. package/src/components/ds-button-v3/ds-button-v3.figma.ts +1 -1
  25. package/src/components/ds-button-v3/ds-button-v3.tsx +6 -0
  26. package/src/components/ds-button-v3/index.ts +2 -0
  27. package/src/components/ds-card/ds-card.tsx +7 -3
  28. package/src/components/ds-catalog-layout/ds-catalog-layout.tsx +8 -0
  29. package/src/components/ds-checkbox/ds-checkbox-level-2.figma.ts +40 -0
  30. package/src/components/ds-checkbox/ds-checkbox.figma.ts +45 -0
  31. package/src/components/ds-checkbox/ds-checkbox.module.scss +1 -1
  32. package/src/components/ds-checkbox/ds-checkbox.tsx +9 -1
  33. package/src/components/ds-checkbox-group/ds-checkbox-group.figma.ts +15 -0
  34. package/src/components/ds-checkbox-group/ds-checkbox-group.tsx +2 -0
  35. package/src/components/ds-chip/ds-chip.tsx +2 -0
  36. package/src/components/ds-chip-group/ds-chip-group.tsx +2 -0
  37. package/src/components/ds-comment-bubble/components/ds-comment-thread/ds-comment-thread.tsx +1 -0
  38. package/src/components/ds-comment-bubble/components/ds-thread-item/ds-thread-item.tsx +1 -0
  39. package/src/components/ds-comment-bubble/ds-comment-bubble.tsx +1 -0
  40. package/src/components/ds-comment-card/ds-comment-card.tsx +1 -0
  41. package/src/components/ds-comment-indicator/ds-comment-indicator.tsx +1 -0
  42. package/src/components/ds-comments-drawer/ds-comments-drawer.tsx +1 -0
  43. package/src/components/ds-confirmation/ds-confirmation.tsx +1 -0
  44. package/src/components/ds-date-input/ds-date-input.tsx +2 -0
  45. package/src/components/ds-date-picker/ds-date-picker.tsx +9 -0
  46. package/src/components/ds-date-picker/ds-date-picker.types.ts +1 -1
  47. package/src/components/ds-date-range-picker/ds-date-range-picker.tsx +2 -0
  48. package/src/components/ds-dialog/ds-dialog.tsx +9 -0
  49. package/src/components/ds-dialog/ds-dialog.types.ts +1 -1
  50. package/src/components/ds-divider/ds-divider.figma.ts +19 -0
  51. package/src/components/ds-divider/ds-divider.tsx +2 -0
  52. package/src/components/ds-drawer/ds-drawer.module.scss +14 -0
  53. package/src/components/ds-drawer/ds-drawer.tsx +30 -1
  54. package/src/components/ds-drawer/ds-drawer.types.ts +7 -0
  55. package/src/components/ds-drawer/figma/ds-drawer-content.figma.ts +15 -0
  56. package/src/components/ds-drawer/figma/ds-drawer-footer.figma.ts +19 -0
  57. package/src/components/ds-drawer/figma/ds-drawer-header.figma.ts +16 -0
  58. package/src/components/ds-drawer/figma/ds-drawer.figma.ts +36 -0
  59. package/src/components/ds-dropdown-menu/ds-dropdown-menu.module.scss +12 -3
  60. package/src/components/ds-dropdown-menu/ds-dropdown-menu.tsx +24 -6
  61. package/src/components/ds-dropdown-menu/ds-dropdown-menu.types.ts +10 -1
  62. package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-footer.figma.ts +11 -0
  63. package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-group.figma.ts +23 -0
  64. package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-item.figma.ts +29 -0
  65. package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-separator.figma.ts +11 -0
  66. package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu.figma.ts +24 -0
  67. package/src/components/ds-expandable-text-input/ds-expandable-text-input.figma.ts +24 -0
  68. package/src/components/ds-expandable-text-input/ds-expandable-text-input.tsx +1 -0
  69. package/src/components/ds-file-upload/ds-file-upload.figma.ts +29 -0
  70. package/src/components/ds-file-upload/ds-file-upload.tsx +2 -0
  71. package/src/components/ds-file-upload/hooks/use-file-upload.ts +7 -0
  72. package/src/components/ds-filter-status-icon/ds-filter-status-icon.figma.ts +22 -0
  73. package/src/components/ds-filter-status-icon/ds-filter-status-icon.tsx +1 -0
  74. package/src/components/ds-form-control/ds-form-control.tsx +3 -0
  75. package/src/components/ds-grid/index.ts +3 -0
  76. package/src/components/ds-icon/ds-icon.tsx +2 -0
  77. package/src/components/ds-key-value-pair/ds-key-value-pair.figma.ts +24 -0
  78. package/src/components/ds-key-value-pair/ds-key-value-pair.tsx +2 -0
  79. package/src/components/ds-loader/ds-loader.figma.ts +11 -0
  80. package/src/components/ds-loader/ds-loader.tsx +2 -0
  81. package/src/components/ds-modal/ds-modal.tsx +9 -0
  82. package/src/components/ds-number-input/ds-number-input.tsx +2 -0
  83. package/src/components/ds-panel/ds-panel.figma.ts +16 -0
  84. package/src/components/ds-panel/index.ts +2 -0
  85. package/src/components/ds-password-input/ds-password-input.tsx +2 -0
  86. package/src/components/ds-popover/ds-popover.tsx +9 -0
  87. package/src/components/ds-popover/figma/ds-popover-content-item.figma.ts +18 -0
  88. package/src/components/ds-popover/figma/ds-popover-content.figma.ts +15 -0
  89. package/src/components/ds-popover/figma/ds-popover-footer.figma.ts +19 -0
  90. package/src/components/ds-popover/figma/ds-popover-header.figma.ts +16 -0
  91. package/src/components/ds-popover/figma/ds-popover.figma.ts +34 -0
  92. package/src/components/ds-progress-arc/ds-progress-arc.figma.ts +23 -0
  93. package/src/components/ds-progress-arc/ds-progress-arc.tsx +2 -0
  94. package/src/components/ds-progress-donut/ds-progress-donut.figma.ts +45 -0
  95. package/src/components/ds-progress-donut/ds-progress-donut.tsx +2 -0
  96. package/src/components/ds-progress-linear/ds-progress-linear.figma.ts +26 -0
  97. package/src/components/ds-progress-linear/ds-progress-linear.tsx +2 -0
  98. package/src/components/ds-progress-task-bar/ds-progress-task-bar.figma.ts +29 -0
  99. package/src/components/ds-progress-task-bar/ds-progress-task-bar.module.scss +39 -0
  100. package/src/components/ds-progress-task-bar/ds-progress-task-bar.tsx +124 -0
  101. package/src/components/ds-progress-task-bar/ds-progress-task-bar.types.ts +65 -0
  102. package/src/components/ds-progress-task-bar/index.ts +2 -0
  103. package/src/components/ds-progress-task-bar/utils.ts +51 -0
  104. package/src/components/ds-radio-group/ds-radio-group.tsx +3 -0
  105. package/src/components/ds-radio-group/figma/ds-radio-group-item.figma.ts +24 -0
  106. package/src/components/ds-radio-group/figma/ds-radio-group.figma.ts +14 -0
  107. package/src/components/ds-segment-group/ds-segment-group.tsx +3 -0
  108. package/src/components/ds-segment-group/figma/ds-segment-group-item.figma.ts +25 -0
  109. package/src/components/ds-segment-group/figma/ds-segment-group.figma.ts +23 -0
  110. package/src/components/ds-select/ds-select.tsx +2 -0
  111. package/src/components/ds-site-node/ds-site-node.figma.ts +27 -0
  112. package/src/components/ds-site-node/ds-site-node.module.scss +59 -0
  113. package/src/components/ds-site-node/ds-site-node.tsx +73 -0
  114. package/src/components/ds-site-node/ds-site-node.types.ts +36 -0
  115. package/src/components/ds-site-node/hooks/use-is-overflowing.ts +31 -0
  116. package/src/components/ds-site-node/index.ts +3 -0
  117. package/src/components/ds-skeleton/ds-skeleton-circle.tsx +2 -0
  118. package/src/components/ds-skeleton/ds-skeleton-rect.tsx +2 -0
  119. package/src/components/ds-skeleton/ds-skeleton-text.tsx +2 -0
  120. package/src/components/ds-skeleton/ds-skeleton.ts +7 -1
  121. package/src/components/ds-smart-tabs/ds-smart-tabs.tsx +4 -0
  122. package/src/components/ds-spinner/ds-spinner.figma.ts +19 -0
  123. package/src/components/ds-spinner/ds-spinner.tsx +2 -0
  124. package/src/components/ds-split-button/ds-split-button.tsx +6 -0
  125. package/src/components/ds-status-badge/ds-status-badge.tsx +2 -0
  126. package/src/components/ds-status-badge-v2/index.ts +2 -0
  127. package/src/components/ds-stepper/components/ds-step-content.tsx +2 -0
  128. package/src/components/ds-stepper/components/ds-step-next-button.tsx +2 -0
  129. package/src/components/ds-stepper/components/ds-step.tsx +2 -0
  130. package/src/components/ds-stepper/ds-stepper.figma.ts +38 -0
  131. package/src/components/ds-stepper/ds-stepper.tsx +1 -0
  132. package/src/components/ds-system-status/ds-system-status.tsx +2 -0
  133. package/src/components/ds-table/components/ds-table-row/ds-table-row.module.scss +1 -1
  134. package/src/components/ds-table/components/ds-table-row/ds-table-row.tsx +2 -0
  135. package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.module.scss +1 -1
  136. package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.tsx +2 -0
  137. package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-checkbox.tsx +1 -0
  138. package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-date.tsx +1 -0
  139. package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-number.tsx +1 -0
  140. package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-select.tsx +1 -0
  141. package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-text.tsx +1 -0
  142. package/src/components/ds-table/components/edit/ds-table-editable-cell/ds-table-editable-cell.module.scss +14 -2
  143. package/src/components/ds-table/components/edit/ds-table-editable-cell/ds-table-editable-cell.tsx +20 -0
  144. package/src/components/ds-table/components/edit/ds-table-editing-cell/ds-table-editing-cell.tsx +1 -0
  145. package/src/components/ds-table/ds-table-column.types.ts +24 -0
  146. package/src/components/ds-table/ds-table.tsx +30 -4
  147. package/src/components/ds-table/ds-table.types.ts +7 -0
  148. package/src/components/ds-table/index.ts +4 -0
  149. package/src/components/ds-table/utils/constants.ts +5 -0
  150. package/src/components/ds-tabs/components/ds-tabs-content/ds-tabs-content.tsx +2 -0
  151. package/src/components/ds-tabs/components/ds-tabs-list/ds-tabs-list.tsx +2 -0
  152. package/src/components/ds-tabs/components/ds-tabs-tab/ds-tabs-tab.tsx +2 -0
  153. package/src/components/ds-tabs/ds-tabs.tsx +2 -0
  154. package/src/components/ds-tabs/figma/ds-tabs-tab-vertical.figma.ts +78 -0
  155. package/src/components/ds-tabs/figma/ds-tabs-tab.figma.ts +89 -0
  156. package/src/components/ds-tabs/figma/ds-tabs-vertical.figma.ts +31 -0
  157. package/src/components/ds-tabs/figma/ds-tabs.figma.ts +29 -0
  158. package/src/components/ds-tag/ds-tag.tsx +2 -0
  159. package/src/components/ds-tag-filter/ds-tag-filter.tsx +2 -0
  160. package/src/components/ds-text-input/ds-input-field-v02.figma.ts +87 -0
  161. package/src/components/ds-text-input/ds-text-input.tsx +2 -0
  162. package/src/components/ds-textarea/ds-textarea.tsx +2 -0
  163. package/src/components/ds-time-picker/ds-time-picker.tsx +2 -0
  164. package/src/components/ds-toast/ds-toast-context.tsx +1 -0
  165. package/src/components/ds-toast/ds-toast.figma.ts +34 -0
  166. package/src/components/ds-toast/ds-toast.tsx +3 -0
  167. package/src/components/ds-toggle/ds-toggle.figma.ts +39 -0
  168. package/src/components/ds-toggle/ds-toggle.tsx +2 -0
  169. package/src/components/ds-tooltip/ds-tooltip.figma.ts +16 -0
  170. package/src/components/ds-tooltip/ds-tooltip.module.scss +8 -1
  171. package/src/components/ds-tooltip/ds-tooltip.tsx +35 -15
  172. package/src/components/ds-tooltip/ds-tooltip.types.ts +40 -0
  173. package/src/components/ds-tree/ds-tree.tsx +16 -0
  174. package/src/components/ds-typography/ds-typography.config.ts +1 -1
  175. package/src/components/ds-typography/ds-typography.figma.ts +63 -0
  176. package/src/components/ds-typography/ds-typography.module.scss +16 -0
  177. package/src/components/ds-typography/ds-typography.tsx +64 -7
  178. package/src/components/ds-typography/ds-typography.types.ts +13 -0
  179. package/src/components/ds-typography/hooks/use-truncation.ts +151 -0
  180. package/src/components/ds-user-card/ds-user-card.figma.ts +16 -0
  181. package/src/components/ds-user-card/ds-user-card.module.scss +25 -0
  182. package/src/components/ds-user-card/ds-user-card.tsx +31 -0
  183. package/src/components/ds-user-card/ds-user-card.types.ts +26 -0
  184. package/src/components/ds-user-card/index.ts +2 -0
  185. package/src/components/ds-vertical-tabs/ds-vertical-tabs.tsx +6 -0
  186. package/src/components/ds-workspace-layout/ds-workspace-layout.tsx +10 -0
  187. package/src/index.ts +3 -0
  188. package/src/styles/_root.scss +468 -363
  189. package/src/styles/shared/_dropdown.scss +2 -2
  190. package/src/styles/styles.scss +0 -3
  191. package/src/styles/_colors.scss +0 -65
  192. package/src/styles/_root_new.scss +0 -451
  193. package/src/styles/_spacing.scss +0 -47
@@ -5,6 +5,13 @@ import classNames from 'classnames';
5
5
  import styles from './ds-dialog.module.scss';
6
6
  import type { DsDialogProps } from './ds-dialog.types';
7
7
 
8
+ /**
9
+ * @summary Lightweight controlled dialog for simple panels and popovers.
10
+ *
11
+ * Renders a Radix dialog with required accessible title, optional description,
12
+ * and custom body content. Use for focused overlays and menu-style panels.
13
+ * Prefer `DsModal` when you need structured header, body, and footer sections.
14
+ */
8
15
  const DsDialog: React.FC<DsDialogProps> = ({
9
16
  open,
10
17
  onOpenChange,
@@ -67,4 +74,6 @@ const DsDialog: React.FC<DsDialogProps> = ({
67
74
  );
68
75
  };
69
76
 
77
+ DsDialog.displayName = 'DsDialog';
78
+
70
79
  export default DsDialog;
@@ -36,7 +36,7 @@ export interface DsDialogProps {
36
36
  /**
37
37
  * Ref to the element the dialog should be anchored to (for relative placement)
38
38
  */
39
- anchorRef?: React.RefObject<HTMLElement>;
39
+ anchorRef?: React.RefObject<HTMLElement | null>;
40
40
  /**
41
41
  * Custom fixed position (e.g., { top: number, left: number })
42
42
  */
@@ -0,0 +1,19 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=32735-122261
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-divider
3
+ // component=DsDivider
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const orientation =
9
+ instance.getEnum('direction', {
10
+ Horizontal: 'horizontal',
11
+ Vertical: 'vertical',
12
+ }) ?? 'horizontal';
13
+
14
+ export default {
15
+ example: figma.code`<DsDivider orientation="${orientation}" />`,
16
+ imports: ["import { DsDivider } from '@drivenets/design-system'"],
17
+ id: 'ds-divider',
18
+ metadata: { nestable: true },
19
+ };
@@ -19,4 +19,6 @@ const DsDivider: React.FC<DsDividerProps> = ({ orientation = 'horizontal', compo
19
19
  return <Component role="separator" aria-orientation={orientation} className={classes} style={style} />;
20
20
  };
21
21
 
22
+ DsDivider.displayName = 'DsDivider';
23
+
22
24
  export default DsDivider;
@@ -56,6 +56,20 @@
56
56
  transform 0.2s ease,
57
57
  width 0.2s ease;
58
58
 
59
+ // A closed (or closing) drawer is invisible but stays mounted and transformed.
60
+ // Without this it still hit-tests and can swallow clicks on neighboring UI when
61
+ // docked at a non-zero offset. Keep it click-through whenever it is not open.
62
+ //
63
+ // `!important` is required: when this drawer is stacked with other open Ark
64
+ // dialogs (e.g. a non-modal drawer opened over another dialog), Ark's layer
65
+ // management writes an inline `pointer-events: auto` onto the content, which
66
+ // would otherwise win over this rule and let the closed drawer keep eating
67
+ // clicks. Overriding a third-party inline style is the canonical use of
68
+ // `!important`, and a closed drawer must never be a pointer target.
69
+ &[data-state='closed'] {
70
+ pointer-events: none !important;
71
+ }
72
+
59
73
  &.position-end {
60
74
  right: 0;
61
75
  transform-origin: 100% 50%;
@@ -1,5 +1,5 @@
1
1
  import { type CSSProperties, type ReactNode, Fragment } from 'react';
2
- import { Dialog } from '@ark-ui/react/dialog';
2
+ import { Dialog, type DialogRootProps } from '@ark-ui/react/dialog';
3
3
  import { Portal } from '@ark-ui/react/portal';
4
4
  import classNames from 'classnames';
5
5
  import type { DsDrawerProps } from './ds-drawer.types';
@@ -12,6 +12,7 @@ import { useResponsiveValue } from '../../utils/responsive';
12
12
  const DsDrawer = ({
13
13
  open,
14
14
  onOpenChange,
15
+ onOpenAutoFocus,
15
16
  columns = 4,
16
17
  position = 'end',
17
18
  backdrop = false,
@@ -29,6 +30,23 @@ const DsDrawer = ({
29
30
  onOpenChange(details.open);
30
31
  };
31
32
 
33
+ // Mirrors Radix's `onOpenAutoFocus`. Ark reads `initialFocusEl` when the drawer
34
+ // opens to decide what to focus. To honor `preventDefault()`, we point initial
35
+ // focus back at the element that was focused when the drawer opened (e.g. the
36
+ // input that triggered it), so the caret stays put. Returning `undefined` keeps
37
+ // Ark's default of focusing the first element inside the drawer. The cast covers
38
+ // the `undefined` branch, which sits outside Ark's `MaybeElement` return type.
39
+ const initialFocusEl = (
40
+ onOpenAutoFocus
41
+ ? () => {
42
+ const event = new Event('openAutoFocus', { cancelable: true });
43
+ onOpenAutoFocus(event);
44
+
45
+ return event.defaultPrevented ? (document.activeElement as HTMLElement | null) : undefined;
46
+ }
47
+ : undefined
48
+ ) as DialogRootProps['initialFocusEl'];
49
+
32
50
  const Wrapper = portal ? Portal : Fragment;
33
51
 
34
52
  return (
@@ -39,6 +57,7 @@ const DsDrawer = ({
39
57
  closeOnEscape={closeOnEscape}
40
58
  closeOnInteractOutside={closeOnInteractOutside}
41
59
  preventScroll={backdrop}
60
+ initialFocusEl={initialFocusEl}
42
61
  >
43
62
  <Wrapper>
44
63
  {backdrop && <Dialog.Backdrop className={styles.backdrop} />}
@@ -151,6 +170,14 @@ const Actions = ({
151
170
  </div>
152
171
  );
153
172
 
173
+ Header.displayName = 'DsDrawer.Header';
174
+ Title.displayName = 'DsDrawer.Title';
175
+ CloseTrigger.displayName = 'DsDrawer.CloseTrigger';
176
+ Toolbar.displayName = 'DsDrawer.Toolbar';
177
+ Body.displayName = 'DsDrawer.Body';
178
+ Footer.displayName = 'DsDrawer.Footer';
179
+ Actions.displayName = 'DsDrawer.Actions';
180
+
154
181
  DsDrawer.Header = Header;
155
182
  DsDrawer.Title = Title;
156
183
  DsDrawer.CloseTrigger = CloseTrigger;
@@ -159,4 +186,6 @@ DsDrawer.Body = Body;
159
186
  DsDrawer.Footer = Footer;
160
187
  DsDrawer.Actions = Actions;
161
188
 
189
+ DsDrawer.displayName = 'DsDrawer';
190
+
162
191
  export default DsDrawer;
@@ -20,6 +20,13 @@ export interface DsDrawerProps extends Pick<DialogProps, 'closeOnEscape' | 'clos
20
20
  * Callback when the drawer open state changes
21
21
  */
22
22
  onOpenChange: (open: boolean) => void;
23
+ /**
24
+ * Called when focus is about to move into the drawer as it opens.
25
+ * Call `event.preventDefault()` to stop the drawer from stealing focus,
26
+ * keeping the caret where it was (e.g. in a text input that triggered the
27
+ * drawer). Useful for type-ahead / popover patterns.
28
+ */
29
+ onOpenAutoFocus?: (event: Event) => void;
23
30
  /**
24
31
  * Number of grid columns the drawer should span (1-12).
25
32
  * Accepts a responsive value, e.g. `{ lg: 4, md: 6 }`.
@@ -0,0 +1,15 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=31470-130498
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-drawer
3
+ // component=DsDrawer.Body
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const content = instance.getSlot('Drawer content slot');
9
+
10
+ export default {
11
+ example: figma.code`<DsDrawer.Body>${content}</DsDrawer.Body>`,
12
+ imports: ["import { DsDrawer } from '@drivenets/design-system'"],
13
+ id: 'ds-drawer-content',
14
+ metadata: { nestable: true },
15
+ };
@@ -0,0 +1,19 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=31416-38250
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-drawer
3
+ // component=DsDrawer.Footer
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const button = instance.findInstance('DAP_Button_v03', { traverseInstances: true });
9
+ let buttonCode: figma.ResultSection[] | undefined;
10
+ if (button.type === 'INSTANCE') {
11
+ buttonCode = button.executeTemplate().example;
12
+ }
13
+
14
+ export default {
15
+ example: figma.code`<DsDrawer.Footer><DsDrawer.Actions>${buttonCode}</DsDrawer.Actions></DsDrawer.Footer>`,
16
+ imports: ["import { DsDrawer } from '@drivenets/design-system'"],
17
+ id: 'ds-drawer-footer',
18
+ metadata: { nestable: true },
19
+ };
@@ -0,0 +1,16 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=31416-38215
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-drawer
3
+ // component=DsDrawer.Header
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const titleNode = instance.findText('left side', { traverseInstances: true });
9
+ const title = titleNode.type === 'TEXT' ? titleNode.textContent : 'Drawer title';
10
+
11
+ export default {
12
+ example: figma.code`<DsDrawer.Header><DsDrawer.Title>${title}</DsDrawer.Title><DsDrawer.CloseTrigger /></DsDrawer.Header>`,
13
+ imports: ["import { DsDrawer } from '@drivenets/design-system'"],
14
+ id: 'ds-drawer-header',
15
+ metadata: { nestable: true },
16
+ };
@@ -0,0 +1,36 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=31945-54500
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-drawer
3
+ // component=DsDrawer
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const header = instance.findInstance('DAP_drawer-in-header_v02', { traverseInstances: true });
9
+ let headerCode: figma.ResultSection[] | undefined;
10
+ if (header.type === 'INSTANCE') {
11
+ headerCode = header.executeTemplate().example;
12
+ }
13
+
14
+ const content = instance.findInstance('DAP_drawer-content_v02', { traverseInstances: true });
15
+ let contentCode: figma.ResultSection[] | undefined;
16
+ if (content.type === 'INSTANCE') {
17
+ contentCode = content.executeTemplate().example;
18
+ }
19
+
20
+ // The footer instance is named `sheet-footer` inside the assembled drawer but the
21
+ // standalone part is `DAP_drawer-in-footer_v02`; try both so the footer resolves.
22
+ let footer = instance.findInstance('DAP_drawer-in-footer_v02', { traverseInstances: true });
23
+ if (footer.type !== 'INSTANCE') {
24
+ footer = instance.findInstance('sheet-footer', { traverseInstances: true });
25
+ }
26
+ let footerCode: figma.ResultSection[] | undefined;
27
+ if (footer.type === 'INSTANCE') {
28
+ footerCode = footer.executeTemplate().example;
29
+ }
30
+
31
+ export default {
32
+ example: figma.code`<DsDrawer open columns={4} onOpenChange={() => {}}>${headerCode}${contentCode}${footerCode}</DsDrawer>`,
33
+ imports: ["import { DsDrawer } from '@drivenets/design-system'"],
34
+ id: 'ds-drawer',
35
+ metadata: { nestable: false },
36
+ };
@@ -17,7 +17,8 @@
17
17
  display: none;
18
18
  }
19
19
 
20
- &[data-nested='menu'] {
20
+ &[data-side='right'],
21
+ &[data-side='left'] {
21
22
  margin-top: -1px;
22
23
  z-index: 10000;
23
24
  }
@@ -83,12 +84,20 @@
83
84
  bottom: -1px;
84
85
  z-index: 1;
85
86
  display: flex;
87
+ border-top: 1px solid var(--border-secondary);
88
+ background-color: var(--background);
89
+ }
90
+
91
+ .actionsRow {
86
92
  align-items: center;
87
93
  justify-content: flex-end;
88
94
  gap: var(--xs);
89
95
  padding: var(--3xs) var(--xs);
90
- border-top: 1px solid var(--border-secondary);
91
- background-color: var(--background);
96
+ }
97
+
98
+ .actionsStretch {
99
+ flex-direction: column;
100
+ padding: var(--3xs);
92
101
  }
93
102
 
94
103
  .groupLabel {
@@ -35,9 +35,11 @@ interface GroupContextValue {
35
35
 
36
36
  const GroupContext = createContext<GroupContextValue | null>(null);
37
37
 
38
+ const MENU_GUTTER = 4;
39
+
38
40
  const DEFAULT_POSITIONING: DsDropdownMenuPositioning = {
39
41
  placement: 'bottom-start' as const,
40
- gutter: 4,
42
+ gutter: MENU_GUTTER,
41
43
  };
42
44
 
43
45
  /**
@@ -158,15 +160,18 @@ const Header: React.FC<DsDropdownMenuHeaderProps> = ({ children, className, styl
158
160
  };
159
161
 
160
162
  /**
161
- * Actions component - footer container for action buttons
163
+ * Actions component - sticky bottom slot for action buttons (`align="end"`) or
164
+ * full-width elements like a logout item (`align="stretch"`).
162
165
  */
163
- const Actions: React.FC<DsDropdownMenuActionsProps> = ({ children, className, style }) => {
166
+ const Actions: React.FC<DsDropdownMenuActionsProps> = ({ children, align = 'end', className, style }) => {
164
167
  return (
165
168
  <div
166
- className={classNames(styles.actions, className)}
169
+ className={classNames(
170
+ styles.actions,
171
+ align === 'stretch' ? styles.actionsStretch : styles.actionsRow,
172
+ className,
173
+ )}
167
174
  style={style}
168
- role="menu"
169
- aria-label="Menu actions"
170
175
  >
171
176
  {children}
172
177
  </div>
@@ -414,3 +419,16 @@ export const DsDropdownMenu = {
414
419
  ItemGroupContent,
415
420
  Separator,
416
421
  };
422
+ DsDropdownMenu.Root.displayName = 'DsDropdownMenu.Root';
423
+ DsDropdownMenu.Trigger.displayName = 'DsDropdownMenu.Trigger';
424
+ DsDropdownMenu.Content.displayName = 'DsDropdownMenu.Content';
425
+ DsDropdownMenu.Item.displayName = 'DsDropdownMenu.Item';
426
+ DsDropdownMenu.ItemIndicator.displayName = 'DsDropdownMenu.ItemIndicator';
427
+ DsDropdownMenu.TriggerItem.displayName = 'DsDropdownMenu.TriggerItem';
428
+ DsDropdownMenu.Header.displayName = 'DsDropdownMenu.Header';
429
+ DsDropdownMenu.Actions.displayName = 'DsDropdownMenu.Actions';
430
+ DsDropdownMenu.ItemGroup.displayName = 'DsDropdownMenu.ItemGroup';
431
+ DsDropdownMenu.ItemGroupLabel.displayName = 'DsDropdownMenu.ItemGroupLabel';
432
+ DsDropdownMenu.ItemGroupContent.displayName = 'DsDropdownMenu.ItemGroupContent';
433
+ DsDropdownMenu.Separator.displayName = 'DsDropdownMenu.Separator';
434
+ DsDropdownMenuLegacy.displayName = 'DsDropdownMenuLegacy';
@@ -5,6 +5,9 @@ import type { IconType } from '../ds-icon';
5
5
  export const dropdownMenuItemVariants = ['default', 'error'] as const;
6
6
  export type DropdownMenuItemVariant = (typeof dropdownMenuItemVariants)[number];
7
7
 
8
+ export const dropdownMenuActionsAlignments = ['end', 'stretch'] as const;
9
+ export type DropdownMenuActionsAlign = (typeof dropdownMenuActionsAlignments)[number];
10
+
8
11
  /**
9
12
  * Base positioning type
10
13
  */
@@ -242,9 +245,15 @@ export interface DsDropdownMenuHeaderProps {
242
245
  */
243
246
  export interface DsDropdownMenuActionsProps {
244
247
  /**
245
- * The action buttons or elements
248
+ * The action buttons or full-width elements pinned to the bottom of the menu.
246
249
  */
247
250
  children: ReactNode;
251
+ /**
252
+ * How children are laid out. `end` is a right-aligned button row (e.g.
253
+ * Cancel/Apply); `stretch` stacks full-width children (e.g. a logout item).
254
+ * @default 'end'
255
+ */
256
+ align?: DropdownMenuActionsAlign;
248
257
  /**
249
258
  * Optional CSS class name
250
259
  */
@@ -0,0 +1,11 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=35299-7214
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-dropdown-menu
3
+ // component=DsDropdownMenu.Actions
4
+ import figma from 'figma';
5
+
6
+ export default {
7
+ example: figma.code`<DsDropdownMenu.Actions>{/* action buttons */}</DsDropdownMenu.Actions>`,
8
+ imports: ["import { DsDropdownMenu } from '@drivenets/design-system'"],
9
+ id: 'ds-dropdown-menu-footer',
10
+ metadata: { nestable: true },
11
+ };
@@ -0,0 +1,23 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=13761-206276
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-dropdown-menu
3
+ // component=DsDropdownMenu.ItemGroup
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const collapsed = instance.getEnum('Type', { Expanded: false, Collapsed: true });
9
+
10
+ const labelNode = instance.findText('Menu text', { traverseInstances: true });
11
+ const label = labelNode.type === 'TEXT' ? labelNode.textContent : 'Group name';
12
+
13
+ const collapsedAttr = collapsed ? ' collapsed' : '';
14
+
15
+ export default {
16
+ example: figma.code`<DsDropdownMenu.ItemGroup${collapsedAttr}>
17
+ <DsDropdownMenu.ItemGroupLabel>${label}</DsDropdownMenu.ItemGroupLabel>
18
+ <DsDropdownMenu.ItemGroupContent>{/* group items */}</DsDropdownMenu.ItemGroupContent>
19
+ </DsDropdownMenu.ItemGroup>`,
20
+ imports: ["import { DsDropdownMenu } from '@drivenets/design-system'"],
21
+ id: 'ds-dropdown-menu-group',
22
+ metadata: { nestable: true },
23
+ };
@@ -0,0 +1,29 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=35298-162404
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-dropdown-menu
3
+ // component=DsDropdownMenu.Item
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const type = instance.getEnum('type', {
9
+ default: 'default',
10
+ checkbox: 'checkbox',
11
+ radio: 'radio',
12
+ error: 'error',
13
+ });
14
+
15
+ const selected = instance.getEnum('selected', { true: true, false: false });
16
+
17
+ const labelNode = instance.findText('Menu text', { traverseInstances: true });
18
+ const label = labelNode.type === 'TEXT' ? labelNode.textContent : 'Menu item';
19
+
20
+ const variantAttr = type === 'error' ? ' variant="error"' : '';
21
+ const selectedAttr = selected ? ' selected' : '';
22
+ const indicator = type === 'checkbox' || type === 'radio' ? '<DsDropdownMenu.ItemIndicator />' : '';
23
+
24
+ export default {
25
+ example: figma.code`<DsDropdownMenu.Item value="item"${variantAttr}${selectedAttr}>${label}${indicator}</DsDropdownMenu.Item>`,
26
+ imports: ["import { DsDropdownMenu } from '@drivenets/design-system'"],
27
+ id: 'ds-dropdown-menu-item',
28
+ metadata: { nestable: true },
29
+ };
@@ -0,0 +1,11 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=13683-206080
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-dropdown-menu
3
+ // component=DsDropdownMenu.Separator
4
+ import figma from 'figma';
5
+
6
+ export default {
7
+ example: figma.code`<DsDropdownMenu.Separator />`,
8
+ imports: ["import { DsDropdownMenu } from '@drivenets/design-system'"],
9
+ id: 'ds-dropdown-menu-separator',
10
+ metadata: { nestable: true },
11
+ };
@@ -0,0 +1,24 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=35301-70996
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-dropdown-menu
3
+ // component=DsDropdownMenu
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const items = instance.getSlot('.partsDropdownList');
9
+
10
+ const footer = instance.findInstance('DAP_dropdown-footer_v01', { traverseInstances: true });
11
+ let footerCode: figma.ResultSection[] | undefined;
12
+ if (footer.type === 'INSTANCE') {
13
+ footerCode = footer.executeTemplate().example;
14
+ }
15
+
16
+ export default {
17
+ example: figma.code`<DsDropdownMenu.Root>
18
+ <DsDropdownMenu.Trigger>{/* trigger element */}</DsDropdownMenu.Trigger>
19
+ <DsDropdownMenu.Content>${items}${footerCode}</DsDropdownMenu.Content>
20
+ </DsDropdownMenu.Root>`,
21
+ imports: ["import { DsDropdownMenu } from '@drivenets/design-system'"],
22
+ id: 'ds-dropdown-menu',
23
+ metadata: { nestable: false },
24
+ };
@@ -0,0 +1,24 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=17353-7836
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-expandable-text-input
3
+ // component=DsExpandableTextInput
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const type = instance.getEnum('Type', {
9
+ Persistent: 'persistent',
10
+ Expandable: 'expandable',
11
+ });
12
+
13
+ const isExpandable = type !== 'persistent';
14
+
15
+ const component = isExpandable ? 'DsExpandableTextInput' : 'DsAutocomplete';
16
+
17
+ export default {
18
+ example: isExpandable
19
+ ? figma.code`<DsExpandableTextInput icon="search" />`
20
+ : figma.code`<DsAutocomplete options={[]} showTrigger={false} />`,
21
+ imports: [`import { ${component} } from '@drivenets/design-system'`],
22
+ id: 'ds-expandable-text-input',
23
+ metadata: { nestable: true },
24
+ };
@@ -112,3 +112,4 @@ export function DsExpandableTextInput({
112
112
  function InputExpander({ children }: { children: ReactNode }) {
113
113
  return <div className={styles.inputExpander}>{children}</div>;
114
114
  }
115
+ DsExpandableTextInput.displayName = 'DsExpandableTextInput';
@@ -0,0 +1,29 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=15128-184303
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-file-upload
3
+ // component=DsFileUpload
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const state = instance.getEnum('State', {
9
+ Default: 'default',
10
+ Error: 'error',
11
+ Disabled: 'disabled',
12
+ Focus: 'focus',
13
+ 'Drop Hover': 'dropHover',
14
+ });
15
+
16
+ const attrs = [
17
+ 'adapter={adapter}',
18
+ state === 'disabled' ? 'disabled' : '',
19
+ state === 'error' ? 'errorText="Upload failed"' : '',
20
+ ]
21
+ .filter(Boolean)
22
+ .join(' ');
23
+
24
+ export default {
25
+ example: figma.code`<DsFileUpload ${attrs} />`,
26
+ imports: ["import { DsFileUpload } from '@drivenets/design-system'"],
27
+ id: 'ds-file-upload',
28
+ metadata: { nestable: false },
29
+ };
@@ -43,4 +43,6 @@ const DsFileUpload: React.FC<DsFileUploadProps> = ({
43
43
  return <FileUpload {...fileUploadProps} {...props} />;
44
44
  };
45
45
 
46
+ DsFileUpload.displayName = 'DsFileUpload';
47
+
46
48
  export default DsFileUpload;
@@ -224,6 +224,13 @@ export function useFileUpload({
224
224
  updateFileProgress(fileId, 100);
225
225
  onFileUploadComplete?.(fileId, result);
226
226
  } catch (error) {
227
+ // A fired abort signal means the upload was cancelled or removed by the
228
+ // user. Adapters reject with a (retryable) error on abort, but that must
229
+ // not overwrite the terminal status owned by cancelUpload/removeFile.
230
+ if (abortController.signal.aborted) {
231
+ return;
232
+ }
233
+
227
234
  const errorMessage = error instanceof Error ? error.message : 'Upload failed';
228
235
  // Determine status based on error type
229
236
  // Unknown errors are treated as retryable (network errors, etc.)
@@ -0,0 +1,22 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=27983-34074
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-filter-status-icon
3
+ // component=DsFilterStatusIcon
4
+ import figma from 'figma';
5
+
6
+ const instance = figma.selectedInstance;
7
+
8
+ const status = instance.getEnum('type', {
9
+ running: 'running',
10
+ warning: 'warning',
11
+ failed: 'failed',
12
+ paused: 'paused',
13
+ });
14
+ const active = instance.getEnum('state', { active: true, 'non-active': false });
15
+ const activeProp = active ? '' : ' active={false}';
16
+
17
+ export default {
18
+ example: figma.code`<DsFilterStatusIcon status="${status}"${activeProp} />`,
19
+ imports: ["import { DsFilterStatusIcon } from '@drivenets/design-system'"],
20
+ id: 'ds-filter-status-icon',
21
+ metadata: { nestable: true },
22
+ };
@@ -33,3 +33,4 @@ export const DsFilterStatusIcon = ({
33
33
  />
34
34
  );
35
35
  };
36
+ DsFilterStatusIcon.displayName = 'DsFilterStatusIcon';
@@ -107,4 +107,7 @@ DsFormControl.Textarea = controlify(DsTextarea);
107
107
  DsFormControl.Select = controlify(DsSelect);
108
108
  DsFormControl.Description = DsFormControlDescription;
109
109
 
110
+ DsFormControl.displayName = 'DsFormControl';
111
+ DsFormControl.Description.displayName = 'DsFormControl.Description';
112
+
110
113
  export default DsFormControl;
@@ -8,3 +8,6 @@ export const DsGridItem = withResponsiveProps(DsGridItemBase, ['colSpan', 'rowSp
8
8
 
9
9
  export type DsGridProps = ComponentProps<typeof DsGrid>;
10
10
  export type DsGridItemProps = ComponentProps<typeof DsGridItem>;
11
+
12
+ DsGrid.displayName = 'DsGrid';
13
+ DsGridItem.displayName = 'DsGridItem';
@@ -45,4 +45,6 @@ const DsIcon = ({
45
45
  );
46
46
  };
47
47
 
48
+ DsIcon.displayName = 'DsIcon';
49
+
48
50
  export default DsIcon;
@@ -0,0 +1,24 @@
1
+ // url=https://www.figma.com/design/nha3m67y7S57cHCSuQO2gp/DAP-Design-System-1.2?node-id=28373-92227
2
+ // source=https://github.com/drivenets/design-system/tree/main/packages/design-system/src/components/ds-key-value-pair
3
+ // component=DsKeyValuePair
4
+ //
5
+ // `Direction` maps to `orientation`. `keyLabel` and `value` are content, not derivable
6
+ // from Figma, so they are emitted as placeholders for the developer to fill in (see
7
+ // `ds-user-card.figma.ts`). Read-only vs editable is consumer edit-mode state rather than
8
+ // a Figma variant, so `readOnly`/`editInput` are left at their defaults.
9
+ import figma from 'figma';
10
+
11
+ const instance = figma.selectedInstance;
12
+
13
+ const orientation =
14
+ instance.getEnum('Direction', {
15
+ vertical: 'vertical',
16
+ horizontal: 'horizontal',
17
+ }) ?? 'vertical';
18
+
19
+ export default {
20
+ example: figma.code`<DsKeyValuePair keyLabel="Label" value="Value" orientation="${orientation}" />`,
21
+ imports: ["import { DsKeyValuePair } from '@drivenets/design-system'"],
22
+ id: 'ds-key-value-pair',
23
+ metadata: { nestable: true },
24
+ };
@@ -44,4 +44,6 @@ const DsKeyValuePair = ({
44
44
  );
45
45
  };
46
46
 
47
+ DsKeyValuePair.displayName = 'DsKeyValuePair';
48
+
47
49
  export default DsKeyValuePair;