@robr0/design-system 0.1.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 (223) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/charts.d.ts +14 -0
  4. package/charts.js +20 -0
  5. package/components/Accordion/Accordion.css +119 -0
  6. package/components/Accordion/Accordion.d.ts +24 -0
  7. package/components/Accordion/Accordion.js +76 -0
  8. package/components/Alert/Alert.css +252 -0
  9. package/components/Alert/Alert.d.ts +24 -0
  10. package/components/Alert/Alert.js +53 -0
  11. package/components/AlertDialog/AlertDialog.css +131 -0
  12. package/components/AlertDialog/AlertDialog.d.ts +29 -0
  13. package/components/AlertDialog/AlertDialog.js +143 -0
  14. package/components/AppLayout/AppLayout.css +52 -0
  15. package/components/AppLayout/AppLayout.d.ts +27 -0
  16. package/components/AppLayout/AppLayout.js +45 -0
  17. package/components/AppSidebar/AppSidebar.css +434 -0
  18. package/components/AppSidebar/AppSidebar.d.ts +67 -0
  19. package/components/AppSidebar/AppSidebar.js +272 -0
  20. package/components/Avatar/Avatar.css +133 -0
  21. package/components/Avatar/Avatar.d.ts +20 -0
  22. package/components/Avatar/Avatar.js +56 -0
  23. package/components/Avatar/demoAvatars.d.ts +14 -0
  24. package/components/Avatar/demoAvatars.js +16 -0
  25. package/components/Badge/Badge.css +68 -0
  26. package/components/Badge/Badge.d.ts +13 -0
  27. package/components/Badge/Badge.js +15 -0
  28. package/components/Breadcrumb/Breadcrumb.css +92 -0
  29. package/components/Breadcrumb/Breadcrumb.d.ts +19 -0
  30. package/components/Breadcrumb/Breadcrumb.js +39 -0
  31. package/components/Button/Button.css +381 -0
  32. package/components/Button/Button.d.ts +39 -0
  33. package/components/Button/Button.js +71 -0
  34. package/components/ButtonGroup/ButtonGroup.css +39 -0
  35. package/components/ButtonGroup/ButtonGroup.d.ts +13 -0
  36. package/components/ButtonGroup/ButtonGroup.js +37 -0
  37. package/components/Card/Card.css +169 -0
  38. package/components/Card/Card.d.ts +30 -0
  39. package/components/Card/Card.js +90 -0
  40. package/components/Carousel/Carousel.css +112 -0
  41. package/components/Carousel/Carousel.d.ts +25 -0
  42. package/components/Carousel/Carousel.js +126 -0
  43. package/components/Chart/AreaChart.d.ts +36 -0
  44. package/components/Chart/AreaChart.js +99 -0
  45. package/components/Chart/BarChart.d.ts +34 -0
  46. package/components/Chart/BarChart.js +107 -0
  47. package/components/Chart/Chart.css +176 -0
  48. package/components/Chart/LineChart.d.ts +34 -0
  49. package/components/Chart/LineChart.js +90 -0
  50. package/components/Chart/PieChart.d.ts +34 -0
  51. package/components/Chart/PieChart.js +106 -0
  52. package/components/Chart/RadarChart.d.ts +34 -0
  53. package/components/Chart/RadarChart.js +91 -0
  54. package/components/Chart/RadialChart.d.ts +37 -0
  55. package/components/Chart/RadialChart.js +119 -0
  56. package/components/Chart/ScatterChart.d.ts +36 -0
  57. package/components/Chart/ScatterChart.js +109 -0
  58. package/components/Chart/StackedBarChart.d.ts +34 -0
  59. package/components/Chart/StackedBarChart.js +111 -0
  60. package/components/Chart/Treemap.d.ts +33 -0
  61. package/components/Chart/Treemap.js +109 -0
  62. package/components/Checkbox/Checkbox.css +164 -0
  63. package/components/Checkbox/Checkbox.d.ts +45 -0
  64. package/components/Checkbox/Checkbox.js +125 -0
  65. package/components/Chip/Chip.css +195 -0
  66. package/components/Chip/Chip.d.ts +27 -0
  67. package/components/Chip/Chip.js +80 -0
  68. package/components/CircularButton/CircularButton.css +206 -0
  69. package/components/CircularButton/CircularButton.d.ts +30 -0
  70. package/components/CircularButton/CircularButton.js +54 -0
  71. package/components/CodeBlock/CodeBlock.css +180 -0
  72. package/components/CodeBlock/CodeBlock.d.ts +23 -0
  73. package/components/CodeBlock/CodeBlock.js +85 -0
  74. package/components/ColourSwatch/ColourSwatch.css +88 -0
  75. package/components/ColourSwatch/ColourSwatch.d.ts +34 -0
  76. package/components/ColourSwatch/ColourSwatch.js +42 -0
  77. package/components/Combobox/Combobox.css +411 -0
  78. package/components/Combobox/Combobox.d.ts +73 -0
  79. package/components/Combobox/Combobox.js +312 -0
  80. package/components/CommandPalette/CommandPalette.css +310 -0
  81. package/components/CommandPalette/CommandPalette.d.ts +60 -0
  82. package/components/CommandPalette/CommandPalette.js +263 -0
  83. package/components/ContactCard/ContactCard.css +123 -0
  84. package/components/ContactCard/ContactCard.d.ts +23 -0
  85. package/components/ContactCard/ContactCard.js +78 -0
  86. package/components/ContributionGraph/ContributionGraph.css +142 -0
  87. package/components/ContributionGraph/ContributionGraph.d.ts +26 -0
  88. package/components/ContributionGraph/ContributionGraph.js +125 -0
  89. package/components/DateInput/DateInput.css +163 -0
  90. package/components/DateInput/DateInput.d.ts +43 -0
  91. package/components/DateInput/DateInput.js +69 -0
  92. package/components/DatePicker/DatePicker.css +198 -0
  93. package/components/DatePicker/DatePicker.d.ts +22 -0
  94. package/components/DatePicker/DatePicker.js +170 -0
  95. package/components/Dialog/Dialog.css +176 -0
  96. package/components/Dialog/Dialog.d.ts +28 -0
  97. package/components/Dialog/Dialog.js +132 -0
  98. package/components/Divider/Divider.css +100 -0
  99. package/components/Divider/Divider.d.ts +18 -0
  100. package/components/Divider/Divider.js +31 -0
  101. package/components/Drawer/Drawer.css +262 -0
  102. package/components/Drawer/Drawer.d.ts +30 -0
  103. package/components/Drawer/Drawer.js +134 -0
  104. package/components/Dropdown/Dropdown.css +300 -0
  105. package/components/Dropdown/Dropdown.d.ts +48 -0
  106. package/components/Dropdown/Dropdown.js +196 -0
  107. package/components/DropdownMenu/DropdownMenu.css +303 -0
  108. package/components/DropdownMenu/DropdownMenu.d.ts +42 -0
  109. package/components/DropdownMenu/DropdownMenu.js +322 -0
  110. package/components/EmptyState/EmptyState.css +115 -0
  111. package/components/EmptyState/EmptyState.d.ts +27 -0
  112. package/components/EmptyState/EmptyState.js +32 -0
  113. package/components/EntityCard/EntityCard.css +69 -0
  114. package/components/EntityCard/EntityCard.d.ts +18 -0
  115. package/components/EntityCard/EntityCard.js +26 -0
  116. package/components/Figure/Figure.css +61 -0
  117. package/components/Figure/Figure.d.ts +17 -0
  118. package/components/Figure/Figure.js +35 -0
  119. package/components/FileInput/FileInput.css +308 -0
  120. package/components/FileInput/FileInput.d.ts +54 -0
  121. package/components/FileInput/FileInput.js +177 -0
  122. package/components/Input/Input.css +193 -0
  123. package/components/Input/Input.d.ts +40 -0
  124. package/components/Input/Input.js +71 -0
  125. package/components/Instructions/Instructions.css +216 -0
  126. package/components/Instructions/Instructions.d.ts +28 -0
  127. package/components/Instructions/Instructions.js +32 -0
  128. package/components/LinkList/LinkList.css +71 -0
  129. package/components/LinkList/LinkList.d.ts +20 -0
  130. package/components/LinkList/LinkList.js +41 -0
  131. package/components/MotionSwatch/MotionSwatch.css +176 -0
  132. package/components/MotionSwatch/MotionSwatch.d.ts +25 -0
  133. package/components/MotionSwatch/MotionSwatch.js +74 -0
  134. package/components/Nav/Nav.css +51 -0
  135. package/components/Nav/Nav.d.ts +19 -0
  136. package/components/Nav/Nav.js +26 -0
  137. package/components/Pagination/Pagination.css +126 -0
  138. package/components/Pagination/Pagination.d.ts +22 -0
  139. package/components/Pagination/Pagination.js +83 -0
  140. package/components/Popover/Popover.css +99 -0
  141. package/components/Popover/Popover.d.ts +28 -0
  142. package/components/Popover/Popover.js +102 -0
  143. package/components/ProgressBar/ProgressBar.css +60 -0
  144. package/components/ProgressBar/ProgressBar.d.ts +16 -0
  145. package/components/ProgressBar/ProgressBar.js +27 -0
  146. package/components/Quote/Quote.css +79 -0
  147. package/components/Quote/Quote.d.ts +18 -0
  148. package/components/Quote/Quote.js +26 -0
  149. package/components/RadioButton/RadioButton.css +132 -0
  150. package/components/RadioButton/RadioButton.d.ts +43 -0
  151. package/components/RadioButton/RadioButton.js +77 -0
  152. package/components/SectionTitle/SectionTitle.css +37 -0
  153. package/components/SectionTitle/SectionTitle.d.ts +10 -0
  154. package/components/SectionTitle/SectionTitle.js +17 -0
  155. package/components/SegmentedControl/SegmentedControl.css +129 -0
  156. package/components/SegmentedControl/SegmentedControl.d.ts +33 -0
  157. package/components/SegmentedControl/SegmentedControl.js +91 -0
  158. package/components/SelectionCard/SelectionCard.css +251 -0
  159. package/components/SelectionCard/SelectionCard.d.ts +26 -0
  160. package/components/SelectionCard/SelectionCard.js +85 -0
  161. package/components/Skeleton/Skeleton.css +79 -0
  162. package/components/Skeleton/Skeleton.d.ts +16 -0
  163. package/components/Skeleton/Skeleton.js +30 -0
  164. package/components/Slider/Slider.css +86 -0
  165. package/components/Slider/Slider.d.ts +25 -0
  166. package/components/Slider/Slider.js +46 -0
  167. package/components/SpacingSwatch/SpacingSwatch.css +108 -0
  168. package/components/SpacingSwatch/SpacingSwatch.d.ts +20 -0
  169. package/components/SpacingSwatch/SpacingSwatch.js +50 -0
  170. package/components/Spinner/Spinner.css +73 -0
  171. package/components/Spinner/Spinner.d.ts +14 -0
  172. package/components/Spinner/Spinner.js +42 -0
  173. package/components/Stat/Stat.css +78 -0
  174. package/components/Stat/Stat.d.ts +19 -0
  175. package/components/Stat/Stat.js +30 -0
  176. package/components/Table/Table.css +186 -0
  177. package/components/Table/Table.d.ts +45 -0
  178. package/components/Table/Table.js +65 -0
  179. package/components/Tabs/Tabs.css +140 -0
  180. package/components/Tabs/Tabs.d.ts +28 -0
  181. package/components/Tabs/Tabs.js +77 -0
  182. package/components/Textarea/Textarea.css +152 -0
  183. package/components/Textarea/Textarea.d.ts +40 -0
  184. package/components/Textarea/Textarea.js +74 -0
  185. package/components/Timeline/Timeline.css +339 -0
  186. package/components/Timeline/Timeline.d.ts +63 -0
  187. package/components/Timeline/Timeline.js +69 -0
  188. package/components/Toast/Toast.css +342 -0
  189. package/components/Toast/Toast.d.ts +63 -0
  190. package/components/Toast/Toast.js +213 -0
  191. package/components/ToggleGroup/ToggleGroup.css +84 -0
  192. package/components/ToggleGroup/ToggleGroup.d.ts +30 -0
  193. package/components/ToggleGroup/ToggleGroup.js +53 -0
  194. package/components/ToggleSwitch/ToggleSwitch.css +139 -0
  195. package/components/ToggleSwitch/ToggleSwitch.d.ts +23 -0
  196. package/components/ToggleSwitch/ToggleSwitch.js +50 -0
  197. package/components/Tooltip/Tooltip.css +122 -0
  198. package/components/Tooltip/Tooltip.d.ts +21 -0
  199. package/components/Tooltip/Tooltip.js +63 -0
  200. package/components/TypographySwatch/TypographySwatch.css +81 -0
  201. package/components/TypographySwatch/TypographySwatch.d.ts +24 -0
  202. package/components/TypographySwatch/TypographySwatch.js +40 -0
  203. package/components/registry.d.ts +20 -0
  204. package/components/registry.js +7 -0
  205. package/components/registry.json +67 -0
  206. package/components/registry.json.d.ts +70 -0
  207. package/components/registry.json.js +8 -0
  208. package/fonts/MaterialSymbolsRounded-VariableFont_FILL,GRAD,opsz,wght.woff2 +0 -0
  209. package/fonts/material-symbols.css +94 -0
  210. package/index.d.ts +62 -0
  211. package/index.js +123 -0
  212. package/package.json +63 -0
  213. package/tokens/registry.d.ts +22 -0
  214. package/tokens/registry.js +14 -0
  215. package/tokens/registry.json +203 -0
  216. package/tokens/registry.json.d.ts +206 -0
  217. package/tokens/registry.json.js +8 -0
  218. package/tokens/tokens-dark.css +119 -0
  219. package/tokens/tokens-light.css +159 -0
  220. package/tokens/tokens-motion.css +68 -0
  221. package/tokens/tokens-primitives.css +176 -0
  222. package/tokens/tokens-typography.css +116 -0
  223. package/tokens/tokens.css +11 -0
@@ -0,0 +1,88 @@
1
+ /* ============================================
2
+ COLOUR SWATCH COMPONENT
3
+ Tall card that displays a colour token with
4
+ Primitive, Hex, and RGB values in a box.
5
+ ============================================ */
6
+
7
+ .ds-colour-swatch {
8
+ /* Layout */
9
+ display: flex;
10
+ flex-direction: column;
11
+ justify-content: space-between;
12
+
13
+ /* Sizing */
14
+ flex: 1 1 0;
15
+ min-width: 250px;
16
+ height: 360px;
17
+
18
+ /* Appearance */
19
+ border: var(--border-xs) solid var(--color-bg-container-border);
20
+ border-radius: var(--radius-xl); /* 24px */
21
+ padding: var(--padding-lg); /* 20px */
22
+ overflow: hidden;
23
+ position: relative;
24
+ }
25
+
26
+ /* Status variant — 1px full border */
27
+ .ds-colour-swatch--status {
28
+ border: 1px solid;
29
+ }
30
+
31
+ /* ============================================
32
+ TITLE BOX
33
+ Semi-transparent container at card top,
34
+ matching the values box treatment for
35
+ readability on any swatch colour.
36
+ ============================================ */
37
+
38
+ .ds-colour-swatch__title-box {
39
+ background: var(--color-bg-container-primary-semi);
40
+ border-radius: var(--radius-md); /* 12px */
41
+ padding: var(--padding-sm) var(--padding-md); /* 8px 16px */
42
+ align-self: flex-start;
43
+ }
44
+
45
+ .ds-colour-swatch__title {
46
+ font-family: var(--font-paragraph-family);
47
+ font-size: var(--font-heading-3-size);
48
+ font-weight: var(--font-heading-3-weight);
49
+ line-height: var(--font-heading-3-line-height);
50
+ letter-spacing: var(--font-heading-3-letter-spacing);
51
+ color: var(--color-text-primary);
52
+ }
53
+
54
+ /* ============================================
55
+ VALUES BOX
56
+ Semi-transparent container at card bottom
57
+ ============================================ */
58
+
59
+ .ds-colour-swatch__values {
60
+ background: var(--color-bg-container-primary-semi);
61
+ border-radius: var(--radius-md); /* 12px */
62
+ padding: var(--padding-sm) var(--padding-md); /* 8px 16px */
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: 2px;
66
+ }
67
+
68
+ /* Row: label + value pair */
69
+ .ds-colour-swatch__row {
70
+ display: flex;
71
+ gap: var(--gap-md); /* 16px */
72
+ font-size: var(--font-paragraph-size);
73
+ font-weight: var(--font-paragraph-weight);
74
+ line-height: var(--font-paragraph-line-height);
75
+ color: var(--color-text-primary);
76
+ }
77
+
78
+ /* Label column (e.g. "Primitive", "Hex", "RGB") */
79
+ .ds-colour-swatch__label {
80
+ flex-shrink: 0;
81
+ min-width: 70px;
82
+ color: var(--color-text-tertiary);
83
+ }
84
+
85
+ /* Data column */
86
+ .ds-colour-swatch__data {
87
+ word-break: break-word;
88
+ }
@@ -0,0 +1,34 @@
1
+ import { default as React } from 'react';
2
+ export interface ColourSwatchValues {
3
+ /** The primitive token name this colour maps to (e.g. "--teal--07--") — omit to hide the row */
4
+ primitive?: string;
5
+ /** The hex value (e.g. "#118AB2") or rgba string */
6
+ hex: string;
7
+ /** The RGB breakdown (e.g. "17 / 138 / 178") */
8
+ rgb: string;
9
+ }
10
+ export interface ColourSwatchProps {
11
+ /** Display label for the swatch (e.g. "Primary", "Red") */
12
+ label: string;
13
+ /** CSS custom property used as background (e.g. "--color-core-ui-primary") */
14
+ cssVar: string;
15
+ /** Values to display for dark theme */
16
+ dark: ColourSwatchValues;
17
+ /** Values to display for light theme — defaults to dark values if omitted */
18
+ light?: ColourSwatchValues;
19
+ /** Which theme is currently active — controls which values are shown */
20
+ theme?: 'dark' | 'light';
21
+ /** Render as a status swatch with left border accent */
22
+ status?: boolean;
23
+ /** CSS custom property for the status left border colour */
24
+ borderVar?: string;
25
+ /** Additional CSS classes */
26
+ className?: string;
27
+ }
28
+ /**
29
+ * ColourSwatch component from Figma design system
30
+ * Displays a colour swatch card with a values box showing
31
+ * Primitive, Hex, and RGB. Values switch when theme changes.
32
+ * Used on Semantic colours and Primitive colours pages.
33
+ */
34
+ export declare const ColourSwatch: ({ label, cssVar, dark, light, theme, status, borderVar, className, }: ColourSwatchProps) => React.JSX.Element;
@@ -0,0 +1,42 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import "react";
3
+ import "./ColourSwatch.css";
4
+ const ColourSwatch = ({
5
+ label,
6
+ cssVar,
7
+ dark,
8
+ light,
9
+ theme = "dark",
10
+ status = false,
11
+ borderVar,
12
+ className = ""
13
+ }) => {
14
+ const baseClass = "ds-colour-swatch";
15
+ const statusClass = status ? `${baseClass}--status` : "";
16
+ const classes = [baseClass, statusClass, className].filter(Boolean).join(" ");
17
+ const values = theme === "light" && light ? light : dark;
18
+ const style = {
19
+ backgroundColor: `var(${cssVar})`,
20
+ ...status && borderVar ? { borderColor: `var(${borderVar})` } : {}
21
+ };
22
+ return /* @__PURE__ */ jsxs("div", { className: classes, style, children: [
23
+ /* @__PURE__ */ jsx("div", { className: `${baseClass}__title-box`, children: /* @__PURE__ */ jsx("h3", { className: `${baseClass}__title`, children: label }) }),
24
+ /* @__PURE__ */ jsxs("div", { className: `${baseClass}__values`, children: [
25
+ values.primitive && /* @__PURE__ */ jsxs("div", { className: `${baseClass}__row`, children: [
26
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: "Primitive" }),
27
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__data`, children: values.primitive })
28
+ ] }),
29
+ /* @__PURE__ */ jsxs("div", { className: `${baseClass}__row`, children: [
30
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: "Hex" }),
31
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__data`, children: values.hex })
32
+ ] }),
33
+ /* @__PURE__ */ jsxs("div", { className: `${baseClass}__row`, children: [
34
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: "RGB" }),
35
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__data`, children: values.rgb })
36
+ ] })
37
+ ] })
38
+ ] });
39
+ };
40
+ export {
41
+ ColourSwatch
42
+ };
@@ -0,0 +1,411 @@
1
+ /* ============================================
2
+ COMBOBOX COMPONENT
3
+ Filterable text field + listbox, with optional
4
+ multi-select chips and async loading state
5
+ ============================================ */
6
+
7
+ .ds-combobox {
8
+ display: flex;
9
+ flex-direction: column;
10
+ gap: var(--gap-sm); /* 8px */
11
+ width: 100%;
12
+ position: relative;
13
+ }
14
+
15
+ /* ============================================
16
+ LABEL
17
+ ============================================ */
18
+
19
+ .ds-combobox__label {
20
+ font-family: var(--font-paragraph-em-family);
21
+ font-size: var(--font-paragraph-em-size);
22
+ font-weight: var(--font-paragraph-em-weight);
23
+ line-height: var(--font-paragraph-em-line-height);
24
+ letter-spacing: var(--font-paragraph-em-letter-spacing);
25
+ color: var(--color-text-primary);
26
+ }
27
+
28
+ .ds-combobox__required {
29
+ color: var(--color-core-accent-coral);
30
+ }
31
+
32
+ /* ============================================
33
+ CONTROL
34
+ ============================================ */
35
+
36
+ .ds-combobox__control {
37
+ display: flex;
38
+ align-items: center;
39
+ gap: var(--gap-sm); /* 8px */
40
+ padding: var(--padding-sm) var(--padding-md); /* 8px 16px */
41
+ border: var(--border-xs) solid var(--color-input-border-primary);
42
+ border-radius: var(--radius-md); /* 12px */
43
+ background-color: var(--color-input-bg-primary);
44
+ cursor: text;
45
+ transition: border-color var(--motion-duration-base) var(--motion-ease-standard);
46
+ }
47
+
48
+ .ds-combobox__control:hover {
49
+ border-color: var(--color-input-border-hover);
50
+ }
51
+
52
+ .ds-combobox--open .ds-combobox__control,
53
+ .ds-combobox__control:focus-within {
54
+ border-color: var(--color-input-border-selected);
55
+ }
56
+
57
+ .ds-combobox__search-icon {
58
+ --icon-size: var(--icon-size-md);
59
+ color: var(--color-icon-primary);
60
+ flex-shrink: 0;
61
+ }
62
+
63
+ /* ============================================
64
+ FIELD — chips + text input share one line
65
+ ============================================ */
66
+
67
+ .ds-combobox__field {
68
+ display: flex;
69
+ align-items: center;
70
+ flex-wrap: wrap;
71
+ gap: var(--gap-xs); /* 4px */
72
+ flex: 1;
73
+ min-width: 0;
74
+ }
75
+
76
+ .ds-combobox__input {
77
+ flex: 1;
78
+ min-width: 0;
79
+ border: none;
80
+ outline: none;
81
+ background-color: transparent;
82
+ padding: 0;
83
+ font-family: var(--font-paragraph-em-family);
84
+ font-size: var(--font-paragraph-em-size);
85
+ font-weight: var(--font-paragraph-em-weight);
86
+ line-height: var(--font-paragraph-em-line-height);
87
+ letter-spacing: var(--font-paragraph-em-letter-spacing);
88
+ color: var(--color-input-text-primary);
89
+ }
90
+
91
+ .ds-combobox__input::placeholder {
92
+ color: var(--color-input-text-placeholder);
93
+ }
94
+
95
+ /* ============================================
96
+ CHIPS — multi-select selections
97
+ ============================================ */
98
+
99
+ .ds-combobox__chip {
100
+ display: inline-flex;
101
+ align-items: center;
102
+ gap: var(--gap-xxs); /* 2px */
103
+ padding: var(--padding-xxxs) var(--padding-sm); /* 2px 8px */
104
+ border-radius: var(--radius-full);
105
+ background-color: var(--color-bg-container-primary);
106
+ font-family: var(--font-paragraph-sm-em-family);
107
+ font-size: var(--font-paragraph-sm-em-size);
108
+ font-weight: var(--font-paragraph-sm-em-weight);
109
+ line-height: var(--font-paragraph-sm-em-line-height);
110
+ letter-spacing: var(--font-paragraph-sm-em-letter-spacing);
111
+ color: var(--color-text-primary);
112
+ max-width: 100%;
113
+ }
114
+
115
+ .ds-combobox__chip-remove {
116
+ display: inline-flex;
117
+ align-items: center;
118
+ justify-content: center;
119
+ padding: 0;
120
+ border: none;
121
+ border-radius: var(--radius-full);
122
+ background-color: transparent;
123
+ color: var(--color-icon-primary);
124
+ cursor: pointer;
125
+ transition: color var(--motion-duration-base) var(--motion-ease-standard);
126
+ }
127
+
128
+ .ds-combobox__chip-remove:hover {
129
+ color: var(--color-text-primary);
130
+ }
131
+
132
+ .ds-combobox__chip-remove:focus-visible {
133
+ outline: 2px solid var(--color-action-primary-bg);
134
+ outline-offset: 1px;
135
+ }
136
+
137
+ .ds-combobox__chip-remove .material-symbols-rounded {
138
+ --icon-size: var(--icon-size-sm);
139
+ }
140
+
141
+ /* ============================================
142
+ CLEAR + CHEVRON
143
+ ============================================ */
144
+
145
+ .ds-combobox__clear {
146
+ display: inline-flex;
147
+ align-items: center;
148
+ justify-content: center;
149
+ padding: 0;
150
+ border: none;
151
+ border-radius: var(--radius-full);
152
+ background-color: transparent;
153
+ color: var(--color-icon-primary);
154
+ cursor: pointer;
155
+ flex-shrink: 0;
156
+ transition: color var(--motion-duration-base) var(--motion-ease-standard);
157
+ }
158
+
159
+ .ds-combobox__clear:hover {
160
+ color: var(--color-text-primary);
161
+ }
162
+
163
+ .ds-combobox__clear:focus-visible {
164
+ outline: 2px solid var(--color-action-primary-bg);
165
+ outline-offset: 2px;
166
+ }
167
+
168
+ .ds-combobox__clear .material-symbols-rounded {
169
+ --icon-size: var(--icon-size-sm);
170
+ }
171
+
172
+ .ds-combobox__chevron {
173
+ --icon-size: var(--icon-size-md);
174
+ color: var(--color-icon-primary);
175
+ transition: transform var(--motion-duration-base) var(--motion-ease-standard);
176
+ flex-shrink: 0;
177
+ }
178
+
179
+ .ds-combobox--open .ds-combobox__chevron {
180
+ transform: rotate(180deg);
181
+ }
182
+
183
+ /* ============================================
184
+ MENU
185
+ Floating surface — the one place a shadow is
186
+ allowed, via the shared elevation token
187
+ ============================================ */
188
+
189
+ .ds-combobox__menu {
190
+ position: absolute;
191
+ top: 100%;
192
+ left: 0;
193
+ right: 0;
194
+ margin-top: var(--gap-xxs); /* 2px */
195
+ padding: var(--padding-xxs);
196
+ border: var(--border-xs) solid var(--color-input-border-primary);
197
+ border-radius: var(--radius-md); /* 12px */
198
+ background-color: var(--color-bg-page-primary);
199
+ list-style: none;
200
+ max-height: 280px;
201
+ overflow-y: auto;
202
+ z-index: 10;
203
+ box-shadow: var(--shadow-floating);
204
+ animation: ds-combobox-appear var(--motion-duration-fast) var(--motion-ease-entrance);
205
+ }
206
+
207
+ @keyframes ds-combobox-appear {
208
+ from {
209
+ opacity: 0;
210
+ transform: scale(0.96);
211
+ }
212
+ to {
213
+ opacity: 1;
214
+ transform: scale(1);
215
+ }
216
+ }
217
+
218
+ /* ============================================
219
+ OPTION
220
+ ============================================ */
221
+
222
+ .ds-combobox__option {
223
+ display: flex;
224
+ align-items: center;
225
+ justify-content: space-between;
226
+ gap: var(--gap-sm);
227
+ padding: var(--padding-sm) var(--padding-sm-md); /* 8px 12px */
228
+ border-radius: var(--radius-sm);
229
+ cursor: pointer;
230
+ transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
231
+ }
232
+
233
+ .ds-combobox__option:hover,
234
+ .ds-combobox__option--focused {
235
+ background-color: var(--color-action-passive-bg-hover);
236
+ }
237
+
238
+ .ds-combobox__option--selected .ds-combobox__option-label {
239
+ color: var(--color-action-primary-text-tertiary);
240
+ }
241
+
242
+ .ds-combobox__option--disabled {
243
+ opacity: 0.4;
244
+ cursor: not-allowed;
245
+ }
246
+
247
+ .ds-combobox__option--disabled:hover {
248
+ background-color: transparent;
249
+ }
250
+
251
+ .ds-combobox__option-text {
252
+ display: flex;
253
+ flex-direction: column;
254
+ gap: var(--gap-xxs);
255
+ min-width: 0;
256
+ }
257
+
258
+ .ds-combobox__option-label {
259
+ font-family: var(--font-paragraph-em-family);
260
+ font-size: var(--font-paragraph-em-size);
261
+ font-weight: var(--font-paragraph-em-weight);
262
+ line-height: var(--font-paragraph-em-line-height);
263
+ letter-spacing: var(--font-paragraph-em-letter-spacing);
264
+ color: var(--color-text-primary);
265
+ }
266
+
267
+ .ds-combobox__option-description {
268
+ font-family: var(--font-paragraph-sm-family);
269
+ font-size: var(--font-paragraph-sm-size);
270
+ font-weight: var(--font-paragraph-sm-weight);
271
+ line-height: var(--font-paragraph-sm-line-height);
272
+ letter-spacing: var(--font-paragraph-sm-letter-spacing);
273
+ color: var(--color-text-tertiary);
274
+ }
275
+
276
+ .ds-combobox__check {
277
+ --icon-size: var(--icon-size-md);
278
+ color: var(--color-action-primary-bg);
279
+ flex-shrink: 0;
280
+ }
281
+
282
+ /* ============================================
283
+ GROUPS
284
+ ============================================ */
285
+
286
+ .ds-combobox__group {
287
+ list-style: none;
288
+ }
289
+
290
+ .ds-combobox__group-label {
291
+ display: block;
292
+ font-family: var(--font-paragraph-sm-family);
293
+ font-size: var(--font-paragraph-sm-size);
294
+ font-weight: var(--font-paragraph-sm-em-weight);
295
+ line-height: var(--font-paragraph-sm-line-height);
296
+ letter-spacing: var(--font-paragraph-sm-letter-spacing);
297
+ color: var(--color-text-tertiary);
298
+ padding: var(--padding-xs) var(--padding-sm-md);
299
+ user-select: none;
300
+ }
301
+
302
+ .ds-combobox__group-list {
303
+ list-style: none;
304
+ margin: 0;
305
+ padding: 0;
306
+ }
307
+
308
+ /* ============================================
309
+ STATUS ROW — loading / empty
310
+ ============================================ */
311
+
312
+ .ds-combobox__status {
313
+ padding: var(--padding-sm) var(--padding-sm-md);
314
+ font-family: var(--font-paragraph-sm-family);
315
+ font-size: var(--font-paragraph-sm-size);
316
+ font-weight: var(--font-paragraph-sm-weight);
317
+ line-height: var(--font-paragraph-sm-line-height);
318
+ letter-spacing: var(--font-paragraph-sm-letter-spacing);
319
+ color: var(--color-text-tertiary);
320
+ list-style: none;
321
+ }
322
+
323
+ /* ============================================
324
+ HELPER TEXT
325
+ ============================================ */
326
+
327
+ .ds-combobox__helper {
328
+ font-family: var(--font-paragraph-sm-family);
329
+ font-size: var(--font-paragraph-sm-size);
330
+ font-weight: var(--font-paragraph-sm-weight);
331
+ line-height: var(--font-paragraph-sm-line-height);
332
+ letter-spacing: var(--font-paragraph-sm-letter-spacing);
333
+ color: var(--color-text-tertiary);
334
+ margin: 0;
335
+ }
336
+
337
+ /* ============================================
338
+ ERROR STATE
339
+ ============================================ */
340
+
341
+ .ds-combobox--error .ds-combobox__control {
342
+ border-color: var(--color-status-error-border);
343
+ }
344
+
345
+ .ds-combobox--error .ds-combobox__helper {
346
+ color: var(--color-status-error-border);
347
+ }
348
+
349
+ /* ============================================
350
+ DISABLED STATE
351
+ ============================================ */
352
+
353
+ .ds-combobox--disabled .ds-combobox__label {
354
+ color: var(--color-input-text-disabled);
355
+ }
356
+
357
+ .ds-combobox--disabled .ds-combobox__control {
358
+ background-color: var(--color-input-bg-disabled);
359
+ border-color: var(--color-input-border-disabled);
360
+ cursor: not-allowed;
361
+ }
362
+
363
+ .ds-combobox--disabled .ds-combobox__input {
364
+ color: var(--color-input-text-disabled);
365
+ cursor: not-allowed;
366
+ }
367
+
368
+ .ds-combobox--disabled .ds-combobox__search-icon,
369
+ .ds-combobox--disabled .ds-combobox__chevron {
370
+ color: var(--color-input-text-disabled);
371
+ }
372
+
373
+ /* ============================================
374
+ SIZE — COMPACT
375
+ ============================================ */
376
+
377
+ .ds-combobox--compact .ds-combobox__control {
378
+ padding: var(--padding-xs) var(--padding-sm-md); /* 6px 12px */
379
+ }
380
+
381
+ .ds-combobox--compact .ds-combobox__label {
382
+ font-size: var(--font-paragraph-sm-size);
383
+ line-height: var(--font-paragraph-sm-line-height);
384
+ }
385
+
386
+ .ds-combobox--compact .ds-combobox__input,
387
+ .ds-combobox--compact .ds-combobox__option-label {
388
+ font-size: var(--font-paragraph-sm-em-size);
389
+ line-height: var(--font-paragraph-sm-em-line-height);
390
+ letter-spacing: var(--font-paragraph-sm-em-letter-spacing);
391
+ }
392
+
393
+ .ds-combobox--compact .ds-combobox__option {
394
+ padding: var(--padding-xs) var(--padding-sm); /* 6px 8px */
395
+ }
396
+
397
+ .ds-combobox--compact .ds-combobox__search-icon,
398
+ .ds-combobox--compact .ds-combobox__chevron,
399
+ .ds-combobox--compact .ds-combobox__check {
400
+ --icon-size: var(--icon-size-sm);
401
+ }
402
+
403
+ /* ============================================
404
+ REDUCED MOTION
405
+ ============================================ */
406
+
407
+ @media (prefers-reduced-motion: reduce) {
408
+ .ds-combobox__menu {
409
+ animation: none;
410
+ }
411
+ }
@@ -0,0 +1,73 @@
1
+ import { default as React } from 'react';
2
+ export interface ComboboxOption {
3
+ /** Display label — also the text matched when filtering */
4
+ label: string;
5
+ /** Option value */
6
+ value: string;
7
+ /** Optional secondary line shown under the label */
8
+ description?: string;
9
+ /** Whether this option is disabled */
10
+ disabled?: boolean;
11
+ }
12
+ export interface ComboboxOptionGroup {
13
+ /** Group heading */
14
+ label: string;
15
+ /** Options within the group */
16
+ options: ComboboxOption[];
17
+ }
18
+ export interface ComboboxProps {
19
+ /** Combobox label text */
20
+ label?: string;
21
+ /** Placeholder shown in the text field when nothing is selected */
22
+ placeholder?: string;
23
+ /**
24
+ * Selected value — a `string` in single mode, `string[]` when `multiple`
25
+ * is set. Leave undefined for an empty selection.
26
+ */
27
+ value?: string | string[];
28
+ /** Available options (flat list) */
29
+ options: ComboboxOption[];
30
+ /** Optional grouped options — when provided, `options` is ignored */
31
+ groups?: ComboboxOptionGroup[];
32
+ /** Allow selecting more than one option; selections render as removable chips */
33
+ multiple?: boolean;
34
+ /** Component size */
35
+ size?: 'default' | 'compact';
36
+ /** Whether the combobox is disabled */
37
+ disabled?: boolean;
38
+ /** Whether the combobox is required */
39
+ required?: boolean;
40
+ /** Error state — shows error styling and message */
41
+ error?: boolean;
42
+ /** Helper or error message displayed below the field */
43
+ helperText?: string;
44
+ /** Show a loading affordance in the menu — for async option fetching */
45
+ loading?: boolean;
46
+ /** Message shown when the filter matches no options */
47
+ emptyMessage?: string;
48
+ /** Show a clear button once something is selected */
49
+ clearable?: boolean;
50
+ /**
51
+ * Called with the new selection — a `string` in single mode,
52
+ * `string[]` when `multiple` is set.
53
+ */
54
+ onChange?: (value: string | string[]) => void;
55
+ /** Called as the user types, for async/server-side filtering */
56
+ onSearchChange?: (query: string) => void;
57
+ /** Skip built-in filtering — use when options are filtered upstream */
58
+ manualFiltering?: boolean;
59
+ /** Additional CSS classes */
60
+ className?: string;
61
+ /** Accessible name override */
62
+ ariaLabel?: string;
63
+ /** HTML name attribute */
64
+ name?: string;
65
+ /** HTML id attribute */
66
+ id?: string;
67
+ }
68
+ /**
69
+ * Combobox component — a text field combined with a filterable listbox.
70
+ * Unlike Dropdown (a static select), it narrows options as the user types
71
+ * and supports multi-select chips and async option loading.
72
+ */
73
+ export declare const Combobox: ({ label, placeholder, value, options, groups, multiple, size, disabled, required, error, helperText, loading, emptyMessage, clearable, onChange, onSearchChange, manualFiltering, className, ariaLabel, name, id, }: ComboboxProps) => React.JSX.Element;