Skip to content

Commit 58a6d9d

Browse files
docs(Drawer): add API decision (#2009)
* feat(Drawer): add API decisions * feat: add full skeleton * fix: image width * fix: typo * feat: add stacking section to api decision * Update packages/blade/src/components/Drawer/_decisions/decisions.md Co-authored-by: Nitin Kumar <[email protected]> * fix: remove DrawerHeaderLink and DrawerHeaderButton * feat: add open questions * feat: add discussion slack thread * feat: update API decision with new API --------- Co-authored-by: Nitin Kumar <[email protected]>
1 parent 85f229d commit 58a6d9d

File tree

3 files changed

+174
-0
lines changed

3 files changed

+174
-0
lines changed
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# Drawer
2+
3+
A drawer is a panel that slides in mostly from the right side of the screen over the existing content in the viewport. It helps in providing additional details or context and can also be used to promote product features or new products.
4+
5+
<img width="500px" src="./2024-02-07-20-04-07.png" alt="Drawer Figma Skeleton">
6+
7+
## Design
8+
9+
- [Drawer - Figma Design](https://www.figma.com/file/jubmQL9Z8V7881ayUD95ps/Blade-DSL?node-id=78667%3A66663&mode=dev)
10+
11+
## Proposed API
12+
13+
```jsx
14+
<Drawer
15+
isOpen={}
16+
onDismiss={() => {}}
17+
showOverlay
18+
>
19+
<DrawerHeader
20+
title=""
21+
subtitle=""
22+
leading={<StarIcon />}
23+
titleSuffix={<Badge></Badge>}
24+
trailing={
25+
<Button icon={DownloadIcon} />
26+
}
27+
/>
28+
<DrawerBody>
29+
<Slot />
30+
</DrawerBody>
31+
<Drawer>
32+
```
33+
34+
<details>
35+
<summary><b>Full Usage Example</b></summary>
36+
37+
```jsx
38+
const MyCuteDrawer = () => {
39+
const [showDrawer, setShowDrawer] = React.useState(false);
40+
return (
41+
<Box>
42+
<Button onClick={() => setShowDrawer(true)}>Open Drawer</Button>
43+
<Drawer
44+
isOpen={showDrawer}
45+
onDismiss={() => {
46+
setShowDrawer(false);
47+
}}
48+
>
49+
<DrawerHeader
50+
title="Announcements"
51+
/>
52+
<DrawerBody>
53+
<FTXAnnouncement />
54+
<RazorpayOnePromotions />
55+
<CatPictures />
56+
</DrawerBody>
57+
<Drawer>
58+
</Box>
59+
)
60+
}
61+
62+
```
63+
64+
</details>
65+
66+
### Props
67+
68+
```ts
69+
type DrawerProps = {
70+
/**
71+
* Controlled state of drawer open or not
72+
*/
73+
isOpen: boolean;
74+
75+
/**
76+
* Dismiss handler
77+
*/
78+
onDismiss: () => void;
79+
80+
/**
81+
* Show or hide overlay.
82+
*
83+
* Also decides if clicking outside on overlay closes the drawer or not
84+
*/
85+
showOverlay?: boolean;
86+
87+
/**
88+
* Initial focus reference element
89+
*/
90+
initialFocusRef?: React.MutableRefObject<any>;
91+
92+
/**
93+
* children node.
94+
*
95+
* Supports DrawerHeader and DrawerBody
96+
*/
97+
children: React.ReactNode;
98+
99+
/**
100+
* Override z-index of Drawer.
101+
*
102+
* @default 1002
103+
*/
104+
zIndex?: number;
105+
106+
/**
107+
* Accessibility label for the drawer
108+
*/
109+
accessibilityLabel?: string;
110+
};
111+
112+
type DrawerHeaderProps = {
113+
/**
114+
* Title of the Drawer
115+
*/
116+
title: string;
117+
118+
/**
119+
* Subtitle of the Drawer
120+
*/
121+
subtitle?: string;
122+
123+
/**
124+
* Leading element
125+
*
126+
* Icon or Asset
127+
*/
128+
leading?: ReactNode;
129+
130+
/**
131+
* Title suffix element
132+
*
133+
* Badge
134+
*/
135+
titleSuffix?: ReactNode;
136+
137+
/**
138+
* Title trailing element
139+
*
140+
* Link, Button[]
141+
*/
142+
trailing?: ReactNode;
143+
};
144+
```
145+
146+
_No alternate APIs were considered because Drawer is closer to Modal on overall meaning and API perspective so made sense to go with API that is closer to Modal, also all DS Drawer components I referenced have similar API_
147+
148+
## Drawer Stacking
149+
150+
- Only 2 Drawers can be stacked on top of each other
151+
- 2nd Drawer always has overlay independent of `showOverlay` prop
152+
- 1st Drawer peeks from behind with 16px gap when 2nd Drawer is opened
153+
154+
## Accessibility
155+
156+
- **Aria Attributes:** Drawer will have `aria-modal="true"` and `role="dialog"` and will be treated as modal for voiceover users.
157+
- **Focus Handling:** Ensure Close Icon and Back Icon is focussable
158+
- **Keyboard Handling:** Pressing `ESC` should close the drawer
159+
160+
Will work in a similar manner as [Ant Design - Drawer](https://ant.design/components/drawer)
161+
162+
## References
163+
164+
- https://atlassian.design/components/drawer/examples
165+
- https://ant.design/components/drawer
166+
167+
## Open Questions
168+
169+
- **Design:** Should 2nd Drawer have back button or should it continue to have close button ([Context](https://github.com/razorpay/blade/pull/2009#discussion_r1487305755))
170+
- We won't have back button anymore. We will have 1st Drawer peek from behind
171+
- **Dev:** Should there be a prop for dismissing component on outside click. E.g. `shouldDismissOnOutsideClick` or should we handle it as part of controlled component (with the UX that confirmation modal is always shown irrespective of whether its outside click or close button click)
172+
- We won't have new prop. This can be achieved with controlled component
173+
- **Dev:** Should we build components like `DrawerHeaderIcon`, `DrawerHeaderAsset` (similar to `ActionListItemIcon`, `CardHeaderIcon`) or should rely on consumer to pass correct sizes and colors without building additional wrappers (similar to `DropdownHeader`, `ModalHeader`, `BottomSheetHeader`)? ([Discussion](https://razorpay.slack.com/archives/G01B3LQ9H0W/p1707822018408929))
174+
- We won't build new components. We will follow what we follow on ModalHeader, BottomSheetHeader, etc

0 commit comments

Comments
 (0)