@drivenets/design-system 0.9.0 → 0.10.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 (95) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/index.cjs +1076 -600
  3. package/dist/index.d.cts +1988 -528
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.ts +1991 -531
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1083 -609
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.min.css +1 -1
  10. package/package.json +16 -17
  11. package/src/components/ds-breadcrumb/ds-breadcrumb.types.ts +40 -6
  12. package/src/components/ds-button/ds-button.types.ts +13 -2
  13. package/src/components/ds-button-v3/ds-button-v3.module.scss +108 -109
  14. package/src/components/ds-button-v3/ds-button-v3.tsx +2 -2
  15. package/src/components/ds-button-v3/ds-button-v3.types.ts +19 -3
  16. package/src/components/ds-button-v3/index.ts +5 -1
  17. package/src/components/ds-card/ds-card.types.ts +3 -1
  18. package/src/components/ds-checkbox/ds-checkbox.module.scss +106 -123
  19. package/src/components/ds-checkbox/ds-checkbox.tsx +24 -35
  20. package/src/components/ds-checkbox/ds-checkbox.types.ts +12 -11
  21. package/src/components/ds-checkbox-group/ds-checkbox-group.module.scss +13 -0
  22. package/src/components/ds-checkbox-group/ds-checkbox-group.tsx +20 -0
  23. package/src/components/ds-checkbox-group/ds-checkbox-group.types.ts +8 -0
  24. package/src/components/ds-checkbox-group/hooks/index.ts +6 -0
  25. package/src/components/ds-checkbox-group/hooks/use-checkbox-select-all.ts +65 -0
  26. package/src/components/ds-checkbox-group/index.ts +3 -0
  27. package/src/components/ds-comment-bubble/components/ds-comment-thread/ds-comment-thread.types.ts +26 -0
  28. package/src/components/ds-comment-bubble/components/ds-thread-item/ds-thread-item.types.ts +38 -0
  29. package/src/components/ds-comment-bubble/ds-comment-bubble.types.ts +78 -0
  30. package/src/components/ds-comment-card/ds-comment-card.module.scss +2 -2
  31. package/src/components/ds-comment-card/ds-comment-card.types.ts +114 -0
  32. package/src/components/ds-comment-indicator/ds-comment-indicator.types.ts +26 -0
  33. package/src/components/ds-comments-drawer/comments-filters.types.ts +33 -0
  34. package/src/components/ds-comments-drawer/components/comments-filter-modal/comments-filter-modal.types.ts +37 -1
  35. package/src/components/ds-comments-drawer/ds-comments-drawer.types.ts +64 -0
  36. package/src/components/ds-date-input/ds-date-input.types.ts +23 -0
  37. package/src/components/ds-date-picker/ds-date-picker.tsx +3 -0
  38. package/src/components/ds-date-picker/ds-date-picker.types.ts +20 -0
  39. package/src/components/ds-date-range-picker/ds-date-range-picker.types.ts +28 -0
  40. package/src/components/ds-dialog/ds-dialog.types.ts +10 -1
  41. package/src/components/ds-dropdown-menu/ds-dropdown-menu.types.ts +24 -0
  42. package/src/components/ds-file-upload/components/file-upload/file-upload.types.ts +1 -0
  43. package/src/components/ds-file-upload/ds-file-upload-api.types.ts +55 -0
  44. package/src/components/ds-form-control/ds-form-control.types.ts +3 -0
  45. package/src/components/ds-grid/ds-grid.tsx +29 -12
  46. package/src/components/ds-grid/ds-grid.types.ts +16 -13
  47. package/src/components/ds-grid/index.ts +10 -2
  48. package/src/components/ds-icon/custom-icons/index.ts +2 -0
  49. package/src/components/ds-icon/custom-icons/special-leading-icon.tsx +11 -0
  50. package/src/components/ds-icon/ds-icon.tsx +10 -4
  51. package/src/components/ds-icon/ds-icon.types.ts +30 -0
  52. package/src/components/ds-key-value-pair/ds-key-value-pair.types.ts +12 -2
  53. package/src/components/ds-modal/ds-modal.types.ts +16 -0
  54. package/src/components/ds-panel/ds-panel.types.ts +39 -0
  55. package/src/components/ds-radio-group/ds-radio-group.module.scss +58 -56
  56. package/src/components/ds-radio-group/ds-radio-group.tsx +35 -28
  57. package/src/components/ds-radio-group/ds-radio-group.types.ts +38 -7
  58. package/src/components/ds-segment-group/ds-segment-group.types.ts +17 -0
  59. package/src/components/ds-select/ds-select.types.ts +32 -0
  60. package/src/components/ds-split-button/ds-split-button.module.scss +7 -7
  61. package/src/components/ds-split-button/ds-split-button.types.ts +28 -0
  62. package/src/components/ds-stack/ds-stack.types.ts +23 -0
  63. package/src/components/ds-stepper/ds-stepper.types.ts +34 -1
  64. package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.types.ts +27 -0
  65. package/src/components/ds-table/components/ds-table-cell/ds-table-cell.tsx +7 -4
  66. package/src/components/ds-table/components/ds-table-cell/ds-table-cell.types.ts +6 -0
  67. package/src/components/ds-table/components/ds-table-row-expandable-cell/ds-table-row-expandable-cell.types.ts +10 -0
  68. package/src/components/ds-table/components/ds-table-row-selectable-cell/ds-table-row-selectable-cell.types.ts +11 -0
  69. package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.types.ts +27 -0
  70. package/src/components/ds-table/filters/types/filter-adapter.types.ts +6 -0
  71. package/src/components/ds-tag/ds-tag.types.ts +6 -0
  72. package/src/components/ds-tag-filter/ds-tag-filter.types.ts +16 -0
  73. package/src/components/ds-text-input/ds-text-input.types.ts +3 -0
  74. package/src/components/ds-time-picker/components/time-item/time-item.types.ts +19 -0
  75. package/src/components/ds-time-picker/components/time-scroller/time-scroller.types.ts +29 -0
  76. package/src/components/ds-time-picker/ds-time-picker.module.scss +7 -0
  77. package/src/components/ds-time-picker/ds-time-picker.tsx +8 -1
  78. package/src/components/ds-time-picker/ds-time-picker.types.ts +80 -0
  79. package/src/components/ds-tooltip/ds-tooltip.types.ts +6 -0
  80. package/src/components/ds-tree/ds-tree.types.ts +86 -4
  81. package/src/components/ds-typography/ds-typography.config.ts +46 -27
  82. package/src/components/ds-typography/ds-typography.tsx +22 -7
  83. package/src/components/ds-typography/ds-typography.types.ts +15 -4
  84. package/src/components/ds-workspace/ds-workspace.module.scss +55 -0
  85. package/src/components/ds-workspace/ds-workspace.tsx +37 -0
  86. package/src/components/ds-workspace/ds-workspace.types.ts +17 -0
  87. package/src/components/ds-workspace/index.ts +8 -0
  88. package/src/index.ts +2 -0
  89. package/src/styles/_grid.scss +7 -3
  90. package/src/styles/_mixin.scss +2 -2
  91. package/src/styles/_root_new.scss +449 -0
  92. package/src/styles/_scrollbars.scss +6 -1
  93. package/src/styles/shared/_input.scss +0 -2
  94. package/src/styles/styles.scss +1 -0
  95. package/src/styles/_root_updated.scss +0 -593
@@ -1,10 +1,29 @@
1
1
  import type { RefObject } from 'react';
2
2
 
3
3
  export interface TimeItemProps {
4
+ /**
5
+ * Ref forwarded to the item button element
6
+ */
4
7
  ref?: RefObject<HTMLButtonElement | null>;
8
+ /**
9
+ * Additional CSS class name applied to the item button
10
+ */
5
11
  className?: string;
12
+ /**
13
+ * Text displayed in the item button (e.g., "03", "15", "AM").
14
+ */
6
15
  label: string;
16
+ /**
17
+ * Whether this item is the currently selected value on its scroller.
18
+ */
7
19
  selected: boolean;
20
+ /**
21
+ * Whether the item is disabled and cannot be selected.
22
+ * @default false
23
+ */
8
24
  disabled?: boolean;
25
+ /**
26
+ * Called when the item button is clicked.
27
+ */
9
28
  onClick: () => void;
10
29
  }
@@ -1,17 +1,46 @@
1
1
  export type TimePeriod = 'AM' | 'PM';
2
2
 
3
3
  export interface TimeScrollerProps {
4
+ /**
5
+ * Additional CSS class name applied to the scroller wrapper.
6
+ */
4
7
  className?: string;
8
+ /**
9
+ * Whether the parent popover is open. Used to snap the scrollers to their
10
+ * selected values when the popover is shown.
11
+ */
5
12
  open: boolean;
13
+ /**
14
+ * Props for each scroller sub-slot (hour, minute, period).
15
+ */
6
16
  slotProps: {
17
+ /**
18
+ * Hour scroller state and handlers.
19
+ */
7
20
  hour: TimeScrollerSlotProps<number>;
21
+ /**
22
+ * Minute scroller state and handlers.
23
+ */
8
24
  minute: TimeScrollerSlotProps<number>;
25
+ /**
26
+ * AM/PM period scroller state and handlers.
27
+ */
9
28
  period: TimeScrollerSlotProps<TimePeriod>;
10
29
  };
11
30
  }
12
31
 
13
32
  export interface TimeScrollerSlotProps<TValue> {
33
+ /**
34
+ * Currently selected value on this scroller.
35
+ */
14
36
  value?: TValue;
37
+ /**
38
+ * Called when the user changes the selection. Receives the new value.
39
+ */
15
40
  onChange?: (value: TValue) => void;
41
+ /**
42
+ * Predicate that marks a value as disabled. Receives the candidate value and
43
+ * returns `true` to disable selecting it.
44
+ */
16
45
  isDisabled?: (value: TValue) => boolean;
17
46
  }
@@ -1,3 +1,5 @@
1
+ @use '../../styles/shared/dropdown';
2
+
1
3
  .root {
2
4
  &:where(:hover, :focus-within) {
3
5
  .clearTrigger {
@@ -9,3 +11,8 @@
9
11
  .clearTrigger {
10
12
  visibility: hidden;
11
13
  }
14
+
15
+ .content {
16
+ @include dropdown.dropdown-content;
17
+ width: auto;
18
+ }
@@ -25,6 +25,7 @@ const DsTimePicker = (props: DsTimePickerProps) => {
25
25
  disablePortal = false,
26
26
  locale,
27
27
  slotProps,
28
+ onBlur,
28
29
  } = props;
29
30
  const [value, setValue] = useControlled(props.value, props.onChange, props.defaultValue ?? null);
30
31
  const [isOpen, setIsOpen] = useControlled(props.open, props.onOpenChange, props.defaultOpen ?? false);
@@ -84,6 +85,7 @@ const DsTimePicker = (props: DsTimePickerProps) => {
84
85
 
85
86
  if (!inputVal) {
86
87
  setValue(null);
88
+ onBlur?.();
87
89
  return;
88
90
  }
89
91
 
@@ -96,6 +98,8 @@ const DsTimePicker = (props: DsTimePickerProps) => {
96
98
  } else {
97
99
  resetInput();
98
100
  }
101
+
102
+ onBlur?.();
99
103
  };
100
104
 
101
105
  const handleOpenChange = (details: Popover.OpenChangeDetails) => {
@@ -166,7 +170,10 @@ const DsTimePicker = (props: DsTimePickerProps) => {
166
170
 
167
171
  <Wrapper>
168
172
  <Popover.Positioner>
169
- <Popover.Content {...slotProps?.popover}>
173
+ <Popover.Content
174
+ {...slotProps?.popover}
175
+ className={classNames(styles.content, slotProps?.popover?.className)}
176
+ >
170
177
  <TimeScroller open={isOpen} {...timeScrollerAdapter(value, setValue, min, max)} />
171
178
  </Popover.Content>
172
179
  </Popover.Positioner>
@@ -3,22 +3,63 @@ import type { DsTextInputProps } from '../ds-text-input';
3
3
  import type { PopoverContentProps } from '@ark-ui/react/popover';
4
4
 
5
5
  export interface DsTimePickerProps {
6
+ /**
7
+ * Unique identifier for the input field
8
+ */
6
9
  id?: string;
10
+ /**
11
+ * Ref forwarded to the time picker root element
12
+ */
7
13
  ref?: RefObject<HTMLDivElement>;
14
+ /**
15
+ * Additional CSS class name applied to the root element
16
+ */
8
17
  className?: string;
9
18
 
19
+ /**
20
+ * Current selected time (controlled). Use `null` to represent no selection.
21
+ * Pair with `onChange`.
22
+ */
10
23
  value?: Date | null;
24
+ /**
25
+ * Initial time when uncontrolled.
26
+ */
11
27
  defaultValue?: Date;
12
28
 
29
+ /**
30
+ * Whether the popover is open (controlled). Pair with `onOpenChange`.
31
+ */
13
32
  open?: boolean;
33
+ /**
34
+ * Whether the popover is initially open when uncontrolled.
35
+ * @default false
36
+ */
14
37
  defaultOpen?: boolean;
15
38
 
39
+ /**
40
+ * Placeholder text shown in the input when no time is selected.
41
+ */
16
42
  placeholder?: string;
17
43
 
44
+ /**
45
+ * Earliest selectable time. Times before this are disabled.
46
+ */
18
47
  min?: Date;
48
+ /**
49
+ * Latest selectable time. Times after this are disabled.
50
+ */
19
51
  max?: Date;
20
52
 
53
+ /**
54
+ * Whether the picker is disabled and cannot be interacted with.
55
+ * @default false
56
+ */
21
57
  disabled?: boolean;
58
+ /**
59
+ * Whether the picker is read-only. The input is focusable but the value cannot
60
+ * be changed.
61
+ * @default false
62
+ */
22
63
  readOnly?: boolean;
23
64
 
24
65
  /**
@@ -33,22 +74,61 @@ export interface DsTimePickerProps {
33
74
  */
34
75
  disablePortal?: boolean;
35
76
 
77
+ /**
78
+ * Localized labels used in the picker UI and for accessibility.
79
+ */
36
80
  locale?: DsTimePickerLocale;
81
+ /**
82
+ * Props forwarded to the internal input and popover slots.
83
+ */
37
84
  slotProps?: DsTimePickerSlotProps;
38
85
 
86
+ /**
87
+ * Called when the selected time changes. Receives the new Date or `null` when
88
+ * cleared.
89
+ */
39
90
  onChange?: (value: Date | null) => void;
91
+ /**
92
+ * Called when the popover opens or closes. Receives the next `open` state.
93
+ */
40
94
  onOpenChange?: (open: boolean) => void;
95
+
96
+ /**
97
+ * Called when the input is blurred
98
+ */
99
+ onBlur?: () => void;
41
100
  }
42
101
 
43
102
  export interface DsTimePickerLocale {
103
+ /**
104
+ * aria-label for the button that opens the popover
105
+ */
44
106
  openLabel?: string;
107
+ /**
108
+ * aria-label for the clear button
109
+ */
45
110
  clearLabel?: string;
111
+ /**
112
+ * aria-label for the hour scroller
113
+ */
46
114
  hourLabel?: string;
115
+ /**
116
+ * aria-label for the minute scroller
117
+ */
47
118
  minuteLabel?: string;
119
+ /**
120
+ * aria-label for the AM/PM period scroller
121
+ */
48
122
  periodLabel?: string;
49
123
  }
50
124
 
51
125
  export interface DsTimePickerSlotProps {
126
+ /**
127
+ * Props forwarded to the underlying `DsTextInput` that displays the selected time.
128
+ */
52
129
  input?: DsTextInputProps;
130
+ /**
131
+ * Props forwarded to the Ark popover content that hosts the time scrollers.
132
+ */
53
133
  popover?: PopoverContentProps;
54
134
  }
@@ -9,7 +9,13 @@ export interface DsTooltipProps {
9
9
  * The content to be rendered inside the tooltip
10
10
  */
11
11
  children: ReactNode;
12
+ /**
13
+ * Props forwarded to nested sub-components.
14
+ */
12
15
  slotProps?: {
16
+ /**
17
+ * Props forwarded to the tooltip content popover (className / inline styles).
18
+ */
13
19
  content?: {
14
20
  className?: string;
15
21
  style?: CSSProperties;
@@ -4,53 +4,129 @@ import type { IconType } from '../ds-icon';
4
4
  import type { FilterStatus } from '../ds-filter-status-icon';
5
5
 
6
6
  export interface DsTreeNode {
7
+ /**
8
+ * Stable identifier for the node. Used as the key in selection, expansion, and
9
+ * checked-state arrays.
10
+ */
7
11
  id: string;
12
+ /**
13
+ * Display name rendered for the node
14
+ */
8
15
  name: string;
16
+ /**
17
+ * Whether the node is disabled and cannot be selected, expanded, or checked.
18
+ * @default false
19
+ */
9
20
  disabled?: boolean;
21
+ /**
22
+ * Optional icon rendered before the node name
23
+ */
10
24
  icon?: IconType;
25
+ /**
26
+ * Optional status indicator shown next to the node (e.g., active/inactive filter).
27
+ */
11
28
  status?: FilterStatus;
29
+ /**
30
+ * Child nodes rendered under this node when it is expanded. Leaf nodes omit this.
31
+ */
12
32
  children?: DsTreeNode[];
13
33
  }
14
34
 
15
35
  export const dsTreeSizes = ['medium', 'small'] as const;
16
36
  export type DsTreeSize = (typeof dsTreeSizes)[number];
17
37
 
18
- interface DsTreeBaseProps {
38
+ export interface DsTreeBaseProps {
19
39
  className?: string;
20
40
  style?: CSSProperties;
21
41
  }
22
42
 
23
- interface DsTreeBasePropsWithChildren extends DsTreeBaseProps {
43
+ export interface DsTreeBasePropsWithChildren extends DsTreeBaseProps {
24
44
  children?: ReactNode;
25
45
  }
26
46
 
27
47
  export interface DsTreeRootProps<T extends DsTreeNode = DsTreeNode> extends DsTreeBasePropsWithChildren {
48
+ /**
49
+ * Ark UI tree collection describing the node hierarchy. Build it with
50
+ * `createTreeCollection` and pass the resulting collection in.
51
+ */
28
52
  collection: ArkTreeView.RootProps<T>['collection'];
53
+ /**
54
+ * Controls visual density of tree rows.
55
+ * @default medium
56
+ */
29
57
  size?: DsTreeSize;
58
+ /**
59
+ * Ref forwarded to the tree root element
60
+ */
30
61
  ref?: Ref<HTMLDivElement>;
31
62
 
63
+ /**
64
+ * Ids of currently selected nodes (controlled). Use with `onSelectionChange`.
65
+ */
32
66
  selectedValue?: string[];
67
+ /**
68
+ * Ids of nodes selected initially when uncontrolled.
69
+ */
33
70
  defaultSelectedValue?: string[];
71
+ /**
72
+ * Called when node selection changes. Receives the Ark selection details
73
+ * including the new `selectedValue` array.
74
+ */
34
75
  onSelectionChange?: ArkTreeView.RootProps<T>['onSelectionChange'];
76
+ /**
77
+ * Whether only one node can be selected at a time (`single`) or multiple
78
+ * selections are allowed (`multiple`).
79
+ * @default single
80
+ */
35
81
  selectionMode?: 'single' | 'multiple';
36
82
 
83
+ /**
84
+ * Ids of currently expanded branch nodes (controlled). Use with `onExpandedChange`.
85
+ */
37
86
  expandedValue?: string[];
87
+ /**
88
+ * Ids of branch nodes expanded initially when uncontrolled.
89
+ */
38
90
  defaultExpandedValue?: string[];
91
+ /**
92
+ * Called when the set of expanded nodes changes. Receives the Ark expansion
93
+ * details including the new `expandedValue` array.
94
+ */
39
95
  onExpandedChange?: ArkTreeView.RootProps<T>['onExpandedChange'];
96
+ /**
97
+ * Whether clicking anywhere on a branch row toggles its expansion in addition
98
+ * to clicking the branch indicator.
99
+ * @default false
100
+ */
40
101
  expandOnClick?: boolean;
41
102
 
103
+ /**
104
+ * Ids of nodes currently in the "checked" state (for checkbox trees). Use with
105
+ * `onCheckedChange`.
106
+ */
42
107
  checkedValue?: string[];
108
+ /**
109
+ * Ids of nodes initially checked when uncontrolled.
110
+ */
43
111
  defaultCheckedValue?: string[];
112
+ /**
113
+ * Called when the set of checked nodes changes. Receives the Ark checked-change
114
+ * details including the new `checkedValue` array.
115
+ */
44
116
  onCheckedChange?: ArkTreeView.RootProps<T>['onCheckedChange'];
45
117
 
46
118
  /**
47
- * Whether to enable typeahead navigation — typing characters focuses matching nodes
119
+ * Whether to enable typeahead navigation — typing characters focuses matching nodes.
48
120
  */
49
121
  typeahead?: boolean;
50
122
  /**
51
- * Whether to defer mounting of branch content until a branch is first expanded
123
+ * Whether to defer mounting of branch content until a branch is first expanded.
52
124
  */
53
125
  lazyMount?: boolean;
126
+ /**
127
+ * Whether to unmount branch content when the branch is collapsed (vs. hiding it).
128
+ * Pair with `lazyMount` to control mounting strategy.
129
+ */
54
130
  unmountOnExit?: boolean;
55
131
  }
56
132
 
@@ -69,6 +145,9 @@ export type DsTreeBranchContentProps = DsTreeBasePropsWithChildren;
69
145
  export type DsTreeBranchIndentGuideProps = DsTreeBaseProps;
70
146
 
71
147
  export interface DsTreeItemProps extends DsTreeBasePropsWithChildren {
148
+ /**
149
+ * Called when the leaf item is clicked. Receives the native mouse event.
150
+ */
72
151
  onClick?: (event: MouseEvent<HTMLDivElement>) => void;
73
152
  }
74
153
 
@@ -79,5 +158,8 @@ export type DsTreeItemIndicatorProps = DsTreeBaseProps;
79
158
  export type DsTreeNodeCheckboxProps = DsTreeBaseProps;
80
159
 
81
160
  export interface DsTreeItemActionProps extends DsTreeBasePropsWithChildren {
161
+ /**
162
+ * Called when the row action button is clicked. Receives the native mouse event.
163
+ */
82
164
  onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
83
165
  }
@@ -1,32 +1,51 @@
1
- export const semanticElementMap = {
2
- // Body variants
3
- 'body-md-reg': 'p',
4
- 'body-md-md': 'p',
5
- 'body-md-semi-bold': 'p',
6
- 'body-md-bold': 'p',
7
- 'body-md-link': 'a',
1
+ import { ark } from '@ark-ui/react';
8
2
 
9
- 'body-sm-reg': 'span',
10
- 'body-sm-md': 'span',
11
- 'body-sm-semi-bold': 'span',
12
- 'body-sm-bold': 'span',
13
- 'body-sm-link': 'a',
3
+ export const typographyVariantConfig = {
4
+ 'body-md-reg': { element: 'p', component: ark.p },
5
+ 'body-md-md': { element: 'p', component: ark.p },
6
+ 'body-md-semi-bold': { element: 'p', component: ark.p },
7
+ 'body-md-bold': { element: 'p', component: ark.p },
8
+ 'body-md-link': { element: 'a', component: ark.a },
14
9
 
15
- 'body-xs-reg': 'span',
16
- 'body-xs-md': 'span',
17
- 'body-xs-semi-bold': 'span',
18
- 'body-xs-bold': 'span',
19
- 'body-xs-link': 'a',
10
+ 'body-sm-reg': { element: 'span', component: ark.span },
11
+ 'body-sm-md': { element: 'span', component: ark.span },
12
+ 'body-sm-semi-bold': { element: 'span', component: ark.span },
13
+ 'body-sm-bold': { element: 'span', component: ark.span },
14
+ 'body-sm-link': { element: 'a', component: ark.a },
20
15
 
21
- // Code variants
22
- 'code-sm-reg': 'code',
23
- 'code-sm-semi-bold': 'code',
24
- 'code-xs-reg': 'code',
25
- 'code-xs-semi-bold': 'code',
16
+ 'body-xs-reg': { element: 'span', component: ark.span },
17
+ 'body-xs-md': { element: 'span', component: ark.span },
18
+ 'body-xs-semi-bold': { element: 'span', component: ark.span },
19
+ 'body-xs-bold': { element: 'span', component: ark.span },
20
+ 'body-xs-link': { element: 'a', component: ark.a },
26
21
 
27
- // Heading variants
28
- heading1: 'h1',
29
- heading2: 'h2',
30
- heading3: 'h3',
31
- heading4: 'h4',
22
+ 'code-sm-reg': { element: 'code', component: ark.code },
23
+ 'code-sm-semi-bold': { element: 'code', component: ark.code },
24
+ 'code-xs-reg': { element: 'code', component: ark.code },
25
+ 'code-xs-semi-bold': { element: 'code', component: ark.code },
26
+
27
+ heading1: { element: 'h1', component: ark.h1 },
28
+ heading2: { element: 'h2', component: ark.h2 },
29
+ heading3: { element: 'h3', component: ark.h3 },
30
+ heading4: { element: 'h4', component: ark.h4 },
32
31
  } as const;
32
+
33
+ /** Semantic text colors backed by `--font-*` tokens in `_root_new.scss`. */
34
+ export const typographyColors = [
35
+ 'main',
36
+ 'secondary',
37
+ 'action',
38
+ 'action-hover',
39
+ 'action-secondary',
40
+ 'action-secondary-hover',
41
+ 'disabled',
42
+ 'light-disabled',
43
+ 'on-action',
44
+ 'on-disabled',
45
+ 'placeholder',
46
+ 'highlight',
47
+ 'success',
48
+ 'warning',
49
+ 'error',
50
+ 'code',
51
+ ] as const;
@@ -1,24 +1,39 @@
1
- import type React from 'react';
2
- import { Slot } from '@radix-ui/react-slot';
3
1
  import classNames from 'classnames';
4
2
  import type { DsTypographyProps } from './ds-typography.types';
5
- import { semanticElementMap } from './ds-typography.config';
3
+ import { typographyColors, typographyVariantConfig } from './ds-typography.config';
6
4
  import styles from './ds-typography.module.scss';
7
5
 
6
+ const semanticColorSet = new Set<string>(typographyColors);
7
+
8
+ const resolveColor = (color: string): string =>
9
+ semanticColorSet.has(color) ? `var(--font-${color})` : color;
10
+
8
11
  /*
9
12
  * Design system Typography component that provides consistent text styling
10
13
  */
11
- const DsTypography: React.FC<DsTypographyProps & { ref?: React.Ref<HTMLElement> }> = ({
14
+ const DsTypography = ({
12
15
  ref,
13
16
  variant,
14
17
  asChild = false,
15
18
  className,
19
+ style,
20
+ color,
16
21
  children,
17
22
  ...props
18
- }) => {
19
- const Component: React.ElementType = asChild ? Slot : semanticElementMap[variant];
23
+ }: DsTypographyProps) => {
24
+ const Component = typographyVariantConfig[variant].component;
25
+
20
26
  return (
21
- <Component ref={ref} className={classNames(styles[variant], className)} {...props}>
27
+ <Component
28
+ // very dynamic ref in here
29
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
30
+ // @ts-expect-error
31
+ ref={ref}
32
+ asChild={asChild}
33
+ className={classNames(styles[variant], className)}
34
+ style={color ? { color: resolveColor(color), ...style } : style}
35
+ {...props}
36
+ >
22
37
  {children}
23
38
  </Component>
24
39
  );
@@ -1,13 +1,24 @@
1
- import type React from 'react';
2
- import type { semanticElementMap } from './ds-typography.config';
1
+ import type { Ref } from 'react';
2
+ import type { typographyColors, typographyVariantConfig } from './ds-typography.config';
3
3
 
4
- export type SemanticVariant = keyof typeof semanticElementMap;
4
+ export type SemanticVariant = keyof typeof typographyVariantConfig;
5
+ export type TypographyColor = (typeof typographyColors)[number];
5
6
 
6
7
  export interface DsTypographyProps {
8
+ /**
9
+ * Ref to the rendered element.
10
+ */
11
+ ref?: Ref<HTMLElement>;
7
12
  /**
8
13
  * The semantic variant of the component
9
14
  */
10
15
  variant: SemanticVariant;
16
+ /**
17
+ * Text color. Semantic names map to `--font-*` tokens; raw CSS color values
18
+ * (hex, rgb, hsl, CSS variables, named colors) pass through unchanged.
19
+ * Omit to inherit.
20
+ */
21
+ color?: TypographyColor | (string & {});
11
22
  /**
12
23
  * Additional CSS class names
13
24
  */
@@ -17,7 +28,7 @@ export interface DsTypographyProps {
17
28
  */
18
29
  style?: React.CSSProperties;
19
30
  /**
20
- * When true, renders as Slot component for composition without extra DOM nodes
31
+ * When true, composes typography styles onto the child element without extra DOM nodes
21
32
  */
22
33
  asChild?: boolean;
23
34
  /**
@@ -0,0 +1,55 @@
1
+ .root {
2
+ --ds-workspace-header-height: 54px;
3
+ --ds-workspace-header-gradient: radial-gradient(
4
+ ellipse at left bottom,
5
+ rgba(1, 75, 253, 1) 0%,
6
+ rgba(10, 60, 194, 1) 78%,
7
+ rgba(16, 51, 160, 1) 89%,
8
+ rgba(21, 42, 126, 1) 100%
9
+ );
10
+
11
+ display: flex;
12
+ flex-direction: column;
13
+ height: 100vh;
14
+ overflow: hidden;
15
+ background: var(--background);
16
+ }
17
+
18
+ .fillParent {
19
+ height: 100%;
20
+ }
21
+
22
+ .header {
23
+ display: flex;
24
+ align-items: center;
25
+ flex-shrink: 0;
26
+ height: var(--ds-workspace-header-height);
27
+ padding: 0 var(--sm) 0 var(--lg);
28
+ background: var(--ds-workspace-header-gradient);
29
+ color: var(--font-on-action);
30
+ overflow: clip;
31
+ }
32
+
33
+ .subHeader {
34
+ display: flex;
35
+ align-items: center;
36
+ flex-shrink: 0;
37
+ padding: var(--xs) var(--standard);
38
+ border-bottom: 1px solid var(--border);
39
+ background: var(--background);
40
+ }
41
+
42
+ .content {
43
+ position: relative;
44
+ flex: 1;
45
+ overflow: auto;
46
+ }
47
+
48
+ .footer {
49
+ display: flex;
50
+ align-items: center;
51
+ flex-shrink: 0;
52
+ padding: var(--xs) var(--standard);
53
+ border-top: 1px solid var(--border);
54
+ background: var(--background);
55
+ }
@@ -0,0 +1,37 @@
1
+ import classNames from 'classnames';
2
+ import styles from './ds-workspace.module.scss';
3
+ import type {
4
+ DsWorkspaceProps,
5
+ DsWorkspaceHeaderProps,
6
+ DsWorkspaceSubHeaderProps,
7
+ DsWorkspaceContentProps,
8
+ DsWorkspaceFooterProps,
9
+ } from './ds-workspace.types';
10
+
11
+ const DsWorkspace = ({ className, fillParent = false, ...rest }: DsWorkspaceProps) => (
12
+ <div {...rest} className={classNames(styles.root, { [styles.fillParent]: fillParent }, className)} />
13
+ );
14
+
15
+ const Header = ({ className, ...rest }: DsWorkspaceHeaderProps) => (
16
+ <header {...rest} className={classNames(styles.header, className)} />
17
+ );
18
+
19
+ const SubHeader = ({ className, ...rest }: DsWorkspaceSubHeaderProps) => (
20
+ <div {...rest} className={classNames(styles.subHeader, className)} />
21
+ );
22
+
23
+ /** Stacking context for non-portal drawer containment. */
24
+ const Content = ({ className, ...rest }: DsWorkspaceContentProps) => (
25
+ <div {...rest} className={classNames(styles.content, className)} />
26
+ );
27
+
28
+ const Footer = ({ className, ...rest }: DsWorkspaceFooterProps) => (
29
+ <footer {...rest} className={classNames(styles.footer, className)} />
30
+ );
31
+
32
+ DsWorkspace.Header = Header;
33
+ DsWorkspace.SubHeader = SubHeader;
34
+ DsWorkspace.Content = Content;
35
+ DsWorkspace.Footer = Footer;
36
+
37
+ export default DsWorkspace;