@cdx-ui/components 0.3.13 → 0.3.14
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/coverage.svg +1 -1
- package/docs/components/alert-dialog/content.md +359 -0
- package/docs/components/bar-chart/content.md +108 -2
- package/docs/components/dialog/content.md +468 -13
- package/docs/components/line-chart/content.md +1 -0
- package/docs/foundations/expressions/icons/content.md +1 -1
- package/docs/llms.txt +1 -0
- package/docs/resources/release-notes/0.3.13/content.md +21 -0
- package/docs/resources/release-notes/content.md +1 -0
- package/lib/commonjs/components/BarChart/geometry.js +95 -10
- package/lib/commonjs/components/BarChart/geometry.js.map +1 -1
- package/lib/commonjs/components/BarChart/index.js +8 -6
- package/lib/commonjs/components/BarChart/index.js.map +1 -1
- package/lib/module/components/BarChart/geometry.js +93 -9
- package/lib/module/components/BarChart/geometry.js.map +1 -1
- package/lib/module/components/BarChart/index.js +9 -7
- package/lib/module/components/BarChart/index.js.map +1 -1
- package/lib/typescript/components/BarChart/geometry.d.ts +19 -2
- package/lib/typescript/components/BarChart/geometry.d.ts.map +1 -1
- package/lib/typescript/components/BarChart/index.d.ts +4 -2
- package/lib/typescript/components/BarChart/index.d.ts.map +1 -1
- package/lib/typescript/components/chart/types.d.ts +7 -0
- package/lib/typescript/components/chart/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/components/BarChart/geometry.ts +126 -10
- package/src/components/BarChart/index.tsx +24 -16
- package/src/components/chart/types.ts +7 -0
|
@@ -61,6 +61,141 @@ export default function DialogBasicDemo() {
|
|
|
61
61
|
}
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
## Sizes
|
|
65
|
+
|
|
66
|
+
Set `size` on `Dialog` to cap the popup width: `xs`, `sm`, `md` (default), `lg`, `xl`, or `full`. Every size except `full` takes 90% of the viewport on narrow screens. Match the size to the content: short confirmations fit `xs` or `sm`, while statements and comparisons need `lg` or wider.
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { useState } from 'react';
|
|
70
|
+
import { Button, Dialog, HStack, Table, Text, type DialogRootProps } from '@cdx-ui/components';
|
|
71
|
+
|
|
72
|
+
type DialogSize = NonNullable<DialogRootProps['size']>;
|
|
73
|
+
|
|
74
|
+
interface SizeScenario {
|
|
75
|
+
size: DialogSize;
|
|
76
|
+
title: string;
|
|
77
|
+
description: string;
|
|
78
|
+
rows: { label: string; value: string }[];
|
|
79
|
+
action: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const scenarios: SizeScenario[] = [
|
|
83
|
+
{
|
|
84
|
+
size: 'xs',
|
|
85
|
+
title: 'Card locked',
|
|
86
|
+
description: 'Debit card ending in 4821',
|
|
87
|
+
rows: [{ label: 'Status', value: 'Locked' }],
|
|
88
|
+
action: 'Done',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
size: 'sm',
|
|
92
|
+
title: 'Turn on Face ID?',
|
|
93
|
+
description: 'Sign in faster without typing your password.',
|
|
94
|
+
rows: [{ label: 'Device', value: 'iPhone 16 Pro' }],
|
|
95
|
+
action: 'Turn on',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
size: 'md',
|
|
99
|
+
title: 'Confirm transfer',
|
|
100
|
+
description: 'From Everyday Checking to High-Yield Savings',
|
|
101
|
+
rows: [
|
|
102
|
+
{ label: 'Amount', value: '$500.00' },
|
|
103
|
+
{ label: 'Delivery', value: 'Today' },
|
|
104
|
+
],
|
|
105
|
+
action: 'Transfer $500',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
size: 'lg',
|
|
109
|
+
title: 'October statement',
|
|
110
|
+
description: 'Everyday Checking •••• 6643',
|
|
111
|
+
rows: [
|
|
112
|
+
{ label: 'Opening balance', value: '$3,104.22' },
|
|
113
|
+
{ label: 'Deposits', value: '+$4,860.00' },
|
|
114
|
+
{ label: 'Withdrawals', value: '−$5,546.15' },
|
|
115
|
+
{ label: 'Closing balance', value: '$2,418.07' },
|
|
116
|
+
],
|
|
117
|
+
action: 'Download PDF',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
size: 'xl',
|
|
121
|
+
title: 'Compare savings accounts',
|
|
122
|
+
description: 'Rates are variable and may change after the account is opened.',
|
|
123
|
+
rows: [
|
|
124
|
+
{ label: 'High-Yield Savings', value: '4.10% APY' },
|
|
125
|
+
{ label: 'Money Market', value: '3.75% APY' },
|
|
126
|
+
{ label: '12-month CD', value: '4.50% APY' },
|
|
127
|
+
{ label: 'Kids Savings', value: '2.00% APY' },
|
|
128
|
+
],
|
|
129
|
+
action: 'Open an account',
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
size: 'full',
|
|
133
|
+
title: 'Monthly spending',
|
|
134
|
+
description: 'October 1 – October 31',
|
|
135
|
+
rows: [
|
|
136
|
+
{ label: 'Housing', value: '$1,850.00' },
|
|
137
|
+
{ label: 'Groceries', value: '$642.18' },
|
|
138
|
+
{ label: 'Dining', value: '$311.40' },
|
|
139
|
+
{ label: 'Transportation', value: '$228.75' },
|
|
140
|
+
{ label: 'Subscriptions', value: '$64.97' },
|
|
141
|
+
],
|
|
142
|
+
action: 'View insights',
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
function SizeDialog({ scenario }: { scenario: SizeScenario }) {
|
|
147
|
+
const [open, setOpen] = useState(false);
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<Dialog isOpen={open} onOpenChange={setOpen} size={scenario.size}>
|
|
151
|
+
<Dialog.Trigger asChild>
|
|
152
|
+
<Button variant="outline">
|
|
153
|
+
<Button.Label>{scenario.size}</Button.Label>
|
|
154
|
+
</Button>
|
|
155
|
+
</Dialog.Trigger>
|
|
156
|
+
<Dialog.Popup>
|
|
157
|
+
<Dialog.Header>
|
|
158
|
+
<Dialog.Title>{scenario.title}</Dialog.Title>
|
|
159
|
+
<Dialog.Description>{scenario.description}</Dialog.Description>
|
|
160
|
+
<Dialog.Close />
|
|
161
|
+
</Dialog.Header>
|
|
162
|
+
<Dialog.Content>
|
|
163
|
+
<Table fullBleed accessibilityLabel={`${scenario.title} details`}>
|
|
164
|
+
<Table.Body>
|
|
165
|
+
{scenario.rows.map((row) => (
|
|
166
|
+
<Table.Row key={row.label}>
|
|
167
|
+
<Table.Cell>
|
|
168
|
+
<Text color="secondary">{row.label}</Text>
|
|
169
|
+
</Table.Cell>
|
|
170
|
+
<Table.Cell align="end">
|
|
171
|
+
<Text weight="semibold">{row.value}</Text>
|
|
172
|
+
</Table.Cell>
|
|
173
|
+
</Table.Row>
|
|
174
|
+
))}
|
|
175
|
+
</Table.Body>
|
|
176
|
+
</Table>
|
|
177
|
+
</Dialog.Content>
|
|
178
|
+
<Dialog.Footer>
|
|
179
|
+
<Button onPress={() => setOpen(false)}>
|
|
180
|
+
<Button.Label>{scenario.action}</Button.Label>
|
|
181
|
+
</Button>
|
|
182
|
+
</Dialog.Footer>
|
|
183
|
+
</Dialog.Popup>
|
|
184
|
+
</Dialog>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export default function DialogSizesDemo() {
|
|
189
|
+
return (
|
|
190
|
+
<HStack space="sm" className="flex-wrap justify-center">
|
|
191
|
+
{scenarios.map((scenario) => (
|
|
192
|
+
<SizeDialog key={scenario.size} scenario={scenario} />
|
|
193
|
+
))}
|
|
194
|
+
</HStack>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
64
199
|
## Title severities
|
|
65
200
|
|
|
66
201
|
Set `severity` on `Dialog.Title` to add a status icon and semantic color treatment.
|
|
@@ -158,13 +293,335 @@ export default function DialogTitleSeveritiesDemo() {
|
|
|
158
293
|
}
|
|
159
294
|
```
|
|
160
295
|
|
|
296
|
+
## Custom triggers
|
|
297
|
+
|
|
298
|
+
`Dialog.Trigger` with `asChild` turns any pressable element into a trigger, such as an `IconButton` or a `ListItem`, and one dialog can have several. To open the dialog from somewhere a trigger can't wrap, such as a `Menu.Item`, control it with `isOpen` and `onOpenChange`.
|
|
299
|
+
|
|
300
|
+
```tsx
|
|
301
|
+
import { useState } from 'react';
|
|
302
|
+
import {
|
|
303
|
+
Avatar,
|
|
304
|
+
Box,
|
|
305
|
+
Button,
|
|
306
|
+
Card,
|
|
307
|
+
Dialog,
|
|
308
|
+
Heading,
|
|
309
|
+
Icon,
|
|
310
|
+
IconButton,
|
|
311
|
+
ListItem,
|
|
312
|
+
Menu,
|
|
313
|
+
Table,
|
|
314
|
+
Text,
|
|
315
|
+
} from '@cdx-ui/components';
|
|
316
|
+
import { ChevronRight, CreditCard, Info, MoreHoriz } from '@cdx-ui/icons';
|
|
317
|
+
|
|
318
|
+
const rewards = [
|
|
319
|
+
{ label: 'Dining · 3x points', value: '6,210 pts' },
|
|
320
|
+
{ label: 'Travel · 2x points', value: '4,180 pts' },
|
|
321
|
+
{ label: 'Everything else · 1x', value: '2,090 pts' },
|
|
322
|
+
];
|
|
323
|
+
|
|
324
|
+
export default function DialogCustomTriggersDemo() {
|
|
325
|
+
const [open, setOpen] = useState(false);
|
|
326
|
+
|
|
327
|
+
return (
|
|
328
|
+
<Dialog isOpen={open} onOpenChange={setOpen}>
|
|
329
|
+
<Card fullBleed className="w-full max-w-sm">
|
|
330
|
+
<Card.Header>
|
|
331
|
+
<Box className="flex-row items-center gap-2">
|
|
332
|
+
<Heading size="sm">Visa Signature</Heading>
|
|
333
|
+
<Dialog.Trigger asChild>
|
|
334
|
+
<IconButton
|
|
335
|
+
as={Info}
|
|
336
|
+
variant="ghost"
|
|
337
|
+
size="small"
|
|
338
|
+
accessibilityLabel="How rewards are earned"
|
|
339
|
+
/>
|
|
340
|
+
</Dialog.Trigger>
|
|
341
|
+
</Box>
|
|
342
|
+
<Menu placement="bottom-end">
|
|
343
|
+
<Menu.Trigger asChild>
|
|
344
|
+
<IconButton
|
|
345
|
+
as={MoreHoriz}
|
|
346
|
+
variant="ghost"
|
|
347
|
+
size="small"
|
|
348
|
+
accessibilityLabel="Visa Signature actions"
|
|
349
|
+
/>
|
|
350
|
+
</Menu.Trigger>
|
|
351
|
+
<Menu.Popup>
|
|
352
|
+
<Menu.Content accessibilityLabel="Visa Signature actions">
|
|
353
|
+
<Menu.Item onPress={() => setOpen(true)}>
|
|
354
|
+
<Menu.ItemLabel>Rewards summary</Menu.ItemLabel>
|
|
355
|
+
</Menu.Item>
|
|
356
|
+
<Menu.Item onPress={() => undefined}>
|
|
357
|
+
<Menu.ItemLabel>Lock card</Menu.ItemLabel>
|
|
358
|
+
</Menu.Item>
|
|
359
|
+
</Menu.Content>
|
|
360
|
+
</Menu.Popup>
|
|
361
|
+
</Menu>
|
|
362
|
+
</Card.Header>
|
|
363
|
+
<Card.Content>
|
|
364
|
+
<Dialog.Trigger asChild>
|
|
365
|
+
<ListItem showSeparator={false} accessibilityHint="Opens rewards summary">
|
|
366
|
+
<ListItem.LeadingSlot>
|
|
367
|
+
<Avatar color="brand">
|
|
368
|
+
<Avatar.Icon as={CreditCard} />
|
|
369
|
+
</Avatar>
|
|
370
|
+
</ListItem.LeadingSlot>
|
|
371
|
+
<ListItem.Content>
|
|
372
|
+
<ListItem.Description>Rewards balance</ListItem.Description>
|
|
373
|
+
<ListItem.Title>12,480 points</ListItem.Title>
|
|
374
|
+
</ListItem.Content>
|
|
375
|
+
<ListItem.TrailingSlot>
|
|
376
|
+
<Icon as={ChevronRight} />
|
|
377
|
+
</ListItem.TrailingSlot>
|
|
378
|
+
</ListItem>
|
|
379
|
+
</Dialog.Trigger>
|
|
380
|
+
</Card.Content>
|
|
381
|
+
</Card>
|
|
382
|
+
|
|
383
|
+
<Dialog.Popup>
|
|
384
|
+
<Dialog.Header>
|
|
385
|
+
<Dialog.Title>Rewards summary</Dialog.Title>
|
|
386
|
+
<Dialog.Description>Worth $124.80 as a statement credit.</Dialog.Description>
|
|
387
|
+
<Dialog.Close />
|
|
388
|
+
</Dialog.Header>
|
|
389
|
+
<Dialog.Content>
|
|
390
|
+
<Table fullBleed accessibilityLabel="Points by category">
|
|
391
|
+
<Table.Body>
|
|
392
|
+
{rewards.map((reward) => (
|
|
393
|
+
<Table.Row key={reward.label}>
|
|
394
|
+
<Table.Cell>
|
|
395
|
+
<Text color="secondary">{reward.label}</Text>
|
|
396
|
+
</Table.Cell>
|
|
397
|
+
<Table.Cell align="end">
|
|
398
|
+
<Text weight="semibold">{reward.value}</Text>
|
|
399
|
+
</Table.Cell>
|
|
400
|
+
</Table.Row>
|
|
401
|
+
))}
|
|
402
|
+
</Table.Body>
|
|
403
|
+
</Table>
|
|
404
|
+
</Dialog.Content>
|
|
405
|
+
<Dialog.Footer>
|
|
406
|
+
<Button variant="outline" onPress={() => setOpen(false)}>
|
|
407
|
+
<Button.Label>Close</Button.Label>
|
|
408
|
+
</Button>
|
|
409
|
+
<Button onPress={() => setOpen(false)}>
|
|
410
|
+
<Button.Label>Redeem points</Button.Label>
|
|
411
|
+
</Button>
|
|
412
|
+
</Dialog.Footer>
|
|
413
|
+
</Dialog.Popup>
|
|
414
|
+
</Dialog>
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## Stacked actions
|
|
420
|
+
|
|
421
|
+
When a dialog offers more than two choices, or the labels are too long to sit side by side, stack the actions in a `Button.Group` with `flexDirection="column"` inside `Dialog.Footer`, and pass `fullWidth` to each `Button`. Give the group `className="flex-1"` so it spans the footer. Order them from most to least recommended.
|
|
422
|
+
|
|
423
|
+
```tsx
|
|
424
|
+
import { useState } from 'react';
|
|
425
|
+
import { Button, Dialog, Table, Text } from '@cdx-ui/components';
|
|
426
|
+
import { Event, Savings } from '@cdx-ui/icons';
|
|
427
|
+
|
|
428
|
+
export default function DialogStackedActionsDemo() {
|
|
429
|
+
const [open, setOpen] = useState(false);
|
|
430
|
+
|
|
431
|
+
return (
|
|
432
|
+
<Dialog isOpen={open} onOpenChange={setOpen} size="sm">
|
|
433
|
+
<Dialog.Trigger asChild>
|
|
434
|
+
<Button variant="outline" color="warning">
|
|
435
|
+
<Button.Label>Review upcoming payment</Button.Label>
|
|
436
|
+
</Button>
|
|
437
|
+
</Dialog.Trigger>
|
|
438
|
+
<Dialog.Popup>
|
|
439
|
+
<Dialog.Header>
|
|
440
|
+
<Dialog.Title severity="warning">Payment may overdraw checking</Dialog.Title>
|
|
441
|
+
<Dialog.Description>Mortgage payment scheduled for tomorrow</Dialog.Description>
|
|
442
|
+
<Dialog.Close />
|
|
443
|
+
</Dialog.Header>
|
|
444
|
+
<Dialog.Content>
|
|
445
|
+
<Table fullBleed accessibilityLabel="Payment details">
|
|
446
|
+
<Table.Body>
|
|
447
|
+
<Table.Row>
|
|
448
|
+
<Table.Cell>
|
|
449
|
+
<Text color="secondary">Payment amount</Text>
|
|
450
|
+
</Table.Cell>
|
|
451
|
+
<Table.Cell align="end">
|
|
452
|
+
<Text weight="semibold">$1,250.00</Text>
|
|
453
|
+
</Table.Cell>
|
|
454
|
+
</Table.Row>
|
|
455
|
+
<Table.Row>
|
|
456
|
+
<Table.Cell>
|
|
457
|
+
<Text color="secondary">Available balance</Text>
|
|
458
|
+
</Table.Cell>
|
|
459
|
+
<Table.Cell align="end">
|
|
460
|
+
<Text weight="semibold" color="danger">
|
|
461
|
+
$1,084.62
|
|
462
|
+
</Text>
|
|
463
|
+
</Table.Cell>
|
|
464
|
+
</Table.Row>
|
|
465
|
+
</Table.Body>
|
|
466
|
+
</Table>
|
|
467
|
+
</Dialog.Content>
|
|
468
|
+
<Dialog.Footer>
|
|
469
|
+
<Button.Group flexDirection="column" className="flex-1">
|
|
470
|
+
<Button fullWidth onPress={() => setOpen(false)}>
|
|
471
|
+
<Button.Icon as={Savings} position="leading" />
|
|
472
|
+
<Button.Label>Transfer $200 from savings</Button.Label>
|
|
473
|
+
</Button>
|
|
474
|
+
<Button fullWidth variant="outline" onPress={() => setOpen(false)}>
|
|
475
|
+
<Button.Icon as={Event} position="leading" />
|
|
476
|
+
<Button.Label>Reschedule payment</Button.Label>
|
|
477
|
+
</Button>
|
|
478
|
+
<Button fullWidth variant="ghost" onPress={() => setOpen(false)}>
|
|
479
|
+
<Button.Label>Pay anyway</Button.Label>
|
|
480
|
+
</Button>
|
|
481
|
+
</Button.Group>
|
|
482
|
+
</Dialog.Footer>
|
|
483
|
+
</Dialog.Popup>
|
|
484
|
+
</Dialog>
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Form
|
|
490
|
+
|
|
491
|
+
Wrap fields in `Form` inside `Dialog.Content` for short, focused tasks. Keep the dialog open until validation passes, and show errors with `Field.Error`. Use a `FullScreenDialog` instead when the form needs more than a few fields.
|
|
492
|
+
|
|
493
|
+
```tsx
|
|
494
|
+
import { useState } from 'react';
|
|
495
|
+
import {
|
|
496
|
+
Button,
|
|
497
|
+
CurrencyInput,
|
|
498
|
+
Dialog,
|
|
499
|
+
Field,
|
|
500
|
+
Form,
|
|
501
|
+
Input,
|
|
502
|
+
Radio,
|
|
503
|
+
Select,
|
|
504
|
+
} from '@cdx-ui/components';
|
|
505
|
+
import { Repeat } from '@cdx-ui/icons';
|
|
506
|
+
|
|
507
|
+
const AVAILABLE_BALANCE = 2418.07;
|
|
508
|
+
|
|
509
|
+
const accounts = [
|
|
510
|
+
{ value: 'savings', label: 'High-Yield Savings •••• 2290' },
|
|
511
|
+
{ value: 'vacation', label: 'Vacation Fund •••• 7713' },
|
|
512
|
+
{ value: 'emergency', label: 'Emergency Fund •••• 0458' },
|
|
513
|
+
];
|
|
514
|
+
|
|
515
|
+
export default function DialogFormDemo() {
|
|
516
|
+
const [open, setOpen] = useState(false);
|
|
517
|
+
const [destination, setDestination] = useState<string | undefined>();
|
|
518
|
+
const [amount, setAmount] = useState(0);
|
|
519
|
+
const [frequency, setFrequency] = useState('monthly');
|
|
520
|
+
const [submitted, setSubmitted] = useState(false);
|
|
521
|
+
|
|
522
|
+
const destinationInvalid = submitted && !destination;
|
|
523
|
+
const amountInvalid = submitted && (amount <= 0 || amount > AVAILABLE_BALANCE);
|
|
524
|
+
|
|
525
|
+
const handleOpenChange = (next: boolean) => {
|
|
526
|
+
setOpen(next);
|
|
527
|
+
if (!next) {
|
|
528
|
+
setSubmitted(false);
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
const handleSubmit = () => {
|
|
533
|
+
setSubmitted(true);
|
|
534
|
+
if (destination && amount > 0 && amount <= AVAILABLE_BALANCE) {
|
|
535
|
+
handleOpenChange(false);
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
return (
|
|
540
|
+
<Dialog isOpen={open} onOpenChange={handleOpenChange}>
|
|
541
|
+
<Dialog.Trigger asChild>
|
|
542
|
+
<Button>
|
|
543
|
+
<Button.Icon as={Repeat} position="leading" />
|
|
544
|
+
<Button.Label>Set up recurring transfer</Button.Label>
|
|
545
|
+
</Button>
|
|
546
|
+
</Dialog.Trigger>
|
|
547
|
+
<Dialog.Popup>
|
|
548
|
+
<Dialog.Header>
|
|
549
|
+
<Dialog.Title>Recurring transfer</Dialog.Title>
|
|
550
|
+
<Dialog.Description>From Everyday Checking · $2,418.07 available</Dialog.Description>
|
|
551
|
+
<Dialog.Close />
|
|
552
|
+
</Dialog.Header>
|
|
553
|
+
<Dialog.Content>
|
|
554
|
+
<Form>
|
|
555
|
+
<Field isRequired isInvalid={destinationInvalid}>
|
|
556
|
+
<Field.Label>To account</Field.Label>
|
|
557
|
+
<Select items={accounts} value={destination} onValueChange={setDestination}>
|
|
558
|
+
<Select.Trigger>
|
|
559
|
+
<Select.Value placeholder="Select an account" />
|
|
560
|
+
</Select.Trigger>
|
|
561
|
+
<Select.Content>
|
|
562
|
+
{accounts.map((account) => (
|
|
563
|
+
<Select.Item key={account.value} value={account.value}>
|
|
564
|
+
<Select.ItemLabel>{account.label}</Select.ItemLabel>
|
|
565
|
+
</Select.Item>
|
|
566
|
+
))}
|
|
567
|
+
</Select.Content>
|
|
568
|
+
</Select>
|
|
569
|
+
<Field.Error>Choose where the money goes.</Field.Error>
|
|
570
|
+
</Field>
|
|
571
|
+
<Field isRequired isInvalid={amountInvalid}>
|
|
572
|
+
<Field.Label>Amount</Field.Label>
|
|
573
|
+
<CurrencyInput
|
|
574
|
+
variant="outline"
|
|
575
|
+
value={amount}
|
|
576
|
+
onChangeValue={setAmount}
|
|
577
|
+
isInvalid={amountInvalid}
|
|
578
|
+
/>
|
|
579
|
+
<Field.Helper>Each transfer runs on the 1st of the period.</Field.Helper>
|
|
580
|
+
<Field.Error>Enter an amount up to $2,418.07.</Field.Error>
|
|
581
|
+
</Field>
|
|
582
|
+
<Field>
|
|
583
|
+
<Field.Label>Frequency</Field.Label>
|
|
584
|
+
<Radio.Group value={frequency} onChange={setFrequency} direction="row">
|
|
585
|
+
<Radio value="weekly">
|
|
586
|
+
<Radio.Label>Weekly</Radio.Label>
|
|
587
|
+
</Radio>
|
|
588
|
+
<Radio value="monthly">
|
|
589
|
+
<Radio.Label>Monthly</Radio.Label>
|
|
590
|
+
</Radio>
|
|
591
|
+
<Radio value="quarterly">
|
|
592
|
+
<Radio.Label>Quarterly</Radio.Label>
|
|
593
|
+
</Radio>
|
|
594
|
+
</Radio.Group>
|
|
595
|
+
</Field>
|
|
596
|
+
<Field>
|
|
597
|
+
<Field.Label>Memo (optional)</Field.Label>
|
|
598
|
+
<Input>
|
|
599
|
+
<Input.Field placeholder="e.g. Summer trip" />
|
|
600
|
+
</Input>
|
|
601
|
+
</Field>
|
|
602
|
+
</Form>
|
|
603
|
+
</Dialog.Content>
|
|
604
|
+
<Dialog.Footer>
|
|
605
|
+
<Button variant="outline" onPress={() => handleOpenChange(false)}>
|
|
606
|
+
<Button.Label>Cancel</Button.Label>
|
|
607
|
+
</Button>
|
|
608
|
+
<Button onPress={handleSubmit}>
|
|
609
|
+
<Button.Label>Schedule transfer</Button.Label>
|
|
610
|
+
</Button>
|
|
611
|
+
</Dialog.Footer>
|
|
612
|
+
</Dialog.Popup>
|
|
613
|
+
</Dialog>
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
161
618
|
## Scrollable content
|
|
162
619
|
|
|
163
|
-
`Dialog.Content` is not scrollable by default. Wrap long content in a `ScrollView` so the header and footer remain visible. On native, set `keyboardShouldPersistTaps="handled"` so a focused field keeps the keyboard open while the body scrolls.
|
|
620
|
+
`Dialog.Content` is not scrollable by default. Wrap long content in a `ScrollView` so the header and footer remain visible, and wrap that in a `ScrollShadow` with `surface="primary"` to fade the edges that still have content. On native, set `keyboardShouldPersistTaps="handled"` so a focused field keeps the keyboard open while the body scrolls.
|
|
164
621
|
|
|
165
622
|
```tsx
|
|
166
623
|
import { useState } from 'react';
|
|
167
|
-
import { Button, Dialog, ScrollView } from '@cdx-ui/components';
|
|
624
|
+
import { Button, Dialog, ScrollShadow, ScrollView } from '@cdx-ui/components';
|
|
168
625
|
|
|
169
626
|
const terms = [
|
|
170
627
|
'Authorization. You authorize us to debit the selected funding account and credit the destination account for the amount shown in the transfer review.',
|
|
@@ -198,17 +655,15 @@ export default function DialogScrollableContentDemo() {
|
|
|
198
655
|
<Dialog.Close />
|
|
199
656
|
</Dialog.Header>
|
|
200
657
|
<Dialog.Content>
|
|
201
|
-
<
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
))}
|
|
211
|
-
</ScrollView>
|
|
658
|
+
<ScrollShadow className="h-60" surface="primary">
|
|
659
|
+
<ScrollView contentContainerClassName="gap-3" keyboardShouldPersistTaps="handled">
|
|
660
|
+
{terms.map((term, index) => (
|
|
661
|
+
<Dialog.Text key={term}>
|
|
662
|
+
{index + 1}. {term}
|
|
663
|
+
</Dialog.Text>
|
|
664
|
+
))}
|
|
665
|
+
</ScrollView>
|
|
666
|
+
</ScrollShadow>
|
|
212
667
|
</Dialog.Content>
|
|
213
668
|
<Dialog.Footer>
|
|
214
669
|
<Button variant="outline" onPress={() => setOpen(false)}>
|
|
@@ -494,6 +494,7 @@ One entry in `series`: a line that reads one `dataset` column.
|
|
|
494
494
|
| `valueFormatter?` | `ChartValueFormatter` | — | Formats tick text on this axis (`location: 'tick'`). On a value axis it also formats series values when the series has no `valueFormatter`. On a line chart's x-axis it formats numeric categories, both the tick (`location: 'tick'`) and the tooltip title (`location: 'tooltip'`). |
|
|
495
495
|
| `position?` | `'top' \| 'bottom' \| 'left' \| 'right' \| 'none'` | — | Side the axis labels draw on. `'none'` hides them. Each chart accepts the sides it can draw and falls back to its default side for the others. |
|
|
496
496
|
| `tickLabelInterval?` | `"auto" \| ((value: unknown, index: number) => boolean)` | `'auto'` | Which category labels to draw. A function keeps the label at `index` when it returns `true`. `'auto'` currently draws every label; it does not thin them yet. |
|
|
497
|
+
| `tickLabelMaxLines?` | `number` | `2` | Most lines a category name may wrap onto before it ends in `…`. `1` truncates without wrapping. Read by `BarChart` on its category axis; a horizontal chart also stops at the lines its rows are tall enough to hold. Forge only; MUI X has no equivalent. |
|
|
497
498
|
|
|
498
499
|
### LineChartMarker
|
|
499
500
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Cross-platform icon library for Forge UI, built on [Material Symbols](https://fonts.google.com/icons) (outlined style, weight 400, optical size 24). Renders via `react-native-svg` and targets iOS, Android, and Web.
|
|
4
4
|
|
|
5
|
-
3,
|
|
5
|
+
3,999 icons are available, each with outlined and filled variants, plus support for custom
|
|
6
6
|
SVGs. Country flags are a separate set and do not appear in the browser below. Render one with
|
|
7
7
|
[`CountryFlag`](https://design.candescent.com/docs/components/country-flag/content.md).
|
|
8
8
|
|
package/docs/llms.txt
CHANGED
|
@@ -151,6 +151,7 @@ Links point at each page's `content.md`, which carries the page's prose, demo so
|
|
|
151
151
|
|
|
152
152
|
## Release notes
|
|
153
153
|
|
|
154
|
+
- [0.3.13](resources/release-notes/0.3.13/content.md): DataGrid adds tree data, detail panels, and column-targeted filters; ListItem and Menu receive visual and focus fixes.
|
|
154
155
|
- [0.3.12](resources/release-notes/0.3.12/content.md): DataGrid adds built-in column types, pinning, type-aware filters, and polarity or delta number cells.
|
|
155
156
|
- [0.3.11](resources/release-notes/0.3.11/content.md): Read-only Input and CurrencyInput stay non-editable on Android instead of accepting edits again.
|
|
156
157
|
- [0.3.10](resources/release-notes/0.3.10/content.md): CurrencyInput no longer clips the top of default-size amounts on iOS.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# 0.3.13 (https://design.candescent.com/docs/resources/release-notes/0.3.13)
|
|
2
|
+
|
|
3
|
+
DataGrid adds tree data, detail panels, and column-targeted filters; ListItem and Menu receive visual and focus fixes.
|
|
4
|
+
|
|
5
|
+
This release expands **DataGrid** with hierarchical rows, per-row detail panels, and ways to open filtering on a specific column, and it corrects **ListItem** section header styling and **Menu** focus when overlays open.
|
|
6
|
+
|
|
7
|
+
## What's new
|
|
8
|
+
|
|
9
|
+
**DataGrid** — Rows can expand for tree data and inline detail panels. Supply tree paths so child rows nest under parents, toggle row detail content without leaving the grid, and combine expansion with the existing selection and column APIs. Text cells in the grid body stay on one line with truncation and a tooltip for the full value ([#965](https://github.com/dfh-candescent/forge-design-system/pull/965)).
|
|
10
|
+
|
|
11
|
+
**DataGrid** — Header filter affordances and the column menu can open the filter panel already focused on one field, even when the grid has no filter toolbar. The panel anchors to its opener in a portal, focuses the target filter row, and returns focus to the opener on close. If that field has no filter item yet, the grid adds one with the default operator and drops value-less items on other fields without resetting pagination ([#992](https://github.com/dfh-candescent/forge-design-system/pull/992)).
|
|
12
|
+
|
|
13
|
+
## Bug fixes
|
|
14
|
+
|
|
15
|
+
**[ListItem](https://design.candescent.com/docs/components/list-item/content.md)** — `ListItem.SectionHeader` in the subtle variant uses the `surface-neutral-tint` fill so it matches design instead of the darker `surface-neutral-subtle` token ([#990](https://github.com/dfh-candescent/forge-design-system/pull/990)).
|
|
16
|
+
|
|
17
|
+
**[Menu](https://design.candescent.com/docs/components/menu/content.md)** — Opening a menu no longer pulls focus back when the user already moved focus elsewhere before the deferred open-focus runs, so focus does not end up stranded on `<body>` ([#978](https://github.com/dfh-candescent/forge-design-system/pull/978)).
|
|
18
|
+
|
|
19
|
+
**DataGrid** — Search field focus restores only when the row that had focus is removed, not on every row update after you click away ([#965](https://github.com/dfh-candescent/forge-design-system/pull/965)).
|
|
20
|
+
|
|
21
|
+
**DataGrid** — Filters on hidden pinned columns no longer log unknown-field warnings ([#965](https://github.com/dfh-candescent/forge-design-system/pull/965)).
|
|
@@ -8,6 +8,7 @@ Notes are generated from the release commit itself, so the versions and commit r
|
|
|
8
8
|
each entry are exact. Releases that contained nothing but backlog or dependency bookkeeping
|
|
9
9
|
are omitted.
|
|
10
10
|
|
|
11
|
+
- [0.3.13](https://design.candescent.com/docs/resources/release-notes/0.3.13/content.md) — 2026-11-11 — DataGrid adds tree data, detail panels, and column-targeted filters; ListItem and Menu receive visual and focus fixes.
|
|
11
12
|
- [0.3.12](https://design.candescent.com/docs/resources/release-notes/0.3.12/content.md) — 2026-11-04 — DataGrid adds built-in column types, pinning, type-aware filters, and polarity or delta number cells.
|
|
12
13
|
- [0.3.11](https://design.candescent.com/docs/resources/release-notes/0.3.11/content.md) — 2026-10-30 — Read-only Input and CurrencyInput stay non-editable on Android instead of accepting edits again.
|
|
13
14
|
- [0.3.10](https://design.candescent.com/docs/resources/release-notes/0.3.10/content.md) — 2026-10-30 — CurrencyInput no longer clips the top of default-size amounts on iOS.
|