@ceed/cds 1.28.1 → 1.29.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/dist/Overview.md +5 -5
- package/dist/components/DatePicker/DatePicker.d.ts +10 -0
- package/dist/components/DateRangePicker/DateRangePicker.d.ts +10 -0
- package/dist/components/data-display/Avatar.md +110 -69
- package/dist/components/data-display/Badge.md +91 -39
- package/dist/components/data-display/Chip.md +49 -20
- package/dist/components/data-display/DataTable.md +93 -0
- package/dist/components/data-display/InfoSign.md +12 -0
- package/dist/components/data-display/Table.md +72 -55
- package/dist/components/data-display/Tooltip.md +40 -40
- package/dist/components/data-display/Typography.md +53 -70
- package/dist/components/feedback/Alert.md +88 -72
- package/dist/components/feedback/CircularProgress.md +17 -0
- package/dist/components/feedback/Skeleton.md +17 -0
- package/dist/components/inputs/Button.md +94 -68
- package/dist/components/inputs/ButtonGroup.md +17 -0
- package/dist/components/inputs/Calendar.md +118 -457
- package/dist/components/inputs/Checkbox.md +185 -430
- package/dist/components/inputs/CurrencyInput.md +22 -0
- package/dist/components/inputs/DatePicker.md +84 -0
- package/dist/components/inputs/DateRangePicker.md +88 -0
- package/dist/components/inputs/FilterableCheckboxGroup.md +20 -3
- package/dist/components/inputs/FormControl.md +32 -2
- package/dist/components/inputs/IconButton.md +18 -0
- package/dist/components/inputs/Input.md +198 -136
- package/dist/components/inputs/MonthPicker.md +25 -0
- package/dist/components/inputs/MonthRangePicker.md +23 -0
- package/dist/components/inputs/PercentageInput.md +25 -0
- package/dist/components/inputs/RadioButton.md +23 -0
- package/dist/components/inputs/RadioList.md +20 -1
- package/dist/components/inputs/RadioTileGroup.md +37 -3
- package/dist/components/inputs/Select.md +56 -0
- package/dist/components/inputs/Slider.md +23 -0
- package/dist/components/inputs/Switch.md +20 -0
- package/dist/components/inputs/Textarea.md +32 -8
- package/dist/components/inputs/Uploader/Uploader.md +21 -0
- package/dist/components/layout/Box.md +52 -41
- package/dist/components/layout/Grid.md +87 -81
- package/dist/components/layout/Stack.md +88 -68
- package/dist/components/navigation/Breadcrumbs.md +57 -46
- package/dist/components/navigation/Drawer.md +17 -0
- package/dist/components/navigation/Dropdown.md +13 -0
- package/dist/components/navigation/IconMenuButton.md +17 -0
- package/dist/components/navigation/InsetDrawer.md +130 -292
- package/dist/components/navigation/Link.md +78 -0
- package/dist/components/navigation/Menu.md +17 -0
- package/dist/components/navigation/MenuButton.md +18 -0
- package/dist/components/navigation/Pagination.md +13 -0
- package/dist/components/navigation/Stepper.md +15 -0
- package/dist/components/navigation/Tabs.md +27 -0
- package/dist/components/surfaces/Accordions.md +804 -49
- package/dist/components/surfaces/Card.md +173 -97
- package/dist/components/surfaces/Divider.md +246 -82
- package/dist/components/surfaces/Sheet.md +15 -0
- package/dist/index.browser.js +2 -2
- package/dist/index.browser.js.map +3 -3
- package/dist/index.cjs +173 -6
- package/dist/index.js +173 -6
- package/framer/index.js +1 -1
- package/package.json +1 -1
|
@@ -6,124 +6,8 @@ InsetDrawer is a slide-out panel that appears from any edge of the screen, provi
|
|
|
6
6
|
|
|
7
7
|
It is commonly used for mobile navigation menus, filter panels, configuration sidebars, and detail views. The component supports four anchor positions (left, right, top, bottom) and three size presets, making it adaptable to a wide range of layout requirements.
|
|
8
8
|
|
|
9
|
-
```
|
|
10
|
-
<
|
|
11
|
-
<Sheet sx={{
|
|
12
|
-
borderRadius: 'md',
|
|
13
|
-
p: 2,
|
|
14
|
-
display: 'flex',
|
|
15
|
-
flexDirection: 'column',
|
|
16
|
-
gap: 2,
|
|
17
|
-
height: '100%',
|
|
18
|
-
overflow: 'auto'
|
|
19
|
-
}}>
|
|
20
|
-
<DialogTitle>Filters</DialogTitle>
|
|
21
|
-
<ModalClose />
|
|
22
|
-
<Divider sx={{
|
|
23
|
-
mt: 'auto'
|
|
24
|
-
}} />
|
|
25
|
-
<DialogContent>
|
|
26
|
-
<FormControl>
|
|
27
|
-
<FormLabel sx={{
|
|
28
|
-
typography: 'title-md',
|
|
29
|
-
fontWeight: 'bold'
|
|
30
|
-
}}>Property type</FormLabel>
|
|
31
|
-
<RadioGroup>
|
|
32
|
-
<Box sx={{
|
|
33
|
-
display: 'grid',
|
|
34
|
-
gridTemplateColumns: 'repeat(auto-fill, minmax(140px, 1fr))',
|
|
35
|
-
gap: 1.5
|
|
36
|
-
}}>
|
|
37
|
-
{[{
|
|
38
|
-
name: 'House',
|
|
39
|
-
icon: <HomeRoundedIcon />
|
|
40
|
-
}, {
|
|
41
|
-
name: 'Apartment',
|
|
42
|
-
icon: <ApartmentRoundedIcon />
|
|
43
|
-
}, {
|
|
44
|
-
name: 'Guesthouse',
|
|
45
|
-
icon: <MeetingRoomRoundedIcon />
|
|
46
|
-
}, {
|
|
47
|
-
name: 'Hotel',
|
|
48
|
-
icon: <HotelRoundedIcon />
|
|
49
|
-
}].map(item => <Card key={item.name} sx={{
|
|
50
|
-
boxShadow: 'none',
|
|
51
|
-
'&:hover': {
|
|
52
|
-
bgcolor: 'background.level1'
|
|
53
|
-
}
|
|
54
|
-
}}>
|
|
55
|
-
<CardContent>
|
|
56
|
-
{item.icon}
|
|
57
|
-
<Typography level="title-md">{item.name}</Typography>
|
|
58
|
-
</CardContent>
|
|
59
|
-
<Radio disableIcon overlay variant="outlined" color="neutral" value={item.name} sx={{
|
|
60
|
-
mt: -2
|
|
61
|
-
}} slotProps={{
|
|
62
|
-
action: {
|
|
63
|
-
sx: {
|
|
64
|
-
'&:hover': {
|
|
65
|
-
bgcolor: 'transparent'
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}} />
|
|
70
|
-
</Card>)}
|
|
71
|
-
</Box>
|
|
72
|
-
</RadioGroup>
|
|
73
|
-
</FormControl>
|
|
74
|
-
|
|
75
|
-
<Typography level="title-md" fontWeight="bold" sx={{
|
|
76
|
-
mt: 2
|
|
77
|
-
}}>
|
|
78
|
-
Booking options
|
|
79
|
-
</Typography>
|
|
80
|
-
<FormControl orientation="horizontal">
|
|
81
|
-
<Box sx={{
|
|
82
|
-
flex: 1,
|
|
83
|
-
pr: 1
|
|
84
|
-
}}>
|
|
85
|
-
<FormLabel sx={{
|
|
86
|
-
typography: 'title-sm'
|
|
87
|
-
}}>Instant booking</FormLabel>
|
|
88
|
-
<FormHelperText sx={{
|
|
89
|
-
typography: 'body-sm'
|
|
90
|
-
}}>
|
|
91
|
-
Listings that you can book without waiting for host approval.
|
|
92
|
-
</FormHelperText>
|
|
93
|
-
</Box>
|
|
94
|
-
<Switch />
|
|
95
|
-
</FormControl>
|
|
96
|
-
|
|
97
|
-
<FormControl orientation="horizontal">
|
|
98
|
-
<Box sx={{
|
|
99
|
-
flex: 1,
|
|
100
|
-
mt: 1,
|
|
101
|
-
mr: 1
|
|
102
|
-
}}>
|
|
103
|
-
<FormLabel sx={{
|
|
104
|
-
typography: 'title-sm'
|
|
105
|
-
}}>Self check-in</FormLabel>
|
|
106
|
-
<FormHelperText sx={{
|
|
107
|
-
typography: 'body-sm'
|
|
108
|
-
}}>
|
|
109
|
-
Easy access to the property when you arrive.
|
|
110
|
-
</FormHelperText>
|
|
111
|
-
</Box>
|
|
112
|
-
<Switch />
|
|
113
|
-
</FormControl>
|
|
114
|
-
</DialogContent>
|
|
115
|
-
|
|
116
|
-
<Divider sx={{
|
|
117
|
-
mt: 'auto'
|
|
118
|
-
}} />
|
|
119
|
-
<Stack direction="row" justifyContent="space-between" useFlexGap spacing={1}>
|
|
120
|
-
<Button variant="outlined" color="neutral">
|
|
121
|
-
Clear
|
|
122
|
-
</Button>
|
|
123
|
-
<Button>Show 165 properties</Button>
|
|
124
|
-
</Stack>
|
|
125
|
-
</Sheet>
|
|
126
|
-
</InsetDrawer>
|
|
9
|
+
```
|
|
10
|
+
<Canvas of={InsetDrawer.Playground} />
|
|
127
11
|
```
|
|
128
12
|
|
|
129
13
|
| Field | Description | Default |
|
|
@@ -155,220 +39,145 @@ function FilterDrawer() {
|
|
|
155
39
|
}
|
|
156
40
|
```
|
|
157
41
|
|
|
158
|
-
##
|
|
42
|
+
## Anchor Positions
|
|
159
43
|
|
|
160
|
-
|
|
44
|
+
InsetDrawer supports four anchor positions. Use `left` for navigation, `right` for details or filters, `top` for search bars, and `bottom` for mobile action sheets.
|
|
161
45
|
|
|
162
|
-
```
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
gap: 1.5
|
|
189
|
-
}}>
|
|
190
|
-
{[{
|
|
191
|
-
name: 'House',
|
|
192
|
-
icon: <HomeRoundedIcon />
|
|
193
|
-
}, {
|
|
194
|
-
name: 'Apartment',
|
|
195
|
-
icon: <ApartmentRoundedIcon />
|
|
196
|
-
}, {
|
|
197
|
-
name: 'Guesthouse',
|
|
198
|
-
icon: <MeetingRoomRoundedIcon />
|
|
199
|
-
}, {
|
|
200
|
-
name: 'Hotel',
|
|
201
|
-
icon: <HotelRoundedIcon />
|
|
202
|
-
}].map(item => <Card key={item.name} sx={{
|
|
203
|
-
boxShadow: 'none',
|
|
204
|
-
'&:hover': {
|
|
205
|
-
bgcolor: 'background.level1'
|
|
206
|
-
}
|
|
207
|
-
}}>
|
|
208
|
-
<CardContent>
|
|
209
|
-
{item.icon}
|
|
210
|
-
<Typography level="title-md">{item.name}</Typography>
|
|
211
|
-
</CardContent>
|
|
212
|
-
<Radio disableIcon overlay variant="outlined" color="neutral" value={item.name} sx={{
|
|
213
|
-
mt: -2
|
|
214
|
-
}} slotProps={{
|
|
215
|
-
action: {
|
|
216
|
-
sx: {
|
|
217
|
-
'&:hover': {
|
|
218
|
-
bgcolor: 'transparent'
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}} />
|
|
223
|
-
</Card>)}
|
|
224
|
-
</Box>
|
|
225
|
-
</RadioGroup>
|
|
226
|
-
</FormControl>
|
|
227
|
-
|
|
228
|
-
<Typography level="title-md" fontWeight="bold" sx={{
|
|
229
|
-
mt: 2
|
|
230
|
-
}}>
|
|
231
|
-
Booking options
|
|
232
|
-
</Typography>
|
|
233
|
-
<FormControl orientation="horizontal">
|
|
234
|
-
<Box sx={{
|
|
235
|
-
flex: 1,
|
|
236
|
-
pr: 1
|
|
237
|
-
}}>
|
|
238
|
-
<FormLabel sx={{
|
|
239
|
-
typography: 'title-sm'
|
|
240
|
-
}}>Instant booking</FormLabel>
|
|
241
|
-
<FormHelperText sx={{
|
|
242
|
-
typography: 'body-sm'
|
|
243
|
-
}}>
|
|
244
|
-
Listings that you can book without waiting for host approval.
|
|
245
|
-
</FormHelperText>
|
|
246
|
-
</Box>
|
|
247
|
-
<Switch />
|
|
248
|
-
</FormControl>
|
|
249
|
-
|
|
250
|
-
<FormControl orientation="horizontal">
|
|
251
|
-
<Box sx={{
|
|
252
|
-
flex: 1,
|
|
253
|
-
mt: 1,
|
|
254
|
-
mr: 1
|
|
255
|
-
}}>
|
|
256
|
-
<FormLabel sx={{
|
|
257
|
-
typography: 'title-sm'
|
|
258
|
-
}}>Self check-in</FormLabel>
|
|
259
|
-
<FormHelperText sx={{
|
|
260
|
-
typography: 'body-sm'
|
|
261
|
-
}}>
|
|
262
|
-
Easy access to the property when you arrive.
|
|
263
|
-
</FormHelperText>
|
|
264
|
-
</Box>
|
|
265
|
-
<Switch />
|
|
266
|
-
</FormControl>
|
|
267
|
-
</DialogContent>
|
|
268
|
-
|
|
269
|
-
<Divider sx={{
|
|
270
|
-
mt: 'auto'
|
|
271
|
-
}} />
|
|
272
|
-
<Stack direction="row" justifyContent="space-between" useFlexGap spacing={1}>
|
|
273
|
-
<Button variant="outlined" color="neutral">
|
|
274
|
-
Clear
|
|
275
|
-
</Button>
|
|
276
|
-
<Button>Show 165 properties</Button>
|
|
277
|
-
</Stack>
|
|
278
|
-
</Sheet>
|
|
279
|
-
</InsetDrawer>
|
|
46
|
+
```
|
|
47
|
+
<Canvas of={InsetDrawer.Anchors} />
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Sizes
|
|
51
|
+
|
|
52
|
+
Three size presets are available: `sm`, `md`, and `lg`. The size controls width for left/right anchors and height for top/bottom anchors.
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
<Canvas of={InsetDrawer.Sizes} />
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Navigation Menu
|
|
59
|
+
|
|
60
|
+
A typical mobile navigation menu pattern using InsetDrawer anchored to the left with a compact size.
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
<Canvas of={InsetDrawer.NavigationMenu} />
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Filter Panel
|
|
67
|
+
|
|
68
|
+
A filter panel that slides in from the right, containing form controls for refining search results.
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
<Canvas of={InsetDrawer.FilterPanel} />
|
|
280
72
|
```
|
|
281
73
|
|
|
282
74
|
## Common Use Cases
|
|
283
75
|
|
|
284
|
-
###
|
|
76
|
+
### Settings Drawer
|
|
285
77
|
|
|
286
78
|
```tsx
|
|
287
|
-
function
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
79
|
+
function SettingsDrawer({ open, onClose }) {
|
|
80
|
+
const [settings, setSettings] = useState({
|
|
81
|
+
notifications: true,
|
|
82
|
+
darkMode: false,
|
|
83
|
+
language: 'en',
|
|
84
|
+
});
|
|
293
85
|
|
|
294
86
|
return (
|
|
295
|
-
<InsetDrawer open={open} onClose={onClose} anchor="
|
|
296
|
-
<Sheet sx={{
|
|
297
|
-
<
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
87
|
+
<InsetDrawer open={open} onClose={onClose} anchor="right" size="sm">
|
|
88
|
+
<Sheet sx={{ height: '100%', p: 2 }}>
|
|
89
|
+
<DialogTitle>Settings</DialogTitle>
|
|
90
|
+
<ModalClose />
|
|
91
|
+
<Divider sx={{ my: 2 }} />
|
|
92
|
+
<DialogContent>
|
|
93
|
+
<Stack gap={3}>
|
|
94
|
+
<FormControl orientation="horizontal">
|
|
95
|
+
<Box sx={{ flex: 1 }}>
|
|
96
|
+
<FormLabel>Notifications</FormLabel>
|
|
97
|
+
<FormHelperText>Receive push notifications</FormHelperText>
|
|
98
|
+
</Box>
|
|
99
|
+
<Switch
|
|
100
|
+
checked={settings.notifications}
|
|
101
|
+
onChange={(e) =>
|
|
102
|
+
setSettings({ ...settings, notifications: e.target.checked })
|
|
103
|
+
}
|
|
104
|
+
/>
|
|
105
|
+
</FormControl>
|
|
106
|
+
<FormControl orientation="horizontal">
|
|
107
|
+
<Box sx={{ flex: 1 }}>
|
|
108
|
+
<FormLabel>Dark Mode</FormLabel>
|
|
109
|
+
<FormHelperText>Use dark color theme</FormHelperText>
|
|
110
|
+
</Box>
|
|
111
|
+
<Switch
|
|
112
|
+
checked={settings.darkMode}
|
|
113
|
+
onChange={(e) =>
|
|
114
|
+
setSettings({ ...settings, darkMode: e.target.checked })
|
|
115
|
+
}
|
|
116
|
+
/>
|
|
117
|
+
</FormControl>
|
|
118
|
+
</Stack>
|
|
119
|
+
</DialogContent>
|
|
314
120
|
</Sheet>
|
|
315
121
|
</InsetDrawer>
|
|
316
122
|
);
|
|
317
123
|
}
|
|
318
124
|
```
|
|
319
125
|
|
|
320
|
-
###
|
|
126
|
+
### Detail View Drawer
|
|
321
127
|
|
|
322
128
|
```tsx
|
|
323
|
-
function
|
|
324
|
-
const [
|
|
129
|
+
function DetailDrawer({ open, onClose, itemId }) {
|
|
130
|
+
const [data, setData] = useState(null);
|
|
131
|
+
|
|
132
|
+
useEffect(() => {
|
|
133
|
+
if (open && itemId) {
|
|
134
|
+
fetchItemDetails(itemId).then(setData);
|
|
135
|
+
}
|
|
136
|
+
}, [open, itemId]);
|
|
325
137
|
|
|
326
138
|
return (
|
|
327
|
-
<InsetDrawer open={open} onClose={onClose} anchor="right" size="
|
|
139
|
+
<InsetDrawer open={open} onClose={onClose} anchor="right" size="lg">
|
|
328
140
|
<Sheet sx={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
|
|
329
141
|
<Box sx={{ p: 2, borderBottom: '1px solid', borderColor: 'divider' }}>
|
|
330
|
-
<DialogTitle>
|
|
142
|
+
<DialogTitle>Item Details</DialogTitle>
|
|
331
143
|
<ModalClose />
|
|
332
144
|
</Box>
|
|
333
145
|
<DialogContent sx={{ flex: 1, overflow: 'auto', p: 2 }}>
|
|
334
|
-
{
|
|
146
|
+
{data ? <ItemDetails data={data} /> : <Skeleton variant="text" />}
|
|
335
147
|
</DialogContent>
|
|
336
|
-
<Box sx={{ p: 2, borderTop: '1px solid', borderColor: 'divider' }}>
|
|
337
|
-
<Stack direction="row" gap={1} justifyContent="space-between">
|
|
338
|
-
<Button variant="outlined" color="neutral" onClick={() => setLocalFilters({})}>
|
|
339
|
-
Clear All
|
|
340
|
-
</Button>
|
|
341
|
-
<Button onClick={() => { onApply(localFilters); onClose(); }}>
|
|
342
|
-
Apply Filters
|
|
343
|
-
</Button>
|
|
344
|
-
</Stack>
|
|
345
|
-
</Box>
|
|
346
148
|
</Sheet>
|
|
347
149
|
</InsetDrawer>
|
|
348
150
|
);
|
|
349
151
|
}
|
|
350
152
|
```
|
|
351
153
|
|
|
352
|
-
### Bottom Sheet for Mobile
|
|
154
|
+
### Bottom Sheet for Mobile Actions
|
|
353
155
|
|
|
354
156
|
```tsx
|
|
355
157
|
function ActionSheet({ open, onClose, onAction }) {
|
|
158
|
+
const actions = [
|
|
159
|
+
{ id: 'edit', label: 'Edit', icon: <EditIcon /> },
|
|
160
|
+
{ id: 'share', label: 'Share', icon: <ShareIcon /> },
|
|
161
|
+
{ id: 'delete', label: 'Delete', icon: <DeleteIcon />, color: 'danger' },
|
|
162
|
+
];
|
|
163
|
+
|
|
356
164
|
return (
|
|
357
165
|
<InsetDrawer open={open} onClose={onClose} anchor="bottom">
|
|
358
166
|
<Sheet sx={{ borderRadius: 'lg lg 0 0', p: 2 }}>
|
|
359
167
|
<List>
|
|
360
|
-
|
|
361
|
-
<
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
168
|
+
{actions.map((action) => (
|
|
169
|
+
<ListItem key={action.id}>
|
|
170
|
+
<ListItemButton
|
|
171
|
+
color={action.color}
|
|
172
|
+
onClick={() => { onAction(action.id); onClose(); }}
|
|
173
|
+
>
|
|
174
|
+
<ListItemDecorator>{action.icon}</ListItemDecorator>
|
|
175
|
+
{action.label}
|
|
176
|
+
</ListItemButton>
|
|
177
|
+
</ListItem>
|
|
178
|
+
))}
|
|
370
179
|
</List>
|
|
371
|
-
<Button variant="soft" color="neutral" fullWidth onClick={onClose}>
|
|
180
|
+
<Button variant="soft" color="neutral" fullWidth sx={{ mt: 1 }} onClick={onClose}>
|
|
372
181
|
Cancel
|
|
373
182
|
</Button>
|
|
374
183
|
</Sheet>
|
|
@@ -377,6 +186,19 @@ function ActionSheet({ open, onClose, onAction }) {
|
|
|
377
186
|
}
|
|
378
187
|
```
|
|
379
188
|
|
|
189
|
+
## Props and Customization
|
|
190
|
+
|
|
191
|
+
### Key Props
|
|
192
|
+
|
|
193
|
+
| Prop | Type | Default | Description |
|
|
194
|
+
| ---------- | -------------------------------------------------------------- | ----------- | -------------- |
|
|
195
|
+
| `children` | `ReactNode` | - | Drawer content |
|
|
196
|
+
| `variant` | `'solid' \| 'soft' \| 'outlined' \| 'plain'` | `'plain'` | Visual style |
|
|
197
|
+
| `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'neutral'` | Color scheme |
|
|
198
|
+
| `sx` | `SxProps` | - | Custom styles |
|
|
199
|
+
|
|
200
|
+
> **Note**: InsetDrawer is a styled Sheet component designed for sidebar layouts. It accepts all Joy UI Sheet props.
|
|
201
|
+
|
|
380
202
|
## Best Practices
|
|
381
203
|
|
|
382
204
|
1. **Use appropriate anchor positions**: Match the drawer position to the content type for intuitive UX.
|
|
@@ -402,6 +224,22 @@ function ActionSheet({ open, onClose, onAction }) {
|
|
|
402
224
|
|
|
403
225
|
3. **Structure content consistently**: Use a header/body/footer layout with clear dividers so users can quickly scan the drawer's content.
|
|
404
226
|
|
|
227
|
+
```tsx
|
|
228
|
+
// ✅ Good: Clear header/body/footer structure
|
|
229
|
+
<Sheet sx={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
|
|
230
|
+
<Box sx={{ p: 2, borderBottom: '1px solid', borderColor: 'divider' }}>
|
|
231
|
+
<DialogTitle>Title</DialogTitle>
|
|
232
|
+
<ModalClose />
|
|
233
|
+
</Box>
|
|
234
|
+
<DialogContent sx={{ flex: 1, overflow: 'auto', p: 2 }}>
|
|
235
|
+
{/* Scrollable content */}
|
|
236
|
+
</DialogContent>
|
|
237
|
+
<Box sx={{ p: 2, borderTop: '1px solid', borderColor: 'divider' }}>
|
|
238
|
+
<Button>Save</Button>
|
|
239
|
+
</Box>
|
|
240
|
+
</Sheet>
|
|
241
|
+
```
|
|
242
|
+
|
|
405
243
|
4. **Do not nest drawers**: Opening a drawer inside another drawer creates a confusing experience.
|
|
406
244
|
|
|
407
245
|
```tsx
|
|
@@ -43,6 +43,64 @@ function MyComponent() {
|
|
|
43
43
|
}
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
### Variants
|
|
49
|
+
|
|
50
|
+
Links support four visual styles through the `variant` prop: `plain`, `outlined`, `soft`, and `solid`.
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
<Canvas of={Link.Variants} />
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Colors
|
|
57
|
+
|
|
58
|
+
Apply semantic colors to communicate different purposes -- `primary`, `neutral`, `success`, `warning`, and `danger`.
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
<Canvas of={Link.Colors} />
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Underline Styles
|
|
65
|
+
|
|
66
|
+
Control the underline behavior with three options: `none` (never shown), `hover` (shown on hover), and `always` (permanently visible).
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
<Canvas of={Link.Underline} />
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Typography Levels
|
|
73
|
+
|
|
74
|
+
Links can adopt any typography level from the design system, enabling consistent text hierarchies when links appear alongside headings or body text.
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
<Canvas of={Link.Levels} />
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Disabled State
|
|
81
|
+
|
|
82
|
+
Links can be disabled to prevent interaction while remaining visible in the layout.
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
<Canvas of={Link.Disabled} />
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### External Links
|
|
89
|
+
|
|
90
|
+
For links that navigate away from your application, include `target="_blank"` and `rel="noopener noreferrer"` for security.
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
<Canvas of={Link.ExternalLink} />
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Inline with Text
|
|
97
|
+
|
|
98
|
+
Links integrate seamlessly within paragraph text, inheriting the surrounding font styles.
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
<Canvas of={Link.InlineWithText} />
|
|
102
|
+
```
|
|
103
|
+
|
|
46
104
|
## Common Use Cases
|
|
47
105
|
|
|
48
106
|
### Inline Text Links
|
|
@@ -93,6 +151,26 @@ function AppNavigation() {
|
|
|
93
151
|
}
|
|
94
152
|
```
|
|
95
153
|
|
|
154
|
+
## Props and Customization
|
|
155
|
+
|
|
156
|
+
### Key Props
|
|
157
|
+
|
|
158
|
+
| Prop | Type | Default | Description |
|
|
159
|
+
| ---------------- | -------------------------------------------------------------- | ----------- | -------------------------------------- |
|
|
160
|
+
| `children` | `ReactNode` | - | Link content |
|
|
161
|
+
| `href` | `string` | - | Link URL |
|
|
162
|
+
| `level` | Typography level | `'body-md'` | Text size (inherits Typography levels) |
|
|
163
|
+
| `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'primary'` | Link color |
|
|
164
|
+
| `variant` | `'solid' \| 'soft' \| 'outlined' \| 'plain'` | - | Visual style |
|
|
165
|
+
| `underline` | `'none' \| 'hover' \| 'always'` | `'hover'` | Underline behavior |
|
|
166
|
+
| `disabled` | `boolean` | `false` | Disables the link |
|
|
167
|
+
| `startDecorator` | `ReactNode` | - | Content before link text |
|
|
168
|
+
| `endDecorator` | `ReactNode` | - | Content after link text |
|
|
169
|
+
| `component` | `ElementType` | `'a'` | Root element type (polymorphic) |
|
|
170
|
+
| `sx` | `SxProps` | - | Custom styles |
|
|
171
|
+
|
|
172
|
+
> **Note**: Link also accepts all Joy UI Link props.
|
|
173
|
+
|
|
96
174
|
## Best Practices
|
|
97
175
|
|
|
98
176
|
- **Use descriptive link text.** The text should clearly communicate the destination. Avoid generic labels such as "click here" or "read more".
|
|
@@ -719,6 +719,23 @@ Menu can contain non-MenuItem elements like Box, Typography, and progress indica
|
|
|
719
719
|
</Dropdown>
|
|
720
720
|
```
|
|
721
721
|
|
|
722
|
+
## Props and Customization
|
|
723
|
+
|
|
724
|
+
### Key Props
|
|
725
|
+
|
|
726
|
+
| Prop | Type | Default | Description |
|
|
727
|
+
| ----------- | -------------------------------------------------------------- | ---------------- | ---------------------------------------- |
|
|
728
|
+
| `children` | `ReactNode` | - | Menu items (MenuItem, ListDivider, etc.) |
|
|
729
|
+
| `open` | `boolean` | - | Controlled open state |
|
|
730
|
+
| `onClose` | `() => void` | - | Callback when the menu closes |
|
|
731
|
+
| `placement` | `Placement` | `'bottom-start'` | Menu position relative to trigger |
|
|
732
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Menu size |
|
|
733
|
+
| `variant` | `'solid' \| 'soft' \| 'outlined' \| 'plain'` | `'outlined'` | Visual style |
|
|
734
|
+
| `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'neutral'` | Color scheme |
|
|
735
|
+
| `sx` | `SxProps` | - | Custom styles |
|
|
736
|
+
|
|
737
|
+
> **Note**: Menu also accepts all Joy UI Menu props and Framer Motion props.
|
|
738
|
+
|
|
722
739
|
## Best Practices
|
|
723
740
|
|
|
724
741
|
- **Use ListDivider to group related items.** Logical grouping helps users scan the menu faster. Place destructive actions (like Delete) in their own group at the bottom.
|
|
@@ -233,6 +233,24 @@ function ToolbarActions({ selectedItems, onAction }) {
|
|
|
233
233
|
}
|
|
234
234
|
```
|
|
235
235
|
|
|
236
|
+
## Props and Customization
|
|
237
|
+
|
|
238
|
+
### Key Props
|
|
239
|
+
|
|
240
|
+
| Prop | Type | Default | Description |
|
|
241
|
+
| ----------------- | -------------------------------------------------------------- | ---------------- | ------------------------------------ |
|
|
242
|
+
| `buttonText` | `string` | (required) | Text displayed in the trigger button |
|
|
243
|
+
| `items` | `{ text: string; onClick?: () => void }[]` | (required) | Menu item list |
|
|
244
|
+
| `variant` | `'solid' \| 'soft' \| 'outlined' \| 'plain'` | `'outlined'` | Button visual style |
|
|
245
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
|
|
246
|
+
| `color` | `'primary' \| 'neutral' \| 'danger' \| 'success' \| 'warning'` | `'neutral'` | Button color |
|
|
247
|
+
| `disabled` | `boolean` | `false` | Disables the button |
|
|
248
|
+
| `startDecorator` | `ReactNode` | - | Content before button text |
|
|
249
|
+
| `endDecorator` | `ReactNode` | - | Content after button text |
|
|
250
|
+
| `showIcon` | `boolean` | `true` | Show dropdown arrow icon |
|
|
251
|
+
| `placement` | `Placement` | `'bottom-start'` | Menu position |
|
|
252
|
+
| `buttonComponent` | `ElementType` | - | Custom trigger element |
|
|
253
|
+
|
|
236
254
|
## Best Practices
|
|
237
255
|
|
|
238
256
|
- **Use descriptive button text.** The button label should clearly indicate what kind of options the menu contains. Avoid vague labels like "More" or "Options" -- prefer specific labels like "Export Options" or "User Actions".
|
|
@@ -214,6 +214,19 @@ function URLPaginatedList() {
|
|
|
214
214
|
}
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
+
## Props and Customization
|
|
218
|
+
|
|
219
|
+
### Key Props
|
|
220
|
+
|
|
221
|
+
| Prop | Type | Default | Description |
|
|
222
|
+
| ------------------------ | ------------------------------------ | --------------------------- | -------------------------- |
|
|
223
|
+
| `paginationModel` | `{ page: number; pageSize: number }` | (required) | Current page and page size |
|
|
224
|
+
| `defaultPaginationModel` | `{ page: number; pageSize: number }` | `{ page: 1, pageSize: 25 }` | Initial pagination state |
|
|
225
|
+
| `rowCount` | `number` | (required) | Total number of rows |
|
|
226
|
+
| `onPageChange` | `(newPage: number) => void` | (required) | Callback when page changes |
|
|
227
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Pagination control size |
|
|
228
|
+
| `variant` | `'standard' \| 'compact'` | `'standard'` | Pagination display mode |
|
|
229
|
+
|
|
217
230
|
## Best Practices
|
|
218
231
|
|
|
219
232
|
- **Always show context.** Display the total item count and current range (for example "Showing 1--25 of 250") alongside the pagination controls so users understand the scope of the data.
|
|
@@ -204,6 +204,21 @@ function CompactProgress({ currentStep, totalSteps }) {
|
|
|
204
204
|
}
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
+
## Props and Customization
|
|
208
|
+
|
|
209
|
+
### Key Props
|
|
210
|
+
|
|
211
|
+
| Prop | Type | Default | Description |
|
|
212
|
+
| ------------------- | --------------------------------------------------------------------------------- | --------------- | -------------------------------------------- |
|
|
213
|
+
| `steps` | `{ indicatorContent?: ReactNode; label?: ReactNode; extraContent?: ReactNode }[]` | (required) | Step definitions |
|
|
214
|
+
| `activeStep` | `number` | (required) | Currently active step index (0-based) |
|
|
215
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Stepper layout direction |
|
|
216
|
+
| `stepOrientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Individual step content orientation |
|
|
217
|
+
| `activeColor` | `string` | `'primary.500'` | Color for active/completed step indicators |
|
|
218
|
+
| `inactiveColor` | `string` | `'neutral.400'` | Color for inactive step indicators |
|
|
219
|
+
| `activeLineColor` | `string` | `'primary.500'` | Color for connector lines of completed steps |
|
|
220
|
+
| `inactiveLineColor` | `string` | `'neutral.300'` | Color for connector lines of future steps |
|
|
221
|
+
|
|
207
222
|
## Best Practices
|
|
208
223
|
|
|
209
224
|
1. **Keep step count manageable**: Limit the number of steps to 3-7 for optimal user comprehension. If more steps are needed, consider grouping them.
|