@cdx-ui/components 0.2.3 → 0.2.5
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/AGENTS.md +24 -0
- package/README.md +2 -0
- package/coverage.svg +1 -1
- package/docs/components/accordion/content.md +538 -0
- package/docs/components/alert/content.md +203 -0
- package/docs/components/alert-dialog/content.md +319 -0
- package/docs/components/avatar/content.md +368 -0
- package/docs/components/avatar/design.md +202 -0
- package/docs/components/badge/content.md +225 -0
- package/docs/components/bottom-sheet/content.md +353 -0
- package/docs/components/bottom-sheet/design.md +249 -0
- package/docs/components/box/content.md +141 -0
- package/docs/components/breadcrumbs/content.md +169 -0
- package/docs/components/button/content.md +398 -0
- package/docs/components/button/design.md +258 -0
- package/docs/components/calendar/content.md +137 -0
- package/docs/components/card/content.md +283 -0
- package/docs/components/carousel/content.md +417 -0
- package/docs/components/checkbox/content.md +236 -0
- package/docs/components/checkbox/design.md +214 -0
- package/docs/components/chip/content.md +439 -0
- package/docs/components/chip/design.md +418 -0
- package/docs/components/color-area/content.md +84 -0
- package/docs/components/color-field/content.md +132 -0
- package/docs/components/color-picker/content.md +209 -0
- package/docs/components/color-slider/content.md +118 -0
- package/docs/components/color-swatch/content.md +62 -0
- package/docs/components/color-swatch-picker/content.md +124 -0
- package/docs/components/content.md +98 -0
- package/docs/components/currency-input/content.md +205 -0
- package/docs/components/data-grid/content.md +521 -0
- package/docs/components/date-field/content.md +147 -0
- package/docs/components/date-picker/content.md +360 -0
- package/docs/components/date-range-picker/content.md +301 -0
- package/docs/components/date-time-field/content.md +157 -0
- package/docs/components/date-time-list/content.md +105 -0
- package/docs/components/date-time-picker/content.md +272 -0
- package/docs/components/dialog/content.md +436 -0
- package/docs/components/dialog/design.md +192 -0
- package/docs/components/divider/content.md +112 -0
- package/docs/components/drawer/content.md +428 -0
- package/docs/components/field/content.md +277 -0
- package/docs/components/form/content.md +62 -0
- package/docs/components/full-screen-dialog/content.md +881 -0
- package/docs/components/heading/content.md +55 -0
- package/docs/components/icon/content.md +190 -0
- package/docs/components/icon-button/content.md +200 -0
- package/docs/components/icon-button/design.md +165 -0
- package/docs/components/image/content.md +104 -0
- package/docs/components/input/content.md +346 -0
- package/docs/components/input/design.md +389 -0
- package/docs/components/insurance-disclosure/content.md +103 -0
- package/docs/components/link/content.md +180 -0
- package/docs/components/link/design.md +160 -0
- package/docs/components/list-item/content.md +695 -0
- package/docs/components/menu/content.md +1254 -0
- package/docs/components/month-calendar/content.md +84 -0
- package/docs/components/month-picker/content.md +273 -0
- package/docs/components/otp-input/content.md +327 -0
- package/docs/components/progress-bar/content.md +87 -0
- package/docs/components/progress-circle/content.md +176 -0
- package/docs/components/progress-segmented/content.md +119 -0
- package/docs/components/quick-action-button/content.md +154 -0
- package/docs/components/quick-action-button/design.md +170 -0
- package/docs/components/radio/content.md +224 -0
- package/docs/components/range-calendar/content.md +123 -0
- package/docs/components/reorderable-list/content.md +311 -0
- package/docs/components/scoped-theme/content.md +47 -0
- package/docs/components/scroll-shadow/content.md +693 -0
- package/docs/components/select/content.md +473 -0
- package/docs/components/select/design.md +301 -0
- package/docs/components/skeleton/content.md +104 -0
- package/docs/components/slider/content.md +423 -0
- package/docs/components/stack/content.md +161 -0
- package/docs/components/switch/content.md +150 -0
- package/docs/components/switch/design.md +208 -0
- package/docs/components/table/content.md +548 -0
- package/docs/components/table-pagination/content.md +177 -0
- package/docs/components/tabs/content.md +297 -0
- package/docs/components/text/content.md +142 -0
- package/docs/components/textarea/content.md +222 -0
- package/docs/components/tile/content.md +702 -0
- package/docs/components/toast/content.md +456 -0
- package/docs/components/toggle-button/content.md +505 -0
- package/docs/components/tooltip/content.md +350 -0
- package/docs/components/virtualized-list/content.md +250 -0
- package/docs/foundations/content.md +9 -0
- package/docs/foundations/expressions/icons/content.md +19 -0
- package/docs/foundations/styles/tokens/all-tokens/content.md +192 -0
- package/docs/foundations/styles/tokens/what-are-tokens/content.md +33 -0
- package/docs/foundations/styles/tokens/what-are-tokens/design.md +33 -0
- package/docs/getting-started/content.md +4 -0
- package/docs/getting-started/designers/content.md +13 -0
- package/docs/getting-started/designers/design.md +13 -0
- package/docs/getting-started/developers/accessibility/content.md +31 -0
- package/docs/getting-started/developers/content.md +612 -0
- package/docs/getting-started/developers/styling/content.md +195 -0
- package/docs/llms.txt +195 -0
- package/docs/patterns/account-management/content.md +75 -0
- package/docs/patterns/authentication/content.md +50 -0
- package/docs/patterns/content.md +10 -0
- package/docs/patterns/dashboard/content.md +34 -0
- package/docs/patterns/empty-states/content.md +32 -0
- package/docs/patterns/forms/content.md +108 -0
- package/docs/patterns/onboarding/content.md +69 -0
- package/docs/patterns/payments/content.md +35 -0
- package/docs/patterns/settings/content.md +72 -0
- package/docs/resources/content.md +9 -0
- package/docs/resources/figma-libraries/content.md +42 -0
- package/docs/resources/release-notes/0.0.1-beta.118/content.md +27 -0
- package/docs/resources/release-notes/0.0.1-beta.122/content.md +21 -0
- package/docs/resources/release-notes/0.0.1-beta.124/content.md +16 -0
- package/docs/resources/release-notes/0.0.1-beta.126/content.md +10 -0
- package/docs/resources/release-notes/0.0.1-beta.127/content.md +14 -0
- package/docs/resources/release-notes/0.0.1-beta.128/content.md +9 -0
- package/docs/resources/release-notes/0.0.1-beta.129/content.md +18 -0
- package/docs/resources/release-notes/0.0.1-beta.130/content.md +18 -0
- package/docs/resources/release-notes/0.0.1-beta.133/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.134/content.md +17 -0
- package/docs/resources/release-notes/0.0.1-beta.136/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.137/content.md +10 -0
- package/docs/resources/release-notes/0.0.1-beta.138/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.139/content.md +13 -0
- package/docs/resources/release-notes/0.0.1-beta.140/content.md +26 -0
- package/docs/resources/release-notes/0.0.1-beta.141/content.md +63 -0
- package/docs/resources/release-notes/0.0.1-beta.142/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.143/content.md +12 -0
- package/docs/resources/release-notes/0.0.1-beta.144/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.145/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.147/content.md +10 -0
- package/docs/resources/release-notes/0.0.1-beta.149/content.md +10 -0
- package/docs/resources/release-notes/0.0.1-beta.150/content.md +13 -0
- package/docs/resources/release-notes/0.0.1-beta.152/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.154/content.md +15 -0
- package/docs/resources/release-notes/0.0.1-beta.156/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.158/content.md +9 -0
- package/docs/resources/release-notes/0.0.1-beta.159/content.md +11 -0
- package/docs/resources/release-notes/0.0.1-beta.160/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.161/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.163/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.164/content.md +9 -0
- package/docs/resources/release-notes/0.0.1-beta.166/content.md +17 -0
- package/docs/resources/release-notes/0.0.1-beta.167/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.168/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.169/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.171/content.md +16 -0
- package/docs/resources/release-notes/0.0.1-beta.172/content.md +24 -0
- package/docs/resources/release-notes/0.0.1-beta.173/content.md +15 -0
- package/docs/resources/release-notes/0.0.1-beta.174/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.176/content.md +32 -0
- package/docs/resources/release-notes/0.0.1-beta.179/content.md +11 -0
- package/docs/resources/release-notes/0.0.1-beta.182/content.md +13 -0
- package/docs/resources/release-notes/0.0.1-beta.185/content.md +7 -0
- package/docs/resources/release-notes/0.0.1-beta.187/content.md +27 -0
- package/docs/resources/release-notes/0.1.1/content.md +23 -0
- package/docs/resources/release-notes/0.1.2/content.md +7 -0
- package/docs/resources/release-notes/0.1.4/content.md +19 -0
- package/docs/resources/release-notes/0.1.5/content.md +7 -0
- package/docs/resources/release-notes/0.1.6/content.md +7 -0
- package/docs/resources/release-notes/0.2.0/content.md +31 -0
- package/docs/resources/release-notes/0.2.1/content.md +17 -0
- package/docs/resources/release-notes/0.2.2/content.md +11 -0
- package/docs/resources/release-notes/0.2.3/content.md +15 -0
- package/docs/resources/release-notes/0.2.4/content.md +17 -0
- package/docs/resources/release-notes/content.md +65 -0
- package/lib/commonjs/components/Box/Box.js +9 -1
- package/lib/commonjs/components/Box/Box.js.map +1 -1
- package/lib/commonjs/components/Breadcrumbs/index.js +28 -3
- package/lib/commonjs/components/Breadcrumbs/index.js.map +1 -1
- package/lib/commonjs/components/Breadcrumbs/styles.js +27 -0
- package/lib/commonjs/components/Breadcrumbs/styles.js.map +1 -1
- package/lib/commonjs/components/DateTimeList/index.js +11 -26
- package/lib/commonjs/components/DateTimeList/index.js.map +1 -1
- package/lib/commonjs/components/DateTimeList/styles.js +2 -12
- package/lib/commonjs/components/DateTimeList/styles.js.map +1 -1
- package/lib/commonjs/components/ListItem/index.js.map +1 -1
- package/lib/commonjs/components/ListItem/styles.js +2 -1
- package/lib/commonjs/components/ListItem/styles.js.map +1 -1
- package/lib/commonjs/components/Menu/index.js +11 -5
- package/lib/commonjs/components/Menu/index.js.map +1 -1
- package/lib/commonjs/components/ScrollShadow/gradient.js +29 -0
- package/lib/commonjs/components/ScrollShadow/gradient.js.map +1 -0
- package/lib/commonjs/components/ScrollShadow/index.js +171 -44
- package/lib/commonjs/components/ScrollShadow/index.js.map +1 -1
- package/lib/commonjs/components/ScrollShadow/styles.js +58 -14
- package/lib/commonjs/components/ScrollShadow/styles.js.map +1 -1
- package/lib/commonjs/components/ScrollShadow/useComposedScrollHandler.js +63 -0
- package/lib/commonjs/components/ScrollShadow/useComposedScrollHandler.js.map +1 -0
- package/lib/commonjs/components/ScrollShadow/useScrollShadow.js +48 -8
- package/lib/commonjs/components/ScrollShadow/useScrollShadow.js.map +1 -1
- package/lib/commonjs/components/Stack/HStack.js +6 -2
- package/lib/commonjs/components/Stack/HStack.js.map +1 -1
- package/lib/commonjs/components/Stack/VStack.js +6 -2
- package/lib/commonjs/components/Stack/VStack.js.map +1 -1
- package/lib/commonjs/components/Tabs/index.js +16 -23
- package/lib/commonjs/components/Tabs/index.js.map +1 -1
- package/lib/commonjs/components/Tabs/styles.js +1 -10
- package/lib/commonjs/components/Tabs/styles.js.map +1 -1
- package/lib/commonjs/figma/ListItem.SectionHeader.figma.js +20 -5
- package/lib/commonjs/figma/ListItem.SectionHeader.figma.js.map +1 -1
- package/lib/commonjs/index.js +10 -10
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/components/Box/Box.js +9 -1
- package/lib/module/components/Box/Box.js.map +1 -1
- package/lib/module/components/Breadcrumbs/index.js +29 -4
- package/lib/module/components/Breadcrumbs/index.js.map +1 -1
- package/lib/module/components/Breadcrumbs/styles.js +26 -0
- package/lib/module/components/Breadcrumbs/styles.js.map +1 -1
- package/lib/module/components/DateTimeList/index.js +12 -27
- package/lib/module/components/DateTimeList/index.js.map +1 -1
- package/lib/module/components/DateTimeList/styles.js +1 -11
- package/lib/module/components/DateTimeList/styles.js.map +1 -1
- package/lib/module/components/ListItem/index.js.map +1 -1
- package/lib/module/components/ListItem/styles.js +2 -1
- package/lib/module/components/ListItem/styles.js.map +1 -1
- package/lib/module/components/Menu/index.js +11 -5
- package/lib/module/components/Menu/index.js.map +1 -1
- package/lib/module/components/ScrollShadow/gradient.js +24 -0
- package/lib/module/components/ScrollShadow/gradient.js.map +1 -0
- package/lib/module/components/ScrollShadow/index.js +170 -48
- package/lib/module/components/ScrollShadow/index.js.map +1 -1
- package/lib/module/components/ScrollShadow/styles.js +57 -13
- package/lib/module/components/ScrollShadow/styles.js.map +1 -1
- package/lib/module/components/ScrollShadow/useComposedScrollHandler.js +57 -0
- package/lib/module/components/ScrollShadow/useComposedScrollHandler.js.map +1 -0
- package/lib/module/components/ScrollShadow/useScrollShadow.js +46 -8
- package/lib/module/components/ScrollShadow/useScrollShadow.js.map +1 -1
- package/lib/module/components/Stack/HStack.js +6 -2
- package/lib/module/components/Stack/HStack.js.map +1 -1
- package/lib/module/components/Stack/VStack.js +6 -2
- package/lib/module/components/Stack/VStack.js.map +1 -1
- package/lib/module/components/Tabs/index.js +17 -24
- package/lib/module/components/Tabs/index.js.map +1 -1
- package/lib/module/components/Tabs/styles.js +0 -9
- package/lib/module/components/Tabs/styles.js.map +1 -1
- package/lib/module/figma/ListItem.SectionHeader.figma.js +20 -5
- package/lib/module/figma/ListItem.SectionHeader.figma.js.map +1 -1
- package/lib/module/index.js +6 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/animation/hooks/usePopupDialogContentAnimation.d.ts +2 -2
- package/lib/typescript/animation/hooks/usePopupOverlayAnimation.d.ts +2 -2
- package/lib/typescript/components/Box/Box.d.ts +4 -0
- package/lib/typescript/components/Box/Box.d.ts.map +1 -1
- package/lib/typescript/components/Breadcrumbs/index.d.ts +3 -1
- package/lib/typescript/components/Breadcrumbs/index.d.ts.map +1 -1
- package/lib/typescript/components/Breadcrumbs/styles.d.ts +2 -0
- package/lib/typescript/components/Breadcrumbs/styles.d.ts.map +1 -1
- package/lib/typescript/components/DateTimeList/index.d.ts.map +1 -1
- package/lib/typescript/components/DateTimeList/styles.d.ts +1 -4
- package/lib/typescript/components/DateTimeList/styles.d.ts.map +1 -1
- package/lib/typescript/components/ListItem/index.d.ts +5 -4
- package/lib/typescript/components/ListItem/index.d.ts.map +1 -1
- package/lib/typescript/components/ListItem/styles.d.ts +1 -1
- package/lib/typescript/components/ListItem/styles.d.ts.map +1 -1
- package/lib/typescript/components/Menu/index.d.ts.map +1 -1
- package/lib/typescript/components/ScrollShadow/gradient.d.ts +7 -0
- package/lib/typescript/components/ScrollShadow/gradient.d.ts.map +1 -0
- package/lib/typescript/components/ScrollShadow/index.d.ts +57 -15
- package/lib/typescript/components/ScrollShadow/index.d.ts.map +1 -1
- package/lib/typescript/components/ScrollShadow/styles.d.ts +8 -2
- package/lib/typescript/components/ScrollShadow/styles.d.ts.map +1 -1
- package/lib/typescript/components/ScrollShadow/useComposedScrollHandler.d.ts +13 -0
- package/lib/typescript/components/ScrollShadow/useComposedScrollHandler.d.ts.map +1 -0
- package/lib/typescript/components/ScrollShadow/useScrollShadow.d.ts +15 -2
- package/lib/typescript/components/ScrollShadow/useScrollShadow.d.ts.map +1 -1
- package/lib/typescript/components/Stack/HStack.d.ts +3 -2
- package/lib/typescript/components/Stack/HStack.d.ts.map +1 -1
- package/lib/typescript/components/Stack/VStack.d.ts +3 -2
- package/lib/typescript/components/Stack/VStack.d.ts.map +1 -1
- package/lib/typescript/components/Tabs/index.d.ts.map +1 -1
- package/lib/typescript/components/Tabs/styles.d.ts +0 -7
- package/lib/typescript/components/Tabs/styles.d.ts.map +1 -1
- package/lib/typescript/components/Toast/animation.d.ts +3 -3
- package/lib/typescript/components/Toast/animation.d.ts.map +1 -1
- package/lib/typescript/figma/ListItem.SectionHeader.figma.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +6 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +11 -9
- package/src/components/Box/Box.tsx +18 -4
- package/src/components/Breadcrumbs/index.tsx +28 -4
- package/src/components/Breadcrumbs/styles.ts +30 -0
- package/src/components/DateTimeList/index.tsx +13 -26
- package/src/components/DateTimeList/styles.ts +1 -10
- package/src/components/ListItem/index.tsx +5 -4
- package/src/components/ListItem/styles.ts +1 -0
- package/src/components/Menu/index.tsx +11 -8
- package/src/components/ScrollShadow/gradient.ts +48 -0
- package/src/components/ScrollShadow/index.tsx +300 -69
- package/src/components/ScrollShadow/styles.ts +45 -28
- package/src/components/ScrollShadow/useComposedScrollHandler.ts +58 -0
- package/src/components/ScrollShadow/useScrollShadow.ts +72 -10
- package/src/components/Stack/HStack.tsx +8 -4
- package/src/components/Stack/VStack.tsx +8 -4
- package/src/components/Tabs/index.tsx +25 -35
- package/src/components/Tabs/styles.ts +0 -9
- package/src/index.ts +8 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Divider (https://design.candescent.com/docs/components/divider)
|
|
2
|
+
|
|
3
|
+
Resources: [Figma](https://www.figma.com/design/0lEVMVlLj8ZS4fgItr3pmd/%E2%AD%90-Forge-DS--Components?node-id=6771-8895), [Storybook](https://victorious-wave-0daadf00f.6.azurestaticapps.net/?path=/story/layout-divider--default)
|
|
4
|
+
|
|
5
|
+
`Divider` visually separates related groups of content.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Divider } from '@cdx-ui/components';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Basic
|
|
12
|
+
|
|
13
|
+
Use a horizontal divider to separate stacked sections.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { Divider, VStack } from '@cdx-ui/components';
|
|
17
|
+
|
|
18
|
+
export default function DividerBasicDemo() {
|
|
19
|
+
return (
|
|
20
|
+
<VStack space="xl" className="w-full">
|
|
21
|
+
<Divider />
|
|
22
|
+
<Divider />
|
|
23
|
+
<Divider />
|
|
24
|
+
</VStack>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## With label
|
|
30
|
+
|
|
31
|
+
Add `Divider.Label` to place text between two line segments. Labeled dividers must use this sub-component so the label receives the correct typography and accessibility treatment.
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { Divider, VStack } from '@cdx-ui/components';
|
|
35
|
+
|
|
36
|
+
export default function DividerWithLabelDemo() {
|
|
37
|
+
return (
|
|
38
|
+
<VStack space="xl" className="w-full">
|
|
39
|
+
<Divider>
|
|
40
|
+
<Divider.Label>or</Divider.Label>
|
|
41
|
+
</Divider>
|
|
42
|
+
<Divider>
|
|
43
|
+
<Divider.Label>More options</Divider.Label>
|
|
44
|
+
</Divider>
|
|
45
|
+
</VStack>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Vertical
|
|
51
|
+
|
|
52
|
+
Set `vertical` to separate content arranged side by side. The parent must provide an explicit height so the divider can stretch.
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { Box, Divider, HStack, Text } from '@cdx-ui/components';
|
|
56
|
+
|
|
57
|
+
export default function DividerVerticalDemo() {
|
|
58
|
+
return (
|
|
59
|
+
<HStack className="h-40 w-full items-stretch">
|
|
60
|
+
<Box className="flex-1 items-center justify-center">
|
|
61
|
+
<Text>Checking</Text>
|
|
62
|
+
</Box>
|
|
63
|
+
<Divider vertical>
|
|
64
|
+
<Divider.Label>or</Divider.Label>
|
|
65
|
+
</Divider>
|
|
66
|
+
<Box className="flex-1 items-center justify-center">
|
|
67
|
+
<Text>Savings</Text>
|
|
68
|
+
</Box>
|
|
69
|
+
</HStack>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## API
|
|
75
|
+
|
|
76
|
+
### Divider
|
|
77
|
+
|
|
78
|
+
| Prop | Type | Default | Description |
|
|
79
|
+
| --- | --- | --- | --- |
|
|
80
|
+
| `className?` | `string` | — | — |
|
|
81
|
+
| `children?` | `ReactNode` | — | When present, splits the divider into line, content, line. Use `Divider.Label` so the label receives the correct typography and accessibility treatment. |
|
|
82
|
+
| `vertical?` | `boolean` | — | Renders a vertical divider instead of the default horizontal orientation. |
|
|
83
|
+
|
|
84
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props). The default orientation is horizontal.
|
|
85
|
+
|
|
86
|
+
## Sub-components
|
|
87
|
+
|
|
88
|
+
### Divider.Label
|
|
89
|
+
|
|
90
|
+
Text displayed between the divider's two line segments.
|
|
91
|
+
|
|
92
|
+
| Prop | Type | Default | Description |
|
|
93
|
+
| --- | --- | --- | --- |
|
|
94
|
+
| `className?` | `string` | — | Additional Uniwind/Tailwind classes, merged after the text's own styles. |
|
|
95
|
+
| `children?` | `ReactNode` | — | Text content, which may include nested `Text` elements. |
|
|
96
|
+
| `asChild?` | `boolean` | — | Renders the consumer's child element in place of the default `Text` host. |
|
|
97
|
+
|
|
98
|
+
Inherits all [`TextProps`](https://reactnative.dev/docs/text#props).
|
|
99
|
+
|
|
100
|
+
## Accessibility
|
|
101
|
+
|
|
102
|
+
An unlabeled divider is decorative and hidden from the accessibility tree. For a labeled divider, the line segments are hidden while the label remains available to screen readers.
|
|
103
|
+
|
|
104
|
+
`Divider` does not define a semantic section boundary. Use a heading or landmark role when content needs programmatic grouping.
|
|
105
|
+
|
|
106
|
+
## When to use
|
|
107
|
+
|
|
108
|
+
| Component | Use for |
|
|
109
|
+
| -------------------------- | ------------------------------------------------------------ |
|
|
110
|
+
| `Divider` | Section breaks, login "or" separators, toolbar groups |
|
|
111
|
+
| `ListItem` `showSeparator` | Bottom border between list rows |
|
|
112
|
+
| `ListItem.SectionHeader` | Dated or grouped list section headings with an accent border |
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# Drawer (https://design.candescent.com/docs/components/drawer)
|
|
2
|
+
|
|
3
|
+
Resources: [Figma](https://www.figma.com/design/0lEVMVlLj8ZS4fgItr3pmd/%E2%AD%90-Forge-DS--Components?node-id=9956-15204), [Storybook](https://victorious-wave-0daadf00f.6.azurestaticapps.net/?path=/story/overlays-drawer--default)
|
|
4
|
+
|
|
5
|
+
A compound panel with permanent and modal presentations. Both share the same header, content, and
|
|
6
|
+
footer anatomy. `variant` only changes how the panel appears on the page. Both variants attach to
|
|
7
|
+
an edge through `placement` (`left`, `right`, `top`, `bottom`); the default is `right`.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Drawer } from '@cdx-ui/components';
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
> [!NOTE]
|
|
14
|
+
>
|
|
15
|
+
> **Portal host**
|
|
16
|
+
>
|
|
17
|
+
> Modal drawers portal `Drawer.Header`, `Drawer.Content`, and `Drawer.Footer` automatically.
|
|
18
|
+
> `ForgeDesignProvider` mounts the shared portal host; otherwise mount one `PortalHost` from
|
|
19
|
+
> `@cdx-ui/primitives` near your app root.
|
|
20
|
+
|
|
21
|
+
## Basic
|
|
22
|
+
|
|
23
|
+
Modal drawers overlay the page from the chosen edge with a backdrop. Clicking the backdrop, the
|
|
24
|
+
header close control, or pressing Escape closes the drawer. Open them with `isOpen` /
|
|
25
|
+
`onOpenChange` — there is no trigger slot in Figma.
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { useState } from 'react';
|
|
29
|
+
import { Button, Drawer, Text } from '@cdx-ui/components';
|
|
30
|
+
|
|
31
|
+
export default function DrawerBasicDemo() {
|
|
32
|
+
const [open, setOpen] = useState(false);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<Button onPress={() => setOpen(true)}>
|
|
37
|
+
<Button.Label>Open drawer</Button.Label>
|
|
38
|
+
</Button>
|
|
39
|
+
<Drawer variant="modal" isOpen={open} onOpenChange={setOpen}>
|
|
40
|
+
<Drawer.Header>
|
|
41
|
+
<Drawer.Title>Filter accounts</Drawer.Title>
|
|
42
|
+
<Drawer.Description>Choose which accounts appear in this view.</Drawer.Description>
|
|
43
|
+
</Drawer.Header>
|
|
44
|
+
<Drawer.Content>
|
|
45
|
+
<Text>Drawer body content stays scrollable when it exceeds the panel height.</Text>
|
|
46
|
+
</Drawer.Content>
|
|
47
|
+
<Drawer.Footer>
|
|
48
|
+
<Button variant="ghost" onPress={() => setOpen(false)}>
|
|
49
|
+
<Button.Label>Cancel</Button.Label>
|
|
50
|
+
</Button>
|
|
51
|
+
<Button onPress={() => setOpen(false)}>
|
|
52
|
+
<Button.Label>Apply</Button.Label>
|
|
53
|
+
</Button>
|
|
54
|
+
</Drawer.Footer>
|
|
55
|
+
</Drawer>
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Permanent rail
|
|
62
|
+
|
|
63
|
+
Use `variant="permanent"` for an in-layout rail that pushes sibling content aside. Place a
|
|
64
|
+
left or right drawer next to a `flex-1` main region in a horizontal row (drawer after the main
|
|
65
|
+
region for `right`, before it for `left`). Place a top or bottom drawer in a vertical column.
|
|
66
|
+
There is no overlay; the header close control still dismisses the rail.
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { Box, Button, Drawer, Text } from '@cdx-ui/components';
|
|
70
|
+
|
|
71
|
+
export default function DrawerPermanentDemo() {
|
|
72
|
+
return (
|
|
73
|
+
<Box className="h-90 flex-row border border-stroke-secondary">
|
|
74
|
+
<Box className="flex-1 items-center justify-center gap-4 p-4">
|
|
75
|
+
<Text>Main content area</Text>
|
|
76
|
+
<Button variant="outline">
|
|
77
|
+
<Button.Label>Primary action</Button.Label>
|
|
78
|
+
</Button>
|
|
79
|
+
</Box>
|
|
80
|
+
<Drawer variant="permanent" size="small">
|
|
81
|
+
<Drawer.Header showSeparator={false}>
|
|
82
|
+
<Drawer.Title>Accounts</Drawer.Title>
|
|
83
|
+
</Drawer.Header>
|
|
84
|
+
<Drawer.Content>
|
|
85
|
+
<Text size="sm" color="secondary">
|
|
86
|
+
Checking
|
|
87
|
+
</Text>
|
|
88
|
+
<Text size="sm" color="secondary">
|
|
89
|
+
Savings
|
|
90
|
+
</Text>
|
|
91
|
+
<Text size="sm" color="secondary">
|
|
92
|
+
Credit card
|
|
93
|
+
</Text>
|
|
94
|
+
</Drawer.Content>
|
|
95
|
+
</Drawer>
|
|
96
|
+
</Box>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Sizes
|
|
102
|
+
|
|
103
|
+
Panel width follows the `size` variant on left and right: `small` (240px), `default` (360px), and
|
|
104
|
+
`large` (480px), capped at the viewport. On top and bottom the same tokens map to height.
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
import { Box, Drawer, Text } from '@cdx-ui/components';
|
|
108
|
+
|
|
109
|
+
const sizeLabels = {
|
|
110
|
+
small: '240px',
|
|
111
|
+
default: '360px',
|
|
112
|
+
large: '480px',
|
|
113
|
+
} as const;
|
|
114
|
+
|
|
115
|
+
export default function DrawerSizesDemo() {
|
|
116
|
+
return (
|
|
117
|
+
<Box className="gap-4">
|
|
118
|
+
{(Object.keys(sizeLabels) as (keyof typeof sizeLabels)[]).map((size) => (
|
|
119
|
+
<Drawer key={size} size={size} className="h-30">
|
|
120
|
+
<Drawer.Header showSeparator={false}>
|
|
121
|
+
<Drawer.Title>{size}</Drawer.Title>
|
|
122
|
+
</Drawer.Header>
|
|
123
|
+
<Drawer.Content>
|
|
124
|
+
<Text size="sm" color="secondary">
|
|
125
|
+
{sizeLabels[size]}
|
|
126
|
+
</Text>
|
|
127
|
+
</Drawer.Content>
|
|
128
|
+
</Drawer>
|
|
129
|
+
))}
|
|
130
|
+
</Box>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Placement
|
|
136
|
+
|
|
137
|
+
Set `placement` to open the panel from `left`, `right`, `top`, or `bottom`. The most common case is
|
|
138
|
+
`right`, which is the default.
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
import { useState } from 'react';
|
|
142
|
+
import { Box, Button, Drawer, Text, type DrawerPlacement } from '@cdx-ui/components';
|
|
143
|
+
|
|
144
|
+
const placements: DrawerPlacement[] = ['left', 'right', 'top', 'bottom'];
|
|
145
|
+
|
|
146
|
+
export default function DrawerSidesDemo() {
|
|
147
|
+
const [open, setOpen] = useState(false);
|
|
148
|
+
const [placement, setPlacement] = useState<DrawerPlacement>('right');
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<>
|
|
152
|
+
<Box className="flex-row flex-wrap gap-2">
|
|
153
|
+
{placements.map((value) => (
|
|
154
|
+
<Button
|
|
155
|
+
key={value}
|
|
156
|
+
variant="outline"
|
|
157
|
+
onPress={() => {
|
|
158
|
+
setPlacement(value);
|
|
159
|
+
setOpen(true);
|
|
160
|
+
}}
|
|
161
|
+
>
|
|
162
|
+
<Button.Label>{value}</Button.Label>
|
|
163
|
+
</Button>
|
|
164
|
+
))}
|
|
165
|
+
</Box>
|
|
166
|
+
<Drawer variant="modal" isOpen={open} onOpenChange={setOpen} placement={placement}>
|
|
167
|
+
<Drawer.Header>
|
|
168
|
+
<Drawer.Title>{placement} drawer</Drawer.Title>
|
|
169
|
+
<Drawer.Description>The panel attaches to this edge of the viewport.</Drawer.Description>
|
|
170
|
+
</Drawer.Header>
|
|
171
|
+
<Drawer.Content>
|
|
172
|
+
<Text>Default is right. Size maps to width on left/right and height on top/bottom.</Text>
|
|
173
|
+
</Drawer.Content>
|
|
174
|
+
<Drawer.Footer>
|
|
175
|
+
<Button variant="ghost" onPress={() => setOpen(false)}>
|
|
176
|
+
<Button.Label>Close</Button.Label>
|
|
177
|
+
</Button>
|
|
178
|
+
</Drawer.Footer>
|
|
179
|
+
</Drawer>
|
|
180
|
+
</>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Full bleed content
|
|
186
|
+
|
|
187
|
+
Set `fullBleed` on `Drawer.Content` to remove horizontal padding for edge-to-edge lists, dividers, or imagery.
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import { Box, Drawer, ListItem } from '@cdx-ui/components';
|
|
191
|
+
|
|
192
|
+
export default function DrawerFullBleedDemo() {
|
|
193
|
+
return (
|
|
194
|
+
<Box className="h-70 flex-row border border-stroke-secondary">
|
|
195
|
+
<Drawer>
|
|
196
|
+
<Drawer.Header>
|
|
197
|
+
<Drawer.Title>Recent activity</Drawer.Title>
|
|
198
|
+
</Drawer.Header>
|
|
199
|
+
<Drawer.Content fullBleed>
|
|
200
|
+
{['Coffee shop', 'Direct deposit', 'Transfer to savings'].map((label, index, labels) => (
|
|
201
|
+
<ListItem key={label} size="compact" showSeparator={index < labels.length - 1}>
|
|
202
|
+
<ListItem.Content>
|
|
203
|
+
<ListItem.Title>{label}</ListItem.Title>
|
|
204
|
+
</ListItem.Content>
|
|
205
|
+
</ListItem>
|
|
206
|
+
))}
|
|
207
|
+
</Drawer.Content>
|
|
208
|
+
</Drawer>
|
|
209
|
+
</Box>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## Header variants
|
|
215
|
+
|
|
216
|
+
Compose `Drawer.LeadingSlot`, `Drawer.Title`, and `Drawer.Description` directly inside
|
|
217
|
+
`Drawer.Header`. The header places the leading slot first, stacks the title and description, and
|
|
218
|
+
adds a close control at the end. Set `close={null}` to remove it.
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
import { FilterList } from '@cdx-ui/icons';
|
|
222
|
+
import { Box, Drawer, Icon, Text } from '@cdx-ui/components';
|
|
223
|
+
|
|
224
|
+
export default function DrawerHeaderVariantsDemo() {
|
|
225
|
+
return (
|
|
226
|
+
<Box className="gap-4">
|
|
227
|
+
<Drawer className="h-40">
|
|
228
|
+
<Drawer.Header>
|
|
229
|
+
<Drawer.LeadingSlot>
|
|
230
|
+
<Icon as={FilterList} className="size-6" />
|
|
231
|
+
</Drawer.LeadingSlot>
|
|
232
|
+
<Drawer.Title>Filter accounts</Drawer.Title>
|
|
233
|
+
<Drawer.Description>Choose which accounts appear in this view.</Drawer.Description>
|
|
234
|
+
</Drawer.Header>
|
|
235
|
+
<Drawer.Content>
|
|
236
|
+
<Text size="sm" color="secondary">
|
|
237
|
+
Leading slot, text column, and the default close control.
|
|
238
|
+
</Text>
|
|
239
|
+
</Drawer.Content>
|
|
240
|
+
</Drawer>
|
|
241
|
+
<Drawer className="h-30">
|
|
242
|
+
<Drawer.Header close={null}>
|
|
243
|
+
<Drawer.Title>Accounts</Drawer.Title>
|
|
244
|
+
</Drawer.Header>
|
|
245
|
+
<Drawer.Content>
|
|
246
|
+
<Text size="sm" color="secondary">
|
|
247
|
+
No close control.
|
|
248
|
+
</Text>
|
|
249
|
+
</Drawer.Content>
|
|
250
|
+
</Drawer>
|
|
251
|
+
</Box>
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## API
|
|
257
|
+
|
|
258
|
+
### Drawer
|
|
259
|
+
|
|
260
|
+
Controls open state, dismissal behavior, size, and variant for the compound component.
|
|
261
|
+
|
|
262
|
+
| Prop | Type | Default | Description |
|
|
263
|
+
| --- | --- | --- | --- |
|
|
264
|
+
| `className?` | `string` | — | — |
|
|
265
|
+
| `children` | `ReactNode` | — | — |
|
|
266
|
+
| `size?` | `'small' \| 'default' \| 'large' \| null` | — | — |
|
|
267
|
+
| `variant?` | `'permanent' \| 'modal' \| null` | — | — |
|
|
268
|
+
| `placement?` | `'left' \| 'right' \| 'top' \| 'bottom'` | `'right'` | Edge the panel attaches to. Applies to both `modal` and `permanent`. |
|
|
269
|
+
| `fullBleed?` | `boolean` | — | — |
|
|
270
|
+
| `animation?` | `'disable-all'` | — | — |
|
|
271
|
+
| `zIndex?` | `number` | — | Stacking order for the modal overlay layer (backdrop + panel). Defaults to {@link MODAL_OVERLAY_Z_INDEX} (10000). |
|
|
272
|
+
| `isOpen?` | `boolean` | — | Controlled open state. Use `defaultOpen` for the uncontrolled variant. |
|
|
273
|
+
| `onOpenChange?` | `((open: boolean) => void)` | — | — |
|
|
274
|
+
| `defaultOpen?` | `boolean` | — | — |
|
|
275
|
+
| `closeOnBackdropPress?` | `boolean` | — | — |
|
|
276
|
+
| `closeOnEscKey?` | `boolean` | — | — |
|
|
277
|
+
|
|
278
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props), except `children` and `role`.
|
|
279
|
+
|
|
280
|
+
| Attribute | Value | Description |
|
|
281
|
+
| ----------- | -------- | ------------ |
|
|
282
|
+
| `data-slot` | `drawer` | Root element |
|
|
283
|
+
|
|
284
|
+
## Sub-components
|
|
285
|
+
|
|
286
|
+
### Drawer.Header
|
|
287
|
+
|
|
288
|
+
Fixed top region. Place `Drawer.LeadingSlot`, `Drawer.Title`, and `Drawer.Description` as direct
|
|
289
|
+
children. Whatever the JSX order, the header renders the first leading slot, then a column holding
|
|
290
|
+
every other child, then the close control. It renders a default `Drawer.Close` unless you compose
|
|
291
|
+
one yourself. Pass a node to `close` to replace it, or `close={null}` to remove it. `asChild`
|
|
292
|
+
renders the child unchanged, with no close control.
|
|
293
|
+
|
|
294
|
+
`Drawer.LeadingSlot` and `Drawer.Close` are matched by component identity. Wrapping either in
|
|
295
|
+
`memo()`, an HOC, or a custom component moves it into the text column. Extra leading slots or close
|
|
296
|
+
controls are not rendered.
|
|
297
|
+
|
|
298
|
+
| Prop | Type | Default | Description |
|
|
299
|
+
| --- | --- | --- | --- |
|
|
300
|
+
| `className?` | `string` | — | — |
|
|
301
|
+
| `children?` | `ReactNode` | — | — |
|
|
302
|
+
| `showSeparator?` | `boolean \| null` | — | — |
|
|
303
|
+
| `asChild?` | `boolean` | — | Substitute the header element with the single child. The child is rendered unchanged: no row partition and no close control are applied, and `close` is ignored. |
|
|
304
|
+
| `close?` | `ReactNode` | — | Close control rendered at the end of the row. - omitted: renders a composed `Drawer.Close` child if present, otherwise a default `<Drawer.Close />` - `null`: renders no close control - a node: rendered in place of the default and any `Drawer.Close` child |
|
|
305
|
+
|
|
306
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props).
|
|
307
|
+
|
|
308
|
+
### Drawer.LeadingSlot
|
|
309
|
+
|
|
310
|
+
Optional leading region in the header (icon or custom content). Place it as a direct child of
|
|
311
|
+
`Drawer.Header`. Hidden from the accessibility tree by default.
|
|
312
|
+
|
|
313
|
+
| Prop | Type | Default | Description |
|
|
314
|
+
| --- | --- | --- | --- |
|
|
315
|
+
| `className?` | `string` | — | — |
|
|
316
|
+
| `children?` | `ReactNode` | — | — |
|
|
317
|
+
| `asChild?` | `boolean` | — | — |
|
|
318
|
+
|
|
319
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props).
|
|
320
|
+
|
|
321
|
+
### Drawer.Close
|
|
322
|
+
|
|
323
|
+
Dismiss control. `Drawer.Header` renders one by default. Compose it yourself to change its props,
|
|
324
|
+
such as a more specific `accessibilityLabel` (default `"Close"`) or custom children in place of the
|
|
325
|
+
close icon. Closes modal and permanent drawers through `onOpenChange(false)`. Modal drawers also
|
|
326
|
+
close when the backdrop is pressed (`closeOnBackdropPress`, default `true`).
|
|
327
|
+
|
|
328
|
+
| Prop | Type | Default | Description |
|
|
329
|
+
| --- | --- | --- | --- |
|
|
330
|
+
| `className?` | `string` | — | — |
|
|
331
|
+
| `children?` | `ReactNode` | — | Replaces the default close glyph. |
|
|
332
|
+
| `accessibilityLabel?` | `string` | — | Overrides the text that's read by the screen reader when the user interacts with the element. By default, the label is constructed by traversing all the children and accumulating all the Text nodes separated by space. |
|
|
333
|
+
| `asChild?` | `boolean` | — | — |
|
|
334
|
+
|
|
335
|
+
Inherits all [`PressableProps`](https://reactnative.dev/docs/pressable#props).
|
|
336
|
+
|
|
337
|
+
### Drawer.Title
|
|
338
|
+
|
|
339
|
+
Heading announced when the modal drawer opens.
|
|
340
|
+
|
|
341
|
+
| Prop | Type | Default | Description |
|
|
342
|
+
| --- | --- | --- | --- |
|
|
343
|
+
| `className?` | `string` | — | — |
|
|
344
|
+
| `children?` | `ReactNode` | — | — |
|
|
345
|
+
| `asChild?` | `boolean` | — | — |
|
|
346
|
+
|
|
347
|
+
Inherits all [`TextProps`](https://reactnative.dev/docs/text#props).
|
|
348
|
+
|
|
349
|
+
### Drawer.Description
|
|
350
|
+
|
|
351
|
+
Secondary text linked to the panel through `aria-describedby` on modal drawers.
|
|
352
|
+
|
|
353
|
+
| Prop | Type | Default | Description |
|
|
354
|
+
| --- | --- | --- | --- |
|
|
355
|
+
| `className?` | `string` | — | — |
|
|
356
|
+
| `children?` | `ReactNode` | — | — |
|
|
357
|
+
| `asChild?` | `boolean` | — | — |
|
|
358
|
+
|
|
359
|
+
Inherits all [`TextProps`](https://reactnative.dev/docs/text#props).
|
|
360
|
+
|
|
361
|
+
### Drawer.Content
|
|
362
|
+
|
|
363
|
+
Scrollable content region between the header and footer. Matches the Figma `Drawer.Content` slot. Set `fullBleed` to remove horizontal padding.
|
|
364
|
+
|
|
365
|
+
| Prop | Type | Default | Description |
|
|
366
|
+
| --- | --- | --- | --- |
|
|
367
|
+
| `className?` | `string` | — | — |
|
|
368
|
+
| `children?` | `ReactNode` | — | — |
|
|
369
|
+
| `contentClassName?` | `string` | — | — |
|
|
370
|
+
| `fullBleed?` | `boolean` | — | — |
|
|
371
|
+
|
|
372
|
+
Inherits all [`ScrollViewProps`](https://reactnative.dev/docs/scrollview#props).
|
|
373
|
+
|
|
374
|
+
### Drawer.Footer
|
|
375
|
+
|
|
376
|
+
Action row below the content. Layout stacks vertically below 600px viewport width and aligns horizontally on wider viewports unless `layout` is set.
|
|
377
|
+
|
|
378
|
+
| Prop | Type | Default | Description |
|
|
379
|
+
| --- | --- | --- | --- |
|
|
380
|
+
| `className?` | `string` | — | — |
|
|
381
|
+
| `children?` | `ReactNode` | — | — |
|
|
382
|
+
| `showSeparator?` | `boolean \| null` | — | — |
|
|
383
|
+
| `direction?` | `'row' \| 'column'` | — | — |
|
|
384
|
+
| `asChild?` | `boolean` | — | — |
|
|
385
|
+
|
|
386
|
+
Inherits all [`ViewProps`](https://reactnative.dev/docs/view#props).
|
|
387
|
+
|
|
388
|
+
## Hook
|
|
389
|
+
|
|
390
|
+
### useDrawer
|
|
391
|
+
|
|
392
|
+
Returns the nearest modal drawer's state and dismissal configuration:
|
|
393
|
+
|
|
394
|
+
```tsx
|
|
395
|
+
const { open, onOpenChange } = useDrawer();
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## Anatomy
|
|
399
|
+
|
|
400
|
+
| `data-slot` | Element |
|
|
401
|
+
| -------------------- | ------------------------------------- |
|
|
402
|
+
| `drawer` | Root panel (permanent) or modal shell |
|
|
403
|
+
| `drawer-overlay` | Modal backdrop scrim |
|
|
404
|
+
| `drawer-header` | Header region |
|
|
405
|
+
| `drawer-leading` | Optional header leading slot |
|
|
406
|
+
| `drawer-title` | Title text |
|
|
407
|
+
| `drawer-description` | Description text |
|
|
408
|
+
| `drawer-close` | Header dismiss control |
|
|
409
|
+
| `drawer-content` | Scrollable body region |
|
|
410
|
+
| `drawer-footer` | Footer actions |
|
|
411
|
+
|
|
412
|
+
## Accessibility
|
|
413
|
+
|
|
414
|
+
- Modal drawers receive `aria-modal`, `aria-labelledby`, and `aria-describedby` relationships automatically.
|
|
415
|
+
- Focus moves into the panel, remains trapped while open, and returns to the previously focused element after close.
|
|
416
|
+
- Escape closes the modal drawer on web when `closeOnEscKey` is enabled.
|
|
417
|
+
- Android's hardware back button closes the modal drawer.
|
|
418
|
+
- Permanent drawers stay in layout, do not trap focus, and do not render an overlay.
|
|
419
|
+
|
|
420
|
+
## Constraints
|
|
421
|
+
|
|
422
|
+
- A shared `PortalHost` must be mounted once near the app root. `ForgeDesignProvider` includes one.
|
|
423
|
+
- Modal drawers portal Figma slots automatically. Do not wrap them in `Dialog.Popup` or a custom portal.
|
|
424
|
+
- Modal drawers slide in from `placement` using transform only.
|
|
425
|
+
- Permanent left/right drawers sit in a horizontal flex row next to a `flex-1` sibling. Permanent
|
|
426
|
+
top/bottom drawers sit in a vertical flex column next to a `flex-1` sibling.
|
|
427
|
+
- Permanent drawers are for wide layouts (desktop, tablet, landscape). On a phone they consume
|
|
428
|
+
most of the viewport (`small` is 240px). Use `variant="modal"` on small screens.
|