@drivenets/design-system 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +201 -0
  3. package/dist/index.cjs +5394 -0
  4. package/dist/index.css +1 -0
  5. package/dist/index.d.cts +9157 -0
  6. package/dist/index.d.cts.map +1 -0
  7. package/dist/index.d.ts +9157 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +5335 -0
  10. package/dist/index.js.map +1 -0
  11. package/package.json +104 -0
  12. package/src/components/ds-alert-banner/ds-alert-banner.module.scss +116 -0
  13. package/src/components/ds-alert-banner/ds-alert-banner.tsx +115 -0
  14. package/src/components/ds-alert-banner/ds-alert-banner.types.tsx +47 -0
  15. package/src/components/ds-alert-banner/index.tsx +2 -0
  16. package/src/components/ds-breadcrumb/ds-breadcrumb.module.scss +99 -0
  17. package/src/components/ds-breadcrumb/ds-breadcrumb.tsx +94 -0
  18. package/src/components/ds-breadcrumb/ds-breadcrumb.types.tsx +32 -0
  19. package/src/components/ds-breadcrumb/index.tsx +2 -0
  20. package/src/components/ds-button/ds-button.tsx +12 -0
  21. package/src/components/ds-button/ds-button.types.ts +6 -0
  22. package/src/components/ds-button/index.ts +2 -0
  23. package/src/components/ds-button/versions/ds-button-legacy/ds-button-legacy.module.scss +257 -0
  24. package/src/components/ds-button/versions/ds-button-legacy/ds-button-legacy.tsx +34 -0
  25. package/src/components/ds-button/versions/ds-button-legacy/ds-button-legacy.types.ts +41 -0
  26. package/src/components/ds-button/versions/ds-button-legacy/index.ts +2 -0
  27. package/src/components/ds-button/versions/ds-button-new/ds-button-new.module.scss +580 -0
  28. package/src/components/ds-button/versions/ds-button-new/ds-button-new.tsx +49 -0
  29. package/src/components/ds-button/versions/ds-button-new/ds-button-new.types.ts +41 -0
  30. package/src/components/ds-button/versions/ds-button-new/index.ts +2 -0
  31. package/src/components/ds-checkbox/ds-checkbox.module.scss +130 -0
  32. package/src/components/ds-checkbox/ds-checkbox.tsx +55 -0
  33. package/src/components/ds-checkbox/ds-checkbox.types.tsx +27 -0
  34. package/src/components/ds-checkbox/index.tsx +2 -0
  35. package/src/components/ds-chip/ds-chip.module.scss +71 -0
  36. package/src/components/ds-chip/ds-chip.tsx +73 -0
  37. package/src/components/ds-chip/ds-chip.types.tsx +46 -0
  38. package/src/components/ds-chip/index.tsx +2 -0
  39. package/src/components/ds-chip-group/ds-chip-group.module.scss +59 -0
  40. package/src/components/ds-chip-group/ds-chip-group.tsx +122 -0
  41. package/src/components/ds-chip-group/ds-chip-group.types.ts +52 -0
  42. package/src/components/ds-chip-group/hooks/use-chip-row-calculation.ts +76 -0
  43. package/src/components/ds-chip-group/index.ts +2 -0
  44. package/src/components/ds-confirmation/ds-confirmation.module.scss +58 -0
  45. package/src/components/ds-confirmation/ds-confirmation.tsx +121 -0
  46. package/src/components/ds-confirmation/ds-confirmation.types.tsx +28 -0
  47. package/src/components/ds-confirmation/index.ts +2 -0
  48. package/src/components/ds-dialog/ds-dialog.module.scss +50 -0
  49. package/src/components/ds-dialog/ds-dialog.tsx +70 -0
  50. package/src/components/ds-dialog/ds-dialog.types.tsx +48 -0
  51. package/src/components/ds-dialog/index.tsx +2 -0
  52. package/src/components/ds-drawer/ds-drawer.module.scss +212 -0
  53. package/src/components/ds-drawer/ds-drawer.tsx +160 -0
  54. package/src/components/ds-drawer/ds-drawer.types.tsx +54 -0
  55. package/src/components/ds-drawer/index.ts +2 -0
  56. package/src/components/ds-dropdown-menu/ds-dropdown-menu.module.scss +123 -0
  57. package/src/components/ds-dropdown-menu/ds-dropdown-menu.tsx +396 -0
  58. package/src/components/ds-dropdown-menu/ds-dropdown-menu.types.tsx +262 -0
  59. package/src/components/ds-dropdown-menu/index.tsx +2 -0
  60. package/src/components/ds-expandable-text-input/ds-expandable-text-input.module.scss +70 -0
  61. package/src/components/ds-expandable-text-input/ds-expandable-text-input.tsx +106 -0
  62. package/src/components/ds-expandable-text-input/ds-expandable-text-input.types.tsx +19 -0
  63. package/src/components/ds-expandable-text-input/index.ts +2 -0
  64. package/src/components/ds-file-upload/components/file-upload/file-upload.module.scss +90 -0
  65. package/src/components/ds-file-upload/components/file-upload/file-upload.tsx +106 -0
  66. package/src/components/ds-file-upload/components/file-upload/file-upload.types.tsx +94 -0
  67. package/src/components/ds-file-upload/components/file-upload/index.ts +2 -0
  68. package/src/components/ds-file-upload/components/file-upload-item/file-upload-item.module.scss +125 -0
  69. package/src/components/ds-file-upload/components/file-upload-item/file-upload-item.tsx +143 -0
  70. package/src/components/ds-file-upload/components/file-upload-item/file-upload-item.types.tsx +26 -0
  71. package/src/components/ds-file-upload/components/file-upload-item/index.ts +2 -0
  72. package/src/components/ds-file-upload/ds-file-upload-api.types.ts +38 -0
  73. package/src/components/ds-file-upload/ds-file-upload.tsx +46 -0
  74. package/src/components/ds-file-upload/ds-file-upload.types.tsx +54 -0
  75. package/src/components/ds-file-upload/errors/file-upload-errors.ts +27 -0
  76. package/src/components/ds-file-upload/hooks/index.ts +2 -0
  77. package/src/components/ds-file-upload/hooks/use-file-upload.ts +350 -0
  78. package/src/components/ds-file-upload/index.ts +7 -0
  79. package/src/components/ds-file-upload/types/accept-types.ts +106 -0
  80. package/src/components/ds-file-upload/utils/accept-utils.ts +25 -0
  81. package/src/components/ds-file-upload/utils/constants.ts +21 -0
  82. package/src/components/ds-file-upload/utils/file-factory.ts +18 -0
  83. package/src/components/ds-file-upload/utils/format-file-size.ts +15 -0
  84. package/src/components/ds-file-upload/utils/generate-helper-text.ts +39 -0
  85. package/src/components/ds-file-upload/utils/get-error-message.ts +17 -0
  86. package/src/components/ds-file-upload/utils/is-file-equal.ts +8 -0
  87. package/src/components/ds-form-control/ds-form-control.module.scss +135 -0
  88. package/src/components/ds-form-control/ds-form-control.tsx +94 -0
  89. package/src/components/ds-form-control/ds-form-control.types.tsx +58 -0
  90. package/src/components/ds-form-control/index.tsx +2 -0
  91. package/src/components/ds-grid/ds-grid.module.scss +0 -0
  92. package/src/components/ds-grid/ds-grid.tsx +43 -0
  93. package/src/components/ds-grid/ds-grid.types.ts +55 -0
  94. package/src/components/ds-grid/index.ts +2 -0
  95. package/src/components/ds-icon/ds-icon.module.scss +25 -0
  96. package/src/components/ds-icon/ds-icon.tsx +33 -0
  97. package/src/components/ds-icon/ds-icon.types.ts +53 -0
  98. package/src/components/ds-icon/index.ts +2 -0
  99. package/src/components/ds-icon/material-icons.ts +6203 -0
  100. package/src/components/ds-modal/ds-modal.module.scss +100 -0
  101. package/src/components/ds-modal/ds-modal.tsx +136 -0
  102. package/src/components/ds-modal/ds-modal.types.tsx +44 -0
  103. package/src/components/ds-modal/index.tsx +2 -0
  104. package/src/components/ds-number-input/ds-number-input.module.scss +15 -0
  105. package/src/components/ds-number-input/ds-number-input.tsx +74 -0
  106. package/src/components/ds-number-input/ds-number-input.types.tsx +76 -0
  107. package/src/components/ds-number-input/index.tsx +2 -0
  108. package/src/components/ds-panel/ds-panel.module.scss +95 -0
  109. package/src/components/ds-panel/ds-panel.tsx +46 -0
  110. package/src/components/ds-panel/ds-panel.types.ts +17 -0
  111. package/src/components/ds-panel/index.tsx +2 -0
  112. package/src/components/ds-password-input/ds-password-input.module.scss +10 -0
  113. package/src/components/ds-password-input/ds-password-input.tsx +67 -0
  114. package/src/components/ds-password-input/ds-password-input.types.tsx +62 -0
  115. package/src/components/ds-password-input/index.tsx +2 -0
  116. package/src/components/ds-popover/ds-popover.module.scss +23 -0
  117. package/src/components/ds-popover/ds-popover.tsx +33 -0
  118. package/src/components/ds-popover/ds-popover.types.tsx +24 -0
  119. package/src/components/ds-popover/index.tsx +2 -0
  120. package/src/components/ds-radio-group/ds-radio-group.module.scss +138 -0
  121. package/src/components/ds-radio-group/ds-radio-group.tsx +115 -0
  122. package/src/components/ds-radio-group/ds-radio-group.types.tsx +93 -0
  123. package/src/components/ds-radio-group/index.tsx +2 -0
  124. package/src/components/ds-select/ds-select.module.scss +66 -0
  125. package/src/components/ds-select/ds-select.tsx +239 -0
  126. package/src/components/ds-select/ds-select.types.tsx +80 -0
  127. package/src/components/ds-select/index.tsx +2 -0
  128. package/src/components/ds-select/select-items-chips.tsx +56 -0
  129. package/src/components/ds-smart-tabs/ds-smart-tabs.module.scss +69 -0
  130. package/src/components/ds-smart-tabs/ds-smart-tabs.tsx +113 -0
  131. package/src/components/ds-smart-tabs/ds-smart-tabs.types.tsx +74 -0
  132. package/src/components/ds-smart-tabs/index.tsx +2 -0
  133. package/src/components/ds-spinner/ds-spinner.module.scss +39 -0
  134. package/src/components/ds-spinner/ds-spinner.tsx +51 -0
  135. package/src/components/ds-spinner/ds-spinner.types.tsx +20 -0
  136. package/src/components/ds-spinner/index.tsx +2 -0
  137. package/src/components/ds-status-badge/ds-status-badge.module.scss +79 -0
  138. package/src/components/ds-status-badge/ds-status-badge.tsx +42 -0
  139. package/src/components/ds-status-badge/ds-status-badge.types.tsx +46 -0
  140. package/src/components/ds-status-badge/index.tsx +2 -0
  141. package/src/components/ds-stepper/components/ds-step-content.tsx +32 -0
  142. package/src/components/ds-stepper/components/ds-step-description.tsx +6 -0
  143. package/src/components/ds-stepper/components/ds-step-label.tsx +6 -0
  144. package/src/components/ds-stepper/components/ds-step-next-button.tsx +13 -0
  145. package/src/components/ds-stepper/components/ds-step.tsx +59 -0
  146. package/src/components/ds-stepper/ds-stepper.module.scss +134 -0
  147. package/src/components/ds-stepper/ds-stepper.tsx +34 -0
  148. package/src/components/ds-stepper/ds-stepper.types.ts +12 -0
  149. package/src/components/ds-stepper/hooks/use-stepper.ts +20 -0
  150. package/src/components/ds-stepper/hooks/use-steps.ts +18 -0
  151. package/src/components/ds-stepper/index.tsx +6 -0
  152. package/src/components/ds-system-status/ds-system-status.module.scss +87 -0
  153. package/src/components/ds-system-status/ds-system-status.tsx +33 -0
  154. package/src/components/ds-system-status/ds-system-status.types.tsx +37 -0
  155. package/src/components/ds-system-status/index.tsx +10 -0
  156. package/src/components/ds-table/components/core-table/core-table.module.scss +32 -0
  157. package/src/components/ds-table/components/core-table/core-table.tsx +83 -0
  158. package/src/components/ds-table/components/core-table/index.ts +1 -0
  159. package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.module.scss +115 -0
  160. package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.tsx +70 -0
  161. package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.types.ts +41 -0
  162. package/src/components/ds-table/components/ds-table-bulk-actions/index.ts +2 -0
  163. package/src/components/ds-table/components/ds-table-cell/ds-table-cell.module.scss +53 -0
  164. package/src/components/ds-table/components/ds-table-cell/ds-table-cell.tsx +95 -0
  165. package/src/components/ds-table/components/ds-table-cell/ds-table-cell.types.ts +67 -0
  166. package/src/components/ds-table/components/ds-table-cell/index.ts +2 -0
  167. package/src/components/ds-table/components/ds-table-header/ds-table-header.module.scss +81 -0
  168. package/src/components/ds-table/components/ds-table-header/ds-table-header.tsx +99 -0
  169. package/src/components/ds-table/components/ds-table-header/ds-table-header.types.ts +11 -0
  170. package/src/components/ds-table/components/ds-table-header/index.ts +2 -0
  171. package/src/components/ds-table/components/ds-table-row/ds-table-row.module.scss +137 -0
  172. package/src/components/ds-table/components/ds-table-row/ds-table-row.tsx +205 -0
  173. package/src/components/ds-table/components/ds-table-row/ds-table-row.types.ts +22 -0
  174. package/src/components/ds-table/components/ds-table-row/index.ts +2 -0
  175. package/src/components/ds-table/context/ds-table-context.tsx +39 -0
  176. package/src/components/ds-table/ds-table.module.scss +60 -0
  177. package/src/components/ds-table/ds-table.tsx +312 -0
  178. package/src/components/ds-table/ds-table.types.ts +377 -0
  179. package/src/components/ds-table/filters/adapters/create-checkbox-filter-adapter.tsx +116 -0
  180. package/src/components/ds-table/filters/adapters/create-dual-range-filter-adapter.tsx +171 -0
  181. package/src/components/ds-table/filters/adapters/create-filter-adapter.ts +131 -0
  182. package/src/components/ds-table/filters/adapters/index.ts +12 -0
  183. package/src/components/ds-table/filters/components/checkbox-filter/checkbox-filter.tsx +43 -0
  184. package/src/components/ds-table/filters/components/checkbox-filter/index.ts +2 -0
  185. package/src/components/ds-table/filters/components/range-filter/index.ts +2 -0
  186. package/src/components/ds-table/filters/components/range-filter/range-filter.module.scss +25 -0
  187. package/src/components/ds-table/filters/components/range-filter/range-filter.tsx +79 -0
  188. package/src/components/ds-table/filters/hooks/index.ts +1 -0
  189. package/src/components/ds-table/filters/hooks/use-table-filters.ts +234 -0
  190. package/src/components/ds-table/filters/index.ts +50 -0
  191. package/src/components/ds-table/filters/types/filter-adapter.types.ts +111 -0
  192. package/src/components/ds-table/hooks/use-drag-and-drop.tsx +107 -0
  193. package/src/components/ds-table/index.ts +4 -0
  194. package/src/components/ds-table/styles/_variables.scss +17 -0
  195. package/src/components/ds-table/styles/shared/ds-table-shared.module.scss +16 -0
  196. package/src/components/ds-table/utils/column-styling.ts +30 -0
  197. package/src/components/ds-table/utils/create-columns-grid-template.ts +23 -0
  198. package/src/components/ds-table/utils/merge-refs.ts +15 -0
  199. package/src/components/ds-table/utils/story-data-generator.ts +91 -0
  200. package/src/components/ds-text-input/ds-text-input.module.scss +27 -0
  201. package/src/components/ds-text-input/ds-text-input.tsx +75 -0
  202. package/src/components/ds-text-input/ds-text-input.types.tsx +110 -0
  203. package/src/components/ds-text-input/index.ts +2 -0
  204. package/src/components/ds-textarea/ds-textarea.module.scss +5 -0
  205. package/src/components/ds-textarea/ds-textarea.tsx +49 -0
  206. package/src/components/ds-textarea/ds-textarea.types.tsx +67 -0
  207. package/src/components/ds-textarea/index.tsx +2 -0
  208. package/src/components/ds-toast/ds-toast-context.tsx +79 -0
  209. package/src/components/ds-toast/ds-toast.module.scss +134 -0
  210. package/src/components/ds-toast/ds-toast.tsx +54 -0
  211. package/src/components/ds-toast/ds-toast.types.tsx +53 -0
  212. package/src/components/ds-toast/index.ts +3 -0
  213. package/src/components/ds-tooltip/ds-tooltip.module.scss +19 -0
  214. package/src/components/ds-tooltip/ds-tooltip.tsx +33 -0
  215. package/src/components/ds-tooltip/ds-tooltip.types.tsx +12 -0
  216. package/src/components/ds-tooltip/index.tsx +2 -0
  217. package/src/components/ds-typography/ds-typography.config.ts +32 -0
  218. package/src/components/ds-typography/ds-typography.module.scss +93 -0
  219. package/src/components/ds-typography/ds-typography.tsx +27 -0
  220. package/src/components/ds-typography/ds-typography.types.tsx +27 -0
  221. package/src/components/ds-typography/index.tsx +2 -0
  222. package/src/components/ds-vertical-tabs/ds-vertical-tabs.module.scss +60 -0
  223. package/src/components/ds-vertical-tabs/ds-vertical-tabs.tsx +80 -0
  224. package/src/components/ds-vertical-tabs/ds-vertical-tabs.types.ts +69 -0
  225. package/src/components/ds-vertical-tabs/index.ts +7 -0
  226. package/src/index.ts +34 -0
  227. package/src/styles/_colors.scss +65 -0
  228. package/src/styles/_grid.scss +111 -0
  229. package/src/styles/_mixin.scss +1 -0
  230. package/src/styles/_reset.scss +38 -0
  231. package/src/styles/_root.scss +390 -0
  232. package/src/styles/_scrollbars.scss +41 -0
  233. package/src/styles/_spacing.scss +47 -0
  234. package/src/styles/_typography.scss +301 -0
  235. package/src/styles/_utilities.scss +33 -0
  236. package/src/styles/_variables.scss +44 -0
  237. package/src/styles/mixins/_bounding-box.scss +53 -0
  238. package/src/styles/mixins/_list.scss +74 -0
  239. package/src/styles/shared/_dropdown.scss +89 -0
  240. package/src/styles/shared/_input.scss +365 -0
  241. package/src/styles/shared/_modal.scss +123 -0
  242. package/src/styles/styles.scss +12 -0
@@ -0,0 +1,51 @@
1
+ import type React from 'react';
2
+ import classNames from 'classnames';
3
+ import styles from './ds-spinner.module.scss';
4
+ import type { DsSpinnerProps, SpinnerSize } from './ds-spinner.types';
5
+
6
+ const sizeMap: Record<SpinnerSize, number> = {
7
+ small: 50,
8
+ medium: 75,
9
+ large: 100,
10
+ };
11
+
12
+ const widthMap: Record<SpinnerSize, number> = {
13
+ small: 4,
14
+ medium: 7,
15
+ large: 9,
16
+ };
17
+
18
+ /**
19
+ * Design system Spinner component
20
+ */
21
+ const DsSpinner: React.FC<DsSpinnerProps> = ({ size = 'medium', className, style = {}, ...props }) => {
22
+ const actualSize = sizeMap[size];
23
+ const actualWidth = widthMap[size];
24
+ const radius = (actualSize - actualWidth) / 2;
25
+ const circumference = 2 * Math.PI * radius;
26
+ const strokeDasharray = `${String(0.25 * circumference)} ${String(circumference)}`;
27
+
28
+ return (
29
+ <div className={classNames(styles.spinnerContainer, styles[size], className)} style={style} {...props}>
30
+ <svg
31
+ className={classNames(styles.progressCircle, styles.spin)}
32
+ width={actualSize}
33
+ height={actualSize}
34
+ viewBox={`0 0 ${String(actualSize)} ${String(actualSize)}`}
35
+ >
36
+ <circle
37
+ className={styles.progressArc}
38
+ cx={actualSize / 2}
39
+ cy={actualSize / 2}
40
+ r={radius}
41
+ fill="none"
42
+ strokeWidth={actualWidth}
43
+ strokeDasharray={strokeDasharray}
44
+ strokeLinecap="round"
45
+ />
46
+ </svg>
47
+ </div>
48
+ );
49
+ };
50
+
51
+ export default DsSpinner;
@@ -0,0 +1,20 @@
1
+ import type React from 'react';
2
+
3
+ export const spinnerSizes = ['small', 'medium', 'large'] as const;
4
+ export type SpinnerSize = (typeof spinnerSizes)[number];
5
+
6
+ export interface DsSpinnerProps {
7
+ /**
8
+ * The size of the spinner
9
+ * @default 'medium'
10
+ */
11
+ size?: SpinnerSize;
12
+ /**
13
+ * Additional CSS class names
14
+ */
15
+ className?: string;
16
+ /**
17
+ * Additional styles to apply to the component
18
+ */
19
+ style?: React.CSSProperties;
20
+ }
@@ -0,0 +1,2 @@
1
+ export { default as DsSpinner } from './ds-spinner';
2
+ export * from './ds-spinner.types';
@@ -0,0 +1,79 @@
1
+ @use '../../styles/typography';
2
+
3
+ @mixin status-filled($color, $background, $label-color: var(--color-font-on-action)) {
4
+ color: $color;
5
+ background: $background;
6
+
7
+ .label {
8
+ color: $label-color;
9
+ }
10
+ }
11
+
12
+ @mixin status-ghost($color, $background) {
13
+ &.ghost {
14
+ color: $color;
15
+ background: $background;
16
+
17
+ .label {
18
+ color: var(--color-font-main);
19
+ }
20
+ }
21
+ }
22
+
23
+ .container {
24
+ display: flex;
25
+ align-items: center;
26
+ padding: var(--spacing-3xs) var(--spacing-standard) var(--spacing-3xs) var(--spacing-xs);
27
+ width: max-content;
28
+ color: var(--color-icon-inverse);
29
+ gap: var(--spacing-3xs);
30
+ border-radius: 100vmax;
31
+
32
+ &.small {
33
+ padding: var(--spacing-4xs) var(--spacing-xs) var(--spacing-4xs) var(--spacing-3xs);
34
+ gap: var(--spacing-4xs);
35
+ }
36
+ }
37
+
38
+ .active {
39
+ @include status-filled(var(--color-font-on-action), var(--color-background-success-strong));
40
+ @include status-ghost(var(--color-background-success-strong), var(--color-status-bg-success));
41
+ }
42
+
43
+ .running {
44
+ @include status-filled(var(--color-font-on-action), var(--color-background-active-moderate));
45
+ @include status-ghost(var(--color-icon-information-secondary), var(--color-status-bg-progress));
46
+ }
47
+
48
+ .pending {
49
+ @include status-filled(var(--color-font-on-action), var(--color-data-fuchsia));
50
+ @include status-ghost(var(--color-data-purple), var(--color-data-light-purple));
51
+ }
52
+
53
+ .draft {
54
+ @include status-filled(var(--color-font-on-action), var(--color-icon-information-main));
55
+ @include status-ghost(var(--color-icon-secondary), var(--color-status-bg-neutral));
56
+ }
57
+
58
+ .inactive {
59
+ @include status-filled(
60
+ var(--color-icon-secondary),
61
+ var(--color-background-disable),
62
+ var(--color-font-on-disabled)
63
+ );
64
+ @include status-ghost(var(--color-icon-secondary), var(--color-status-bg-inactive));
65
+ }
66
+
67
+ .warning {
68
+ @include status-filled(var(--color-font-on-action), var(--color-background-warning-strong));
69
+ @include status-ghost(var(--color-background-warning-strong), var(--color-status-bg-warning));
70
+ }
71
+
72
+ .failed {
73
+ @include status-filled(var(--color-font-on-action), var(--color-background-danger-strong));
74
+ @include status-ghost(var(--color-background-danger-strong-hover), var(--color-status-bg-failed));
75
+ }
76
+
77
+ .label {
78
+ text-transform: capitalize;
79
+ }
@@ -0,0 +1,42 @@
1
+ import type React from 'react';
2
+ import classNames from 'classnames';
3
+ import styles from './ds-status-badge.module.scss';
4
+ import type { DsStatusBadgeProps } from './ds-status-badge.types';
5
+ import { DsIcon } from '../ds-icon';
6
+ import { DsTypography } from '../ds-typography';
7
+
8
+ /**
9
+ * Design system StatusBadge component
10
+ */
11
+ const DsStatusBadge: React.FC<DsStatusBadgeProps> = ({
12
+ icon,
13
+ status,
14
+ label = status,
15
+ className,
16
+ style,
17
+ ghost = false,
18
+ size = 'medium',
19
+ 'aria-label': ariaLabel = label,
20
+ }) => {
21
+ return (
22
+ <div
23
+ style={style}
24
+ className={classNames(
25
+ styles.container,
26
+ styles[status],
27
+ ghost && styles.ghost,
28
+ size === 'small' && styles.small,
29
+ className,
30
+ )}
31
+ role="status"
32
+ aria-label={ariaLabel}
33
+ >
34
+ {icon && <DsIcon icon={icon} size="tiny" filled aria-hidden="true" />}
35
+ <DsTypography className={styles.label} variant={ghost ? 'body-xs-md' : 'body-xs-reg'}>
36
+ {label}
37
+ </DsTypography>
38
+ </div>
39
+ );
40
+ };
41
+
42
+ export default DsStatusBadge;
@@ -0,0 +1,46 @@
1
+ import type { CSSProperties } from 'react';
2
+ import type { IconType } from '../ds-icon';
3
+
4
+ export const dsStatuses = ['active', 'running', 'pending', 'draft', 'inactive', 'warning', 'failed'] as const;
5
+
6
+ export type DsStatus = (typeof dsStatuses)[number];
7
+
8
+ export const statusBadgeSizes = ['medium', 'small'] as const;
9
+ export type StatusBadgeSize = (typeof statusBadgeSizes)[number];
10
+
11
+ export interface DsStatusBadgeProps {
12
+ /**
13
+ * The icon of the status badge
14
+ */
15
+ icon?: IconType;
16
+ /**
17
+ * The value of the status badge
18
+ */
19
+ status: DsStatus;
20
+ /**
21
+ * Additional CSS class names
22
+ */
23
+ className?: string;
24
+ /**
25
+ * Additional styles to apply to the component
26
+ */
27
+ style?: CSSProperties;
28
+ /**
29
+ * Optional label to display instead of the default status text
30
+ */
31
+ label?: string;
32
+ /**
33
+ * Whether the status badge should use ghost style (light background)
34
+ * @default false
35
+ */
36
+ ghost?: boolean;
37
+ /**
38
+ * Size of the status badge
39
+ * @default 'medium'
40
+ */
41
+ size?: StatusBadgeSize;
42
+ /**
43
+ * Accessible label for screen readers, if provided, will override default label/status text.
44
+ */
45
+ 'aria-label'?: string;
46
+ }
@@ -0,0 +1,2 @@
1
+ export { default as DsStatusBadge } from './ds-status-badge';
2
+ export type { DsStatus, StatusBadgeSize, DsStatusBadgeProps } from './ds-status-badge.types';
@@ -0,0 +1,32 @@
1
+ import type { ReactNode } from 'react';
2
+ import { useStepper } from '../hooks/use-stepper';
3
+ import { DsStepLabel } from './ds-step-label';
4
+ import { DsStepDescription } from './ds-step-description';
5
+ import classnames from 'classnames';
6
+ import styles from '../ds-stepper.module.scss';
7
+
8
+ type DsStepContentProps = {
9
+ index: number;
10
+ label: string;
11
+ description?: string;
12
+ actions?: ReactNode;
13
+ };
14
+
15
+ export function DsStepContent({ index, label, description, actions }: DsStepContentProps) {
16
+ const { variant, stepsApi } = useStepper();
17
+ const { current } = stepsApi.getItemState({ index });
18
+
19
+ return (
20
+ <div
21
+ className={classnames(styles.stepContent, {
22
+ [styles.stepContentSingle]: variant === 'single',
23
+ })}
24
+ >
25
+ <DsStepLabel>{label}</DsStepLabel>
26
+
27
+ {variant !== 'single' && description && <DsStepDescription>{description}</DsStepDescription>}
28
+
29
+ {actions && current && <div className={styles.stepActions}>{actions}</div>}
30
+ </div>
31
+ );
32
+ }
@@ -0,0 +1,6 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ import styles from '../ds-stepper.module.scss';
3
+
4
+ export function DsStepDescription({ children }: PropsWithChildren) {
5
+ return <p className={styles.stepDescription}>{children}</p>;
6
+ }
@@ -0,0 +1,6 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ import styles from '../ds-stepper.module.scss';
3
+
4
+ export function DsStepLabel({ children }: PropsWithChildren) {
5
+ return <span className={styles.stepLabel}>{children}</span>;
6
+ }
@@ -0,0 +1,13 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ import { useStepper } from '../hooks/use-stepper';
3
+ import DsButton from '../../ds-button/ds-button';
4
+
5
+ export function DsNextStepButton({ children }: PropsWithChildren) {
6
+ const context = useStepper();
7
+
8
+ return (
9
+ <DsButton {...context.stepsApi.getNextTriggerProps()} size="small">
10
+ {children}
11
+ </DsButton>
12
+ );
13
+ }
@@ -0,0 +1,59 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ import { useStepper } from '../hooks/use-stepper';
3
+ import classnames from 'classnames';
4
+ import styles from '../ds-stepper.module.scss';
5
+ import DsIcon from '../../ds-icon/ds-icon';
6
+
7
+ type DsStepProps = PropsWithChildren<{
8
+ index: number;
9
+ className?: string;
10
+ }>;
11
+
12
+ export function DsStep({ index, children, className }: DsStepProps) {
13
+ const context = useStepper();
14
+
15
+ const { completed, current, last } = context.stepsApi.getItemState({ index });
16
+
17
+ const isSingleVariant = context.variant === 'single';
18
+ const isLast = last && context.stepsApi.value === index + 1;
19
+
20
+ const shouldHide = isSingleVariant && !current && !isLast;
21
+
22
+ if (shouldHide) {
23
+ return null;
24
+ }
25
+
26
+ const isClickable = completed && !isSingleVariant;
27
+
28
+ const Wrapper = isClickable ? 'button' : 'div';
29
+
30
+ const props = isClickable
31
+ ? {
32
+ onClick: () => {
33
+ context.stepsApi.setStep(index);
34
+ },
35
+ }
36
+ : {};
37
+
38
+ return (
39
+ <Wrapper
40
+ {...context.stepsApi.getItemProps({ index })}
41
+ data-current={current ? '' : undefined}
42
+ data-complete={completed ? '' : undefined}
43
+ className={classnames(styles.step, className)}
44
+ {...props}
45
+ >
46
+ <div {...context.stepsApi.getIndicatorProps({ index })} className={styles.indicatorContainer}>
47
+ {completed ? (
48
+ <DsIcon icon="check" className={styles.indicator} />
49
+ ) : (
50
+ <span className={styles.indicator}>{index + 1}</span>
51
+ )}
52
+
53
+ <div {...context.stepsApi.getSeparatorProps({ index })} className={styles.separator} />
54
+ </div>
55
+
56
+ {children}
57
+ </Wrapper>
58
+ );
59
+ }
@@ -0,0 +1,134 @@
1
+ .step {
2
+ padding: 12px;
3
+ display: flex;
4
+ gap: 16px;
5
+ background: none;
6
+ border: none;
7
+ text-align: start;
8
+ font-family: inherit;
9
+
10
+ .root.variantSingle & {
11
+ padding-block: 16px;
12
+ padding-inline-start: 12px;
13
+ padding-inline-end: 20px;
14
+ border-radius: 8px;
15
+ }
16
+
17
+ .root:not(.variantSingle) &[data-complete] {
18
+ cursor: pointer;
19
+ }
20
+
21
+ &[data-current] {
22
+ border-radius: 4px;
23
+ background: var(--color-background-action-secondary-hover);
24
+ }
25
+
26
+ .indicatorContainer {
27
+ padding: 0 2px;
28
+ position: relative;
29
+ display: flex;
30
+
31
+ .indicator {
32
+ height: 36px;
33
+ width: 36px;
34
+ border: 2px solid var(--color-border);
35
+ display: grid;
36
+ place-items: center;
37
+ border-radius: 100%;
38
+
39
+ .variantSingle & {
40
+ height: 32px;
41
+ width: 32px;
42
+ }
43
+ }
44
+
45
+ &[data-complete] .indicator {
46
+ color: var(--color-background-selected);
47
+ border-color: var(--color-background-selected);
48
+ }
49
+
50
+ &[data-current] .indicator {
51
+ background: var(--color-background-selected);
52
+ color: var(--white);
53
+ border: 3px solid var(--white);
54
+ }
55
+
56
+ .separator {
57
+ position: absolute;
58
+ width: 2px;
59
+ height: calc(100% - 12px);
60
+ top: 36px;
61
+ left: 50%;
62
+ margin-left: -1px;
63
+ background: var(--color-border);
64
+
65
+ &[data-complete] {
66
+ background: var(--color-background-selected);
67
+ }
68
+ }
69
+ }
70
+
71
+ &:last-child .indicatorContainer .separator {
72
+ display: none;
73
+ }
74
+
75
+ .stepContent {
76
+ display: flex;
77
+ flex-direction: column;
78
+ flex-grow: 1;
79
+
80
+ &.stepContentSingle {
81
+ flex-direction: row;
82
+ align-items: center;
83
+ }
84
+ }
85
+
86
+ .stepLabel {
87
+ padding: 2px 0;
88
+ font-size: 16px;
89
+ line-height: 1.5;
90
+ font-weight: 500;
91
+ color: var(--color-font-secondary);
92
+
93
+ .root.variantSingle & {
94
+ font-size: 14px;
95
+ }
96
+ }
97
+
98
+ .stepDescription {
99
+ margin: 0;
100
+ font-size: 14px;
101
+ line-height: 1.4;
102
+ color: var(--color-background-deselected);
103
+ }
104
+
105
+ &[data-current] {
106
+ .stepLabel {
107
+ color: var(--color-font-action);
108
+ }
109
+
110
+ .stepDescription {
111
+ color: var(--color-font-main);
112
+ }
113
+ }
114
+
115
+ &[data-complete] {
116
+ .stepLabel {
117
+ color: var(--color-font-main);
118
+ }
119
+
120
+ .stepDescription {
121
+ color: var(--color-font-secondary);
122
+ }
123
+ }
124
+
125
+ .stepContent:not(.stepContentSingle) .stepActions {
126
+ margin-top: 12px;
127
+ }
128
+
129
+ .stepActions {
130
+ margin-inline-start: auto;
131
+ display: flex;
132
+ gap: 4px;
133
+ }
134
+ }
@@ -0,0 +1,34 @@
1
+ import classnames from 'classnames';
2
+ import styles from './ds-stepper.module.scss';
3
+ import { useSteps } from './hooks/use-steps';
4
+ import { StepperContext } from './hooks/use-stepper';
5
+ import type { DsStepperProps } from './ds-stepper.types';
6
+
7
+ export function DsStepper({
8
+ count,
9
+ variant,
10
+ activeStep,
11
+ onStepChange,
12
+ onComplete,
13
+ children,
14
+ }: DsStepperProps) {
15
+ const stepsApi = useSteps({ count, activeStep, onStepChange, onComplete });
16
+
17
+ return (
18
+ <StepperContext.Provider
19
+ value={{
20
+ stepsApi,
21
+ variant,
22
+ }}
23
+ >
24
+ <div
25
+ {...stepsApi.getRootProps()}
26
+ className={classnames(styles.root, {
27
+ [styles.variantSingle]: variant === 'single',
28
+ })}
29
+ >
30
+ {children}
31
+ </div>
32
+ </StepperContext.Provider>
33
+ );
34
+ }
@@ -0,0 +1,12 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ import type * as steps from '@zag-js/steps';
3
+
4
+ export type DsStepperVariant = 'single';
5
+
6
+ export type DsStepperProps = PropsWithChildren<
7
+ {
8
+ variant?: DsStepperVariant;
9
+ onComplete?: steps.Props['onStepComplete'];
10
+ activeStep?: steps.Props['step'];
11
+ } & Pick<steps.Props, 'onStepChange' | 'count'>
12
+ >;
@@ -0,0 +1,20 @@
1
+ import { createContext, useContext } from 'react';
2
+ import type { DsStepperVariant } from '../ds-stepper.types';
3
+ import type { useSteps } from './use-steps';
4
+
5
+ type StepsContext = {
6
+ stepsApi: ReturnType<typeof useSteps>;
7
+ variant: DsStepperVariant | undefined;
8
+ };
9
+
10
+ export const StepperContext = createContext<StepsContext | null>(null);
11
+
12
+ export function useStepper() {
13
+ const context = useContext(StepperContext);
14
+
15
+ if (!context) {
16
+ throw new Error('useStepper must be used within a DsStepper');
17
+ }
18
+
19
+ return context;
20
+ }
@@ -0,0 +1,18 @@
1
+ import { useId } from 'react';
2
+ import * as steps from '@zag-js/steps';
3
+ import { normalizeProps, useMachine } from '@zag-js/react';
4
+ import type { DsStepperProps } from '../ds-stepper.types';
5
+
6
+ type UseSteps = Pick<DsStepperProps, 'activeStep' | 'onStepChange' | 'count' | 'onComplete'>;
7
+
8
+ export function useSteps({ count, activeStep, onStepChange, onComplete }: UseSteps) {
9
+ const service = useMachine(steps.machine, {
10
+ id: useId(),
11
+ count,
12
+ step: activeStep,
13
+ onStepChange,
14
+ onStepComplete: onComplete,
15
+ });
16
+
17
+ return steps.connect(service, normalizeProps);
18
+ }
@@ -0,0 +1,6 @@
1
+ export { DsStepper } from './ds-stepper';
2
+ export { DsStep } from './components/ds-step';
3
+ export { DsStepContent } from './components/ds-step-content';
4
+ export { DsNextStepButton } from './components/ds-step-next-button';
5
+
6
+ export type { DsStepperProps, DsStepperVariant } from './ds-stepper.types';
@@ -0,0 +1,87 @@
1
+ @use '../../styles/typography';
2
+
3
+ .container {
4
+ @include typography.p-special;
5
+ @include typography.medium;
6
+ display: inline-flex;
7
+ align-items: center;
8
+ gap: 4px;
9
+ padding: 4px 8px;
10
+ border-radius: 4px;
11
+ width: max-content;
12
+ text-transform: uppercase;
13
+ }
14
+
15
+ .dot {
16
+ width: 10px;
17
+ height: 10px;
18
+ border-radius: 50%;
19
+ border: 1px solid var(--white);
20
+ }
21
+
22
+ .label {
23
+ @include typography.p-special;
24
+ }
25
+
26
+ .healthy {
27
+ background: var(--utility-ok);
28
+ color: var(--system-status-ok);
29
+
30
+ .dot {
31
+ background: var(--system-status-ok);
32
+ }
33
+ }
34
+
35
+ .neutral {
36
+ background: var(--utility-info);
37
+ color: var(--system-status-info);
38
+
39
+ .dot {
40
+ background: var(--system-status-info);
41
+ }
42
+ }
43
+
44
+ .error {
45
+ background: var(--utility-error);
46
+ color: var(--system-status-error);
47
+
48
+ .dot {
49
+ background: var(--system-status-error);
50
+ }
51
+ }
52
+
53
+ .in-progress {
54
+ background: var(--utility-in-progress);
55
+ color: var(--system-status-in-progress);
56
+
57
+ .dot {
58
+ background: var(--system-status-in-progress);
59
+ }
60
+ }
61
+
62
+ .pending {
63
+ background: var(--utility-pending);
64
+ color: var(--system-status-pending);
65
+
66
+ .dot {
67
+ background: var(--system-status-pending);
68
+ }
69
+ }
70
+
71
+ .alert {
72
+ background: var(--utility-alert);
73
+ color: var(--system-status-alert);
74
+
75
+ .dot {
76
+ background: var(--system-status-alert);
77
+ }
78
+ }
79
+
80
+ .disabled {
81
+ background: var(--utility-disabled);
82
+ color: var(--neutral-2);
83
+
84
+ .dot {
85
+ background: var(--neutral-2);
86
+ }
87
+ }