@syscore/ui-library 1.25.0 → 2.0.0-beta-publish-workflow-beta.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.
- package/client/App.tsx +0 -2
- package/client/assets/alert/icon-clear.svg +4 -0
- package/client/assets/alert/icon-done.svg +3 -0
- package/client/assets/avatar-identity/photo.png +0 -0
- package/client/assets/avatar-identity/placeholder-icon.svg +8 -0
- package/client/assets/breadcrumb/icon-ellipsis.svg +5 -0
- package/client/assets/breadcrumb/icon-home.svg +3 -0
- package/client/assets/breadcrumb/icon-separator.svg +3 -0
- package/client/assets/button-v01/icon-back.svg +4 -0
- package/client/assets/button-v01/icon-check.svg +3 -0
- package/client/assets/button-v01/icon-close.svg +4 -0
- package/client/assets/button-v01/icon-delete.svg +3 -0
- package/client/assets/button-v01/icon-device.svg +3 -0
- package/client/assets/dropdown/icon-carrot-contract.svg +3 -0
- package/client/assets/dropdown/icon-carrot-expand.svg +3 -0
- package/client/assets/dropdown/icon-clear.svg +4 -0
- package/client/assets/dropdown/icon-enter.svg +3 -0
- package/client/components/icons/UtilityChangeType.tsx +21 -0
- package/client/components/ui/alert-dialog-panel.tsx +246 -0
- package/client/components/ui/alert-v02.tsx +214 -0
- package/client/components/ui/app-bar.tsx +299 -0
- package/client/components/ui/avatar-identity.tsx +122 -0
- package/client/components/ui/banner.tsx +108 -0
- package/client/components/ui/bottom-navigation.tsx +223 -0
- package/client/components/ui/breadcrumb-trail.tsx +170 -0
- package/client/components/ui/button-v01.tsx +238 -0
- package/client/components/ui/button.tsx +2 -0
- package/client/components/ui/card.tsx +108 -26
- package/client/components/ui/code-badge.tsx +62 -0
- package/client/components/ui/date-picker.tsx +188 -0
- package/client/components/ui/dropdown.tsx +448 -0
- package/client/components/ui/empty-state.tsx +197 -0
- package/client/components/ui/file-upload.tsx +214 -0
- package/client/components/ui/footer.tsx +179 -0
- package/client/components/ui/layout.tsx +1182 -0
- package/client/components/ui/pagination-v01.tsx +157 -0
- package/client/components/ui/password-field-v01.tsx +67 -0
- package/client/components/ui/search-field-v01.tsx +192 -0
- package/client/components/ui/section-heading.tsx +49 -0
- package/client/components/ui/sidebar.tsx +13 -8
- package/client/components/ui/stepper.tsx +148 -0
- package/client/components/ui/switch-v01.tsx +71 -0
- package/client/components/ui/system-bar.tsx +119 -0
- package/client/components/ui/table-v01.tsx +230 -0
- package/client/components/ui/tabs-v01.tsx +99 -0
- package/client/components/ui/tag-v02.tsx +113 -0
- package/client/components/ui/text-area-v01.tsx +33 -0
- package/client/components/ui/text-field-v01.tsx +108 -0
- package/client/components/ui/timeline.tsx +181 -0
- package/client/components/ui/toast-v01.tsx +206 -0
- package/client/components/ui/tooltip.tsx +264 -71
- package/client/global.css +9565 -4378
- package/client/storybook.css +125 -0
- package/client/ui/Accordion.stories.tsx +1 -1
- package/client/ui/AlertDialogPanel/AlertDialogPanel.stories.tsx +150 -0
- package/client/ui/AlertV02/AlertV02.stories.tsx +188 -0
- package/client/ui/AppBar/app-bar.stories.tsx +280 -0
- package/client/ui/AspectRatio.stories.tsx +1 -1
- package/client/ui/AvatarIdentity/AvatarIdentity.stories.tsx +77 -0
- package/client/ui/Banner/banner.stories.tsx +238 -0
- package/client/ui/BottomNavigation/bottom-navigation.stories.tsx +285 -0
- package/client/ui/BreadcrumbTrail/BreadcrumbTrail.stories.tsx +232 -0
- package/client/ui/Button.stories.tsx +1 -1
- package/client/ui/ButtonV01/ButtonV01.stories.tsx +417 -0
- package/client/ui/Calendar/Calendar.stories.tsx +1 -1
- package/client/ui/Card.stories.tsx +285 -168
- package/client/ui/Carousel/Carousel.stories.tsx +1 -1
- package/client/ui/Chart/Chart.stories.tsx +1 -1
- package/client/ui/Checkbox.stories.tsx +1 -1
- package/client/ui/Collapsible/Collapsible.stories.tsx +1 -1
- package/client/ui/Colors.stories.tsx +1 -1
- package/client/ui/Command/Command.stories.tsx +1 -1
- package/client/ui/ContextMenu/ContextMenu.stories.tsx +1 -1
- package/client/ui/DatePicker/DatePicker.stories.tsx +293 -0
- package/client/ui/Dialog.stories.tsx +1 -1
- package/client/ui/Drawer/Drawer.stories.tsx +1 -1
- package/client/ui/Dropdown/Dropdown.stories.tsx +205 -0
- package/client/ui/EmptyState/empty-state.stories.tsx +251 -0
- package/client/ui/FileUpload/FileUpload.stories.tsx +218 -0
- package/client/ui/Footer/footer.stories.tsx +194 -0
- package/client/ui/Form/Form.stories.tsx +1 -1
- package/client/ui/Hero.stories.tsx +1 -1
- package/client/ui/HoverCard/HoverCard.stories.tsx +1 -1
- package/client/ui/Icons.stories.tsx +1 -1
- package/client/ui/Input.stories.tsx +1 -1
- package/client/ui/InputOTP/InputOTP.stories.tsx +1 -1
- package/client/ui/Label.stories.tsx +1 -1
- package/client/ui/Layout/Center.stories.tsx +100 -0
- package/client/ui/Layout/Columns.stories.tsx +136 -0
- package/client/ui/Layout/Container.stories.tsx +104 -0
- package/client/ui/Layout/FormLayout.stories.tsx +144 -0
- package/client/ui/Layout/Grid.stories.tsx +158 -0
- package/client/ui/Layout/GridSpan.stories.tsx +75 -0
- package/client/ui/Layout/HStack.stories.tsx +128 -0
- package/client/ui/Layout/Layout.stories.tsx +287 -0
- package/client/ui/Layout/LayoutContent.stories.tsx +91 -0
- package/client/ui/Layout/LayoutFooter.stories.tsx +77 -0
- package/client/ui/Layout/LayoutHeader.stories.tsx +104 -0
- package/client/ui/Layout/LayoutPanel.stories.tsx +143 -0
- package/client/ui/Layout/Positioned.stories.tsx +113 -0
- package/client/ui/Layout/Section.stories.tsx +84 -0
- package/client/ui/Layout/ShowHide.stories.tsx +99 -0
- package/client/ui/Layout/Spacer.stories.tsx +149 -0
- package/client/ui/Layout/Stack.stories.tsx +69 -0
- package/client/ui/Layout/StackItem.stories.tsx +124 -0
- package/client/ui/Layout/VStack.stories.tsx +101 -0
- package/client/ui/Layout/controls.ts +33 -0
- package/client/ui/Layout/demo.tsx +37 -0
- package/client/ui/Menubar/Menubar.stories.tsx +1 -1
- package/client/ui/MobileNav.stories.tsx +1 -1
- package/client/ui/Navigation.stories.tsx +1 -1
- package/client/ui/NavigationMenu/NavigationMenu.stories.tsx +1 -1
- package/client/ui/PageHeader.stories.tsx +13 -13
- package/client/ui/Pagination/Pagination.stories.tsx +178 -98
- package/client/ui/Pagination/PaginationLegacy.stories.tsx +121 -0
- package/client/ui/Panel.stories.tsx +1 -1
- package/client/ui/Popover/Popover.stories.tsx +1 -1
- package/client/ui/Progress/Progress.stories.tsx +1 -1
- package/client/ui/RadioGroup/RadioGroup.stories.tsx +1 -1
- package/client/ui/Resizable/Resizable.stories.tsx +1 -1
- package/client/ui/ScrollArea/ScrollArea.stories.tsx +1 -1
- package/client/ui/SearchField/SearchField.stories.tsx +153 -0
- package/client/ui/{SearchField.stories.tsx → SearchField/SearchFieldLegacy.stories.tsx} +2 -2
- package/client/ui/SectionBadge.stories.tsx +1 -1
- package/client/ui/Select.stories.tsx +1 -1
- package/client/ui/Separator/Separator.stories.tsx +1 -1
- package/client/ui/Sheet/Sheet.stories.tsx +1 -1
- package/client/ui/Sidebar/Sidebar.stories.tsx +57 -8
- package/client/ui/Skeleton/Skeleton.stories.tsx +1 -1
- package/client/ui/Slider/Slider.stories.tsx +1 -1
- package/client/ui/StandardNavigation.stories.tsx +1 -1
- package/client/ui/Stepper/Stepper.stories.tsx +344 -0
- package/client/ui/Switch.stories.tsx +1 -1
- package/client/ui/SwitchV01/SwitchV01.stories.tsx +152 -0
- package/client/ui/SystemBar/system-bar.stories.tsx +179 -0
- package/client/ui/Table/TableV01.stories.tsx +256 -0
- package/client/ui/Tabs.stories.tsx +1 -1
- package/client/ui/TabsV01/TabsV01.stories.tsx +144 -0
- package/client/ui/Tag.stories.tsx +1 -1
- package/client/ui/TagV02/TagStatusV02.stories.tsx +132 -0
- package/client/ui/TagV02/TagV02.stories.tsx +142 -0
- package/client/ui/TextAreaV01/TextAreaV01.stories.tsx +146 -0
- package/client/ui/TextFieldV01/PasswordFieldV01.stories.tsx +161 -0
- package/client/ui/TextFieldV01/TextFieldV01.stories.tsx +160 -0
- package/client/ui/Textarea.stories.tsx +1 -1
- package/client/ui/Timeline/timeline.stories.tsx +404 -0
- package/client/ui/Toast/Toast.stories.tsx +1 -1
- package/client/ui/ToastV01/ToastV01.stories.tsx +201 -0
- package/client/ui/Toaster/Toaster.stories.tsx +1 -1
- package/client/ui/Toggle.stories.tsx +1 -1
- package/client/ui/Tooltip.stories.tsx +287 -114
- package/client/ui/Typography.stories.tsx +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +649 -13
- package/dist/index.es.js +6109 -2360
- package/package.json +1 -1
- package/client/components/ui/badge.tsx +0 -33
- package/client/components/ui/sonner.tsx +0 -26
- package/client/components/ui/toggle-group.tsx +0 -76
- package/client/ui/Alert/Alert.stories.tsx +0 -82
- package/client/ui/AlertDialog/AlertDialog.stories.tsx +0 -106
- package/client/ui/Avatar/Avatar.stories.tsx +0 -94
- package/client/ui/Badge/Badge.stories.tsx +0 -60
- package/client/ui/Breadcrumb/Breadcrumb.stories.tsx +0 -97
- package/client/ui/DropdownMenu/DropdownMenu.stories.tsx +0 -139
- package/client/ui/Sonner/Sonner.stories.tsx +0 -48
- package/client/ui/Table/Table.stories.tsx +0 -135
- 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
|
+
};
|
|
@@ -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
|
+
};
|