@syscore/ui-library 1.27.3 → 2.0.0-beta-publish-workflow-beta.2

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 (169) hide show
  1. package/client/App.tsx +0 -2
  2. package/client/assets/alert/icon-clear.svg +4 -0
  3. package/client/assets/alert/icon-done.svg +3 -0
  4. package/client/assets/avatar-identity/photo.png +0 -0
  5. package/client/assets/avatar-identity/placeholder-icon.svg +8 -0
  6. package/client/assets/breadcrumb/icon-ellipsis.svg +5 -0
  7. package/client/assets/breadcrumb/icon-home.svg +3 -0
  8. package/client/assets/breadcrumb/icon-separator.svg +3 -0
  9. package/client/assets/button-v01/icon-back.svg +4 -0
  10. package/client/assets/button-v01/icon-check.svg +3 -0
  11. package/client/assets/button-v01/icon-close.svg +4 -0
  12. package/client/assets/button-v01/icon-delete.svg +3 -0
  13. package/client/assets/button-v01/icon-device.svg +3 -0
  14. package/client/assets/dropdown/icon-carrot-contract.svg +3 -0
  15. package/client/assets/dropdown/icon-carrot-expand.svg +3 -0
  16. package/client/assets/dropdown/icon-clear.svg +4 -0
  17. package/client/assets/dropdown/icon-enter.svg +3 -0
  18. package/client/components/icons/UtilityChangeType.tsx +21 -0
  19. package/client/components/ui/alert-dialog-panel.tsx +246 -0
  20. package/client/components/ui/alert-v02.tsx +214 -0
  21. package/client/components/ui/app-bar.tsx +299 -0
  22. package/client/components/ui/avatar-identity.tsx +122 -0
  23. package/client/components/ui/banner.tsx +108 -0
  24. package/client/components/ui/bottom-navigation.tsx +223 -0
  25. package/client/components/ui/breadcrumb-trail.tsx +170 -0
  26. package/client/components/ui/button-v01.tsx +238 -0
  27. package/client/components/ui/button.tsx +2 -0
  28. package/client/components/ui/card.tsx +108 -26
  29. package/client/components/ui/code-badge.tsx +62 -0
  30. package/client/components/ui/date-picker.tsx +188 -0
  31. package/client/components/ui/dropdown.tsx +448 -0
  32. package/client/components/ui/empty-state.tsx +197 -0
  33. package/client/components/ui/file-upload.tsx +214 -0
  34. package/client/components/ui/footer.tsx +179 -0
  35. package/client/components/ui/layout.tsx +1182 -0
  36. package/client/components/ui/pagination-v01.tsx +157 -0
  37. package/client/components/ui/password-field-v01.tsx +67 -0
  38. package/client/components/ui/search-field-v01.tsx +192 -0
  39. package/client/components/ui/section-heading.tsx +49 -0
  40. package/client/components/ui/sidebar.tsx +2 -3
  41. package/client/components/ui/standard-navigation.tsx +8 -2
  42. package/client/components/ui/stepper.tsx +148 -0
  43. package/client/components/ui/switch-v01.tsx +71 -0
  44. package/client/components/ui/system-bar.tsx +119 -0
  45. package/client/components/ui/table-v01.tsx +230 -0
  46. package/client/components/ui/tabs-v01.tsx +99 -0
  47. package/client/components/ui/tag-v02.tsx +113 -0
  48. package/client/components/ui/text-area-v01.tsx +33 -0
  49. package/client/components/ui/text-field-v01.tsx +108 -0
  50. package/client/components/ui/timeline.tsx +181 -0
  51. package/client/components/ui/toast-v01.tsx +206 -0
  52. package/client/components/ui/tooltip.tsx +264 -71
  53. package/client/global.css +9565 -4378
  54. package/client/storybook.css +125 -0
  55. package/client/ui/Accordion.stories.tsx +1 -1
  56. package/client/ui/AlertDialogPanel/AlertDialogPanel.stories.tsx +150 -0
  57. package/client/ui/AlertV02/AlertV02.stories.tsx +188 -0
  58. package/client/ui/AppBar/app-bar.stories.tsx +280 -0
  59. package/client/ui/AspectRatio.stories.tsx +1 -1
  60. package/client/ui/AvatarIdentity/AvatarIdentity.stories.tsx +77 -0
  61. package/client/ui/Banner/banner.stories.tsx +238 -0
  62. package/client/ui/BottomNavigation/bottom-navigation.stories.tsx +285 -0
  63. package/client/ui/BreadcrumbTrail/BreadcrumbTrail.stories.tsx +232 -0
  64. package/client/ui/Button.stories.tsx +1 -1
  65. package/client/ui/ButtonV01/ButtonV01.stories.tsx +417 -0
  66. package/client/ui/Calendar/Calendar.stories.tsx +1 -1
  67. package/client/ui/Card.stories.tsx +285 -168
  68. package/client/ui/Carousel/Carousel.stories.tsx +1 -1
  69. package/client/ui/Chart/Chart.stories.tsx +1 -1
  70. package/client/ui/Checkbox.stories.tsx +1 -1
  71. package/client/ui/Collapsible/Collapsible.stories.tsx +1 -1
  72. package/client/ui/Colors.stories.tsx +1 -1
  73. package/client/ui/Command/Command.stories.tsx +1 -1
  74. package/client/ui/ContextMenu/ContextMenu.stories.tsx +1 -1
  75. package/client/ui/DatePicker/DatePicker.stories.tsx +293 -0
  76. package/client/ui/Dialog.stories.tsx +1 -1
  77. package/client/ui/Drawer/Drawer.stories.tsx +1 -1
  78. package/client/ui/Dropdown/Dropdown.stories.tsx +205 -0
  79. package/client/ui/EmptyState/empty-state.stories.tsx +251 -0
  80. package/client/ui/FileUpload/FileUpload.stories.tsx +218 -0
  81. package/client/ui/Footer/footer.stories.tsx +194 -0
  82. package/client/ui/Form/Form.stories.tsx +1 -1
  83. package/client/ui/Hero.stories.tsx +1 -1
  84. package/client/ui/HoverCard/HoverCard.stories.tsx +1 -1
  85. package/client/ui/Icons.stories.tsx +1 -1
  86. package/client/ui/Input.stories.tsx +1 -1
  87. package/client/ui/InputOTP/InputOTP.stories.tsx +1 -1
  88. package/client/ui/Label.stories.tsx +1 -1
  89. package/client/ui/Layout/Center.stories.tsx +100 -0
  90. package/client/ui/Layout/Columns.stories.tsx +136 -0
  91. package/client/ui/Layout/Container.stories.tsx +104 -0
  92. package/client/ui/Layout/FormLayout.stories.tsx +144 -0
  93. package/client/ui/Layout/Grid.stories.tsx +158 -0
  94. package/client/ui/Layout/GridSpan.stories.tsx +75 -0
  95. package/client/ui/Layout/HStack.stories.tsx +128 -0
  96. package/client/ui/Layout/Layout.stories.tsx +287 -0
  97. package/client/ui/Layout/LayoutContent.stories.tsx +91 -0
  98. package/client/ui/Layout/LayoutFooter.stories.tsx +77 -0
  99. package/client/ui/Layout/LayoutHeader.stories.tsx +104 -0
  100. package/client/ui/Layout/LayoutPanel.stories.tsx +143 -0
  101. package/client/ui/Layout/Positioned.stories.tsx +113 -0
  102. package/client/ui/Layout/Section.stories.tsx +84 -0
  103. package/client/ui/Layout/ShowHide.stories.tsx +99 -0
  104. package/client/ui/Layout/Spacer.stories.tsx +149 -0
  105. package/client/ui/Layout/Stack.stories.tsx +69 -0
  106. package/client/ui/Layout/StackItem.stories.tsx +124 -0
  107. package/client/ui/Layout/VStack.stories.tsx +101 -0
  108. package/client/ui/Layout/controls.ts +33 -0
  109. package/client/ui/Layout/demo.tsx +37 -0
  110. package/client/ui/Menubar/Menubar.stories.tsx +1 -1
  111. package/client/ui/MobileNav.stories.tsx +1 -1
  112. package/client/ui/Navigation.stories.tsx +1 -1
  113. package/client/ui/NavigationMenu/NavigationMenu.stories.tsx +1 -1
  114. package/client/ui/PageHeader.stories.tsx +13 -13
  115. package/client/ui/Pagination/Pagination.stories.tsx +178 -98
  116. package/client/ui/Pagination/PaginationLegacy.stories.tsx +121 -0
  117. package/client/ui/Panel.stories.tsx +1 -1
  118. package/client/ui/Popover/Popover.stories.tsx +1 -1
  119. package/client/ui/Progress/Progress.stories.tsx +1 -1
  120. package/client/ui/RadioGroup/RadioGroup.stories.tsx +1 -1
  121. package/client/ui/Resizable/Resizable.stories.tsx +1 -1
  122. package/client/ui/ScrollArea/ScrollArea.stories.tsx +1 -1
  123. package/client/ui/SearchField/SearchField.stories.tsx +153 -0
  124. package/client/ui/{SearchField.stories.tsx → SearchField/SearchFieldLegacy.stories.tsx} +2 -2
  125. package/client/ui/SectionBadge.stories.tsx +1 -1
  126. package/client/ui/Select.stories.tsx +1 -1
  127. package/client/ui/Separator/Separator.stories.tsx +1 -1
  128. package/client/ui/Sheet/Sheet.stories.tsx +1 -1
  129. package/client/ui/Sidebar/Sidebar.stories.tsx +57 -8
  130. package/client/ui/Skeleton/Skeleton.stories.tsx +1 -1
  131. package/client/ui/Slider/Slider.stories.tsx +1 -1
  132. package/client/ui/StandardNavigation.stories.tsx +1 -1
  133. package/client/ui/Stepper/Stepper.stories.tsx +344 -0
  134. package/client/ui/Switch.stories.tsx +1 -1
  135. package/client/ui/SwitchV01/SwitchV01.stories.tsx +152 -0
  136. package/client/ui/SystemBar/system-bar.stories.tsx +179 -0
  137. package/client/ui/Table/TableV01.stories.tsx +256 -0
  138. package/client/ui/Tabs.stories.tsx +1 -1
  139. package/client/ui/TabsV01/TabsV01.stories.tsx +144 -0
  140. package/client/ui/Tag.stories.tsx +1 -1
  141. package/client/ui/TagV02/TagStatusV02.stories.tsx +132 -0
  142. package/client/ui/TagV02/TagV02.stories.tsx +142 -0
  143. package/client/ui/TextAreaV01/TextAreaV01.stories.tsx +146 -0
  144. package/client/ui/TextFieldV01/PasswordFieldV01.stories.tsx +161 -0
  145. package/client/ui/TextFieldV01/TextFieldV01.stories.tsx +160 -0
  146. package/client/ui/Textarea.stories.tsx +1 -1
  147. package/client/ui/Timeline/timeline.stories.tsx +404 -0
  148. package/client/ui/Toast/Toast.stories.tsx +1 -1
  149. package/client/ui/ToastV01/ToastV01.stories.tsx +201 -0
  150. package/client/ui/Toaster/Toaster.stories.tsx +1 -1
  151. package/client/ui/Toggle.stories.tsx +1 -1
  152. package/client/ui/Tooltip.stories.tsx +287 -114
  153. package/client/ui/Typography.stories.tsx +1 -1
  154. package/dist/index.cjs.js +1 -1
  155. package/dist/index.d.ts +649 -13
  156. package/dist/index.es.js +4405 -653
  157. package/package.json +1 -1
  158. package/client/components/ui/badge.tsx +0 -33
  159. package/client/components/ui/sonner.tsx +0 -26
  160. package/client/components/ui/toggle-group.tsx +0 -76
  161. package/client/ui/Alert/Alert.stories.tsx +0 -82
  162. package/client/ui/AlertDialog/AlertDialog.stories.tsx +0 -106
  163. package/client/ui/Avatar/Avatar.stories.tsx +0 -94
  164. package/client/ui/Badge/Badge.stories.tsx +0 -60
  165. package/client/ui/Breadcrumb/Breadcrumb.stories.tsx +0 -97
  166. package/client/ui/DropdownMenu/DropdownMenu.stories.tsx +0 -139
  167. package/client/ui/Sonner/Sonner.stories.tsx +0 -48
  168. package/client/ui/Table/Table.stories.tsx +0 -135
  169. package/client/ui/ToggleGroup/ToggleGroup.stories.tsx +0 -88
@@ -0,0 +1,293 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { useState } from "react";
3
+ import { DatePicker, DateRangePicker, type DateRange } from "../../components/ui/date-picker";
4
+
5
+ const meta = {
6
+ title: "Components/DatePicker",
7
+ component: DatePicker,
8
+ tags: ["autodocs"],
9
+ parameters: {
10
+ layout: "padded",
11
+ docs: {
12
+ description: {
13
+ component: [
14
+ "A text input that opens a Calendar popover when clicked. Supports single date and date range selection.",
15
+ "",
16
+ "**The difference from Calendar:**",
17
+ "- `Calendar` — always visible grid, sits on the page",
18
+ "- `DatePicker` — input field that pops open a calendar, closes after selection",
19
+ "",
20
+ "**Import:**",
21
+ "```tsx",
22
+ `import { DatePicker, DateRangePicker } from "@syscore/ui-library"`,
23
+ "```",
24
+ "",
25
+ "**Key props:**",
26
+ "",
27
+ "| Prop | Type | Default | Effect |",
28
+ "|------|------|---------|--------|",
29
+ "| `value` | `Date` | — | Controlled selected date |",
30
+ "| `onChange` | `(date?: Date) => void` | — | Called when date is picked |",
31
+ "| `placeholder` | string | `\"Select date\"` | Input placeholder text |",
32
+ "| `dateFormat` | string | `\"MMM d, yyyy\"` | Display format (date-fns) |",
33
+ "| `fromDate` | `Date` | — | Disable dates before this |",
34
+ "| `toDate` | `Date` | — | Disable dates after this |",
35
+ "| `disabled` | boolean | `false` | Disable the input |",
36
+ ].join("\n"),
37
+ },
38
+ },
39
+ },
40
+ } satisfies Meta<typeof DatePicker>;
41
+
42
+ export default meta;
43
+ type Story = StoryObj<typeof meta>;
44
+
45
+ export const Default: Story = {
46
+ parameters: {
47
+ docs: {
48
+ source: {
49
+ code: `import { DatePicker } from "@syscore/ui-library"
50
+ import { useState } from "react"
51
+
52
+ const [date, setDate] = useState<Date>()
53
+
54
+ <DatePicker
55
+ value={date}
56
+ onChange={setDate}
57
+ placeholder="Select date"
58
+ />`,
59
+ },
60
+ },
61
+ },
62
+ render: () => {
63
+ const [date, setDate] = useState<Date>();
64
+ return (
65
+ <div className="max-w-xs">
66
+ <DatePicker
67
+ value={date}
68
+ onChange={setDate}
69
+ placeholder="Select date"
70
+ />
71
+ {date && (
72
+ <p className="mt-2 text-sm text-gray-500">Selected: {date.toDateString()}</p>
73
+ )}
74
+ </div>
75
+ );
76
+ },
77
+ };
78
+
79
+ export const WithDefaultValue: Story = {
80
+ name: "With default value",
81
+ parameters: {
82
+ docs: {
83
+ source: {
84
+ code: `import { DatePicker } from "@syscore/ui-library"
85
+ import { useState } from "react"
86
+
87
+ const [date, setDate] = useState<Date>(new Date())
88
+
89
+ <DatePicker value={date} onChange={setDate} />`,
90
+ },
91
+ },
92
+ },
93
+ render: () => {
94
+ const [date, setDate] = useState<Date>(new Date());
95
+ return (
96
+ <div className="max-w-xs">
97
+ <DatePicker value={date} onChange={setDate} />
98
+ </div>
99
+ );
100
+ },
101
+ };
102
+
103
+ export const WithDateLimits: Story = {
104
+ name: "With date limits",
105
+ parameters: {
106
+ docs: {
107
+ source: {
108
+ code: `import { DatePicker } from "@syscore/ui-library"
109
+ import { useState } from "react"
110
+
111
+ // Only allow dates from today onwards
112
+ const [date, setDate] = useState<Date>()
113
+ const today = new Date()
114
+
115
+ <DatePicker
116
+ value={date}
117
+ onChange={setDate}
118
+ fromDate={today}
119
+ placeholder="Select future date"
120
+ />`,
121
+ },
122
+ },
123
+ },
124
+ render: () => {
125
+ const [date, setDate] = useState<Date>();
126
+ const today = new Date();
127
+ return (
128
+ <div className="max-w-xs">
129
+ <DatePicker
130
+ value={date}
131
+ onChange={setDate}
132
+ fromDate={today}
133
+ placeholder="Select future date"
134
+ />
135
+ <p className="mt-2 text-xs text-gray-400">Dates before today are disabled</p>
136
+ </div>
137
+ );
138
+ },
139
+ };
140
+
141
+ export const CustomFormat: Story = {
142
+ name: "Custom date format",
143
+ parameters: {
144
+ docs: {
145
+ source: {
146
+ code: `import { DatePicker } from "@syscore/ui-library"
147
+
148
+ // Uses date-fns format tokens
149
+ <DatePicker
150
+ value={date}
151
+ onChange={setDate}
152
+ dateFormat="dd/MM/yyyy"
153
+ />`,
154
+ },
155
+ },
156
+ },
157
+ render: () => {
158
+ const [date, setDate] = useState<Date>(new Date());
159
+ return (
160
+ <div className="flex flex-col gap-4 max-w-xs">
161
+ <div className="flex flex-col gap-1">
162
+ <span className="text-xs text-gray-500">MMM d, yyyy (default)</span>
163
+ <DatePicker value={date} onChange={setDate} dateFormat="MMM d, yyyy" />
164
+ </div>
165
+ <div className="flex flex-col gap-1">
166
+ <span className="text-xs text-gray-500">dd/MM/yyyy</span>
167
+ <DatePicker value={date} onChange={setDate} dateFormat="dd/MM/yyyy" />
168
+ </div>
169
+ <div className="flex flex-col gap-1">
170
+ <span className="text-xs text-gray-500">MMMM do, yyyy</span>
171
+ <DatePicker value={date} onChange={setDate} dateFormat="MMMM do, yyyy" />
172
+ </div>
173
+ </div>
174
+ );
175
+ },
176
+ };
177
+
178
+ export const Disabled: Story = {
179
+ parameters: {
180
+ docs: {
181
+ source: {
182
+ code: `import { DatePicker } from "@syscore/ui-library"
183
+
184
+ <DatePicker disabled placeholder="Not available" />`,
185
+ },
186
+ },
187
+ },
188
+ render: () => (
189
+ <div className="max-w-xs">
190
+ <DatePicker disabled placeholder="Not available" />
191
+ </div>
192
+ ),
193
+ };
194
+
195
+ export const RangePicker: Story = {
196
+ name: "Date range picker",
197
+ parameters: {
198
+ docs: {
199
+ source: {
200
+ code: `import { DateRangePicker, type DateRange } from "@syscore/ui-library"
201
+ import { useState } from "react"
202
+
203
+ const [range, setRange] = useState<DateRange>()
204
+
205
+ <DateRangePicker
206
+ value={range}
207
+ onChange={setRange}
208
+ placeholder="Select date range"
209
+ />`,
210
+ },
211
+ },
212
+ },
213
+ render: () => {
214
+ const [range, setRange] = useState<DateRange>();
215
+ return (
216
+ <div className="max-w-sm">
217
+ <DateRangePicker
218
+ value={range}
219
+ onChange={setRange}
220
+ placeholder="Select date range"
221
+ />
222
+ {range?.from && (
223
+ <p className="mt-2 text-sm text-gray-500">
224
+ {range.from.toDateString()} {range.to ? `→ ${range.to.toDateString()}` : "→ pick end date"}
225
+ </p>
226
+ )}
227
+ </div>
228
+ );
229
+ },
230
+ };
231
+
232
+ export const InForm: Story = {
233
+ name: "Inside a form",
234
+ parameters: {
235
+ docs: {
236
+ source: {
237
+ code: `import { DatePicker, DateRangePicker } from "@syscore/ui-library"
238
+ import { Stack, Text, Button } from "@syscore/ui-library"
239
+
240
+ <Stack gap="xl">
241
+ <Stack gap="xs">
242
+ <Text variant="overline-small">Payment date</Text>
243
+ <DatePicker
244
+ value={paymentDate}
245
+ onChange={setPaymentDate}
246
+ placeholder="Select date"
247
+ />
248
+ </Stack>
249
+
250
+ <Stack gap="xs">
251
+ <Text variant="overline-small">Project period</Text>
252
+ <DateRangePicker
253
+ value={period}
254
+ onChange={setPeriod}
255
+ placeholder="Start — End"
256
+ />
257
+ </Stack>
258
+
259
+ <Button variant="primary-dark" size="large">Save</Button>
260
+ </Stack>`,
261
+ },
262
+ },
263
+ },
264
+ render: () => {
265
+ const [paymentDate, setPaymentDate] = useState<Date>();
266
+ const [period, setPeriod] = useState<DateRange>();
267
+ return (
268
+ <div className="max-w-sm border border-gray-100 rounded-xl p-6">
269
+ <div className="flex flex-col gap-6">
270
+ <div className="flex flex-col gap-2">
271
+ <span className="text-xs font-semibold uppercase tracking-wider text-gray-500">Payment date</span>
272
+ <DatePicker
273
+ value={paymentDate}
274
+ onChange={setPaymentDate}
275
+ placeholder="Select date"
276
+ />
277
+ </div>
278
+ <div className="flex flex-col gap-2">
279
+ <span className="text-xs font-semibold uppercase tracking-wider text-gray-500">Project period</span>
280
+ <DateRangePicker
281
+ value={period}
282
+ onChange={setPeriod}
283
+ placeholder="Start — End"
284
+ />
285
+ </div>
286
+ <button className="w-full bg-gray-900 text-white rounded-lg py-2.5 text-sm font-medium">
287
+ Save
288
+ </button>
289
+ </div>
290
+ </div>
291
+ );
292
+ },
293
+ };
@@ -37,7 +37,7 @@ function useIsMobile(breakpoint = 640) {
37
37
  }
38
38
 
39
39
  const meta = {
40
- title: "Review/Dialog",
40
+ title: "Components/Dialog",
41
41
  component: Dialog,
42
42
  tags: ["autodocs"],
43
43
  parameters: {
@@ -13,7 +13,7 @@ import { Button } from "../../components/ui/button";
13
13
  import { useState } from "react";
14
14
 
15
15
  const meta = {
16
- title: "UI/Drawer",
16
+ title: "Draft/Drawer",
17
17
  component: Drawer,
18
18
  tags: ["autodocs"],
19
19
  parameters: {
@@ -0,0 +1,205 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { Dropdown } from "../../components/ui/dropdown";
3
+
4
+ const items = [
5
+ { value: "item-1", label: "Item" },
6
+ { value: "item-2", label: "Item" },
7
+ { value: "item-3", label: "Item" },
8
+ ];
9
+
10
+ const typeaheadItems = [
11
+ { value: "entry-typeahead", label: "Entrytypeahead" },
12
+ { value: "entry-unmatch-1", label: "Entryunmatch" },
13
+ { value: "entry-unmatch-2", label: "Entryunmatch" },
14
+ ];
15
+
16
+ const autoSuggestItems = [
17
+ {
18
+ value: "create",
19
+ label: "Appendix I: Environmental",
20
+ actionLabel: "Create new",
21
+ },
22
+ {
23
+ value: "680924a0ffb5a0bb2880e677",
24
+ label: "Appendix I: Environmental satisfaction survey criteria",
25
+ secondary: "680924a0ffb5a0bb2880e677",
26
+ },
27
+ ];
28
+
29
+ const meta = {
30
+ title: "Components/Dropdown",
31
+ component: Dropdown,
32
+ tags: ["autodocs"],
33
+ parameters: {
34
+ layout: "centered",
35
+ docs: {
36
+ description: {
37
+ component: [
38
+ "Labeled combobox.",
39
+ "",
40
+ "States: **Default**, **Focus**, **Active** (typeahead), **Filled**,",
41
+ "**Auto suggest**, and **Error**. Open the menu by focusing the field,",
42
+ "or lock a state with `open` / `error` in Controls.",
43
+ "",
44
+ "---",
45
+ "",
46
+ "## Import",
47
+ "",
48
+ "```tsx",
49
+ `import { Dropdown } from "@syscore/ui-library"`,
50
+ "```",
51
+ "",
52
+ "## How to use",
53
+ "",
54
+ "Pass `options` and read the selected value from `onValueChange`.",
55
+ "This is a labeled combobox, not a menu of actions — use `DropdownMenu` for that.",
56
+ "",
57
+ "```tsx",
58
+ "const [value, setValue] = useState<string>()",
59
+ "",
60
+ "<Dropdown",
61
+ ` label="Theme"`,
62
+ ` placeholder="Choose a theme"`,
63
+ " value={value}",
64
+ " onValueChange={setValue}",
65
+ " options={[",
66
+ ` { value: "community", label: "Community" },`,
67
+ ` { value: "movement", label: "Movement" },`,
68
+ " ]}",
69
+ "/>",
70
+ "```",
71
+ "",
72
+ "Two-line suggestions use `secondary`. A trailing action uses `actionLabel`.",
73
+ "Validation uses `error` and `errorMessage`.",
74
+ "",
75
+ "```tsx",
76
+ "<Dropdown",
77
+ ` label="Appendix"`,
78
+ " error={!value}",
79
+ ` errorMessage="Choose an option"`,
80
+ " options={[",
81
+ " {",
82
+ ` value: "create",`,
83
+ ` label: "Appendix I: Environmental",`,
84
+ ` actionLabel: "Create new",`,
85
+ " },",
86
+ " {",
87
+ ` value: "6809",`,
88
+ ` label: "Appendix I: Environmental satisfaction survey criteria",`,
89
+ ` secondary: "680924a0ffb5a0bb2880e677",`,
90
+ " },",
91
+ " ]}",
92
+ "/>",
93
+ "```",
94
+ "",
95
+ "## Props",
96
+ "",
97
+ "| Prop | Values | Default | Effect |",
98
+ "|------|--------|---------|--------|",
99
+ "| `label` | `string` | `\"Label\"` | Field label |",
100
+ "| `placeholder` | `string` | `\"Placeholder\"` | Empty-state text |",
101
+ "| `options` | `{ value, label, secondary?, actionLabel? }[]` | `[]` | Menu items |",
102
+ "| `value` / `defaultValue` | `string` | — | Selected option |",
103
+ "| `onValueChange` | `(value: string) => void` | — | Selection handler |",
104
+ "| `error` | `boolean` | `false` | Error chrome |",
105
+ "| `errorMessage` | `string` | `\"Choose an option\"` | Helper under the field |",
106
+ "| `disabled` | `boolean` | `false` | Blocks input |",
107
+ "| `open` / `defaultOpen` | `boolean` | — | Controlled / initial menu |",
108
+ ].join("\n"),
109
+ },
110
+ },
111
+ },
112
+ argTypes: {
113
+ label: { control: "text" },
114
+ placeholder: { control: "text" },
115
+ error: { control: "boolean" },
116
+ errorMessage: { control: "text" },
117
+ disabled: { control: "boolean" },
118
+ open: { control: "boolean" },
119
+ },
120
+ args: {
121
+ label: "Label",
122
+ placeholder: "Placeholder",
123
+ options: items,
124
+ },
125
+ decorators: [
126
+ (Story) => (
127
+ <div style={{ minHeight: 280, width: 344 }}>
128
+ <Story />
129
+ </div>
130
+ ),
131
+ ],
132
+ } satisfies Meta<typeof Dropdown>;
133
+
134
+ export default meta;
135
+ type Story = StoryObj<typeof meta>;
136
+
137
+ export const Default: Story = {};
138
+
139
+ export const Focus: Story = {
140
+ args: { open: true },
141
+ };
142
+
143
+ export const Active: Story = {
144
+ args: {
145
+ open: true,
146
+ defaultInputValue: "Entry",
147
+ options: typeaheadItems,
148
+ },
149
+ };
150
+
151
+ export const Filled: Story = {
152
+ args: {
153
+ defaultValue: "item-1",
154
+ options: [{ value: "item-1", label: "Entry" }],
155
+ },
156
+ };
157
+
158
+ export const AutoSuggest: Story = {
159
+ args: {
160
+ open: true,
161
+ defaultInputValue: "Appendix I: Environmental",
162
+ options: autoSuggestItems,
163
+ },
164
+ };
165
+
166
+ export const Error: Story = {
167
+ args: {
168
+ error: true,
169
+ errorMessage: "Choose an option",
170
+ },
171
+ };
172
+
173
+ const tags = [
174
+ { id: "t1", label: "Tag", dot: true, changeType: "mild" as const },
175
+ { id: "t2", label: "Tag", dot: true, changeType: "medium" as const },
176
+ { id: "t3", label: "Tag", dot: true, changeType: "hot" as const },
177
+ { id: "t4", label: "Tag" },
178
+ ];
179
+
180
+ export const WithTags: Story = {
181
+ name: "Tags",
182
+ args: {
183
+ label: "Label",
184
+ placeholder: "Placeholder",
185
+ options: items,
186
+ tags,
187
+ onTagRemove: () => {},
188
+ onClearTags: () => {},
189
+ },
190
+ };
191
+
192
+ export const TagsChangeTypes: Story = {
193
+ name: "Tags · change types",
194
+ args: {
195
+ label: "Label",
196
+ placeholder: "Placeholder",
197
+ options: items,
198
+ tags: [
199
+ { id: "m", label: "Mild", changeType: "mild" as const },
200
+ { id: "d", label: "Medium", changeType: "medium" as const },
201
+ { id: "h", label: "Hot", changeType: "hot" as const },
202
+ { id: "b", label: "Branded", dot: true },
203
+ ],
204
+ },
205
+ };