@sproutsocial/seeds-react-drawer 1.0.0

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.
@@ -0,0 +1,378 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-function */
2
+ import React, { useState } from "react";
3
+ import type { Meta, StoryObj } from "@storybook/react";
4
+ import { Box } from "@sproutsocial/seeds-react-box";
5
+ import { Button } from "@sproutsocial/seeds-react-button";
6
+ import { Icon } from "@sproutsocial/seeds-react-icon";
7
+ // import { Tabs } from "@sproutsocial/seeds-react-tabs";
8
+ import { Text } from "@sproutsocial/seeds-react-text";
9
+ import Drawer from "./Drawer";
10
+
11
+ // @ts-ignore We'll come back to this later
12
+ const StatefulDrawer = ({ isOpen = true, onClose, children, ...rest }) => {
13
+ const [isDrawerOpen, setIsDrawerOpen] = useState(isOpen);
14
+
15
+ const onDrawerClose = () => {
16
+ setIsDrawerOpen(false);
17
+ onClose();
18
+ };
19
+
20
+ return (
21
+ <React.Fragment>
22
+ <Drawer
23
+ {...rest}
24
+ isOpen={isDrawerOpen}
25
+ onClose={onDrawerClose}
26
+ closeButtonLabel="closer drawer"
27
+ id="drawer-1"
28
+ >
29
+ {children}
30
+ </Drawer>
31
+ <Button
32
+ appearance="primary"
33
+ onClick={() => setIsDrawerOpen(!isDrawerOpen)}
34
+ >
35
+ Toggle Drawer
36
+ </Button>
37
+ </React.Fragment>
38
+ );
39
+ };
40
+
41
+ // @ts-ignore We'll come back to this later
42
+ const DrawerComponent = ({ direction, offset, width }) => {
43
+ const [isOpen, setIsOpen] = useState(false);
44
+
45
+ const onOpen = () => setIsOpen(true);
46
+
47
+ const onClose = () => setIsOpen(false);
48
+
49
+ return (
50
+ <Box>
51
+ <Box
52
+ width="100%"
53
+ bg="neutral.800"
54
+ display="flex"
55
+ justifyContent="flex-end"
56
+ padding={300}
57
+ >
58
+ <Button
59
+ appearance="secondary"
60
+ onClick={onOpen}
61
+ aria-label="View Notifications"
62
+ >
63
+ <Icon name="bell-outline" aria-hidden />
64
+ </Button>
65
+ </Box>
66
+ <Drawer
67
+ onClose={onClose}
68
+ isOpen={isOpen}
69
+ direction={direction}
70
+ offset={offset}
71
+ width={width}
72
+ id="notifications-drawer"
73
+ closeButtonLabel="close drawer"
74
+ >
75
+ <Drawer.Header title="Drawer Header" />
76
+ <Drawer.Content>
77
+ <Text color="text.body">Drawer Content</Text>
78
+ </Drawer.Content>
79
+ </Drawer>
80
+ </Box>
81
+ );
82
+ };
83
+
84
+ const BigDrawerContent = () => (
85
+ <Text.BodyCopy as="p">
86
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam ac consectetur
87
+ tortor. Fusce ac rutrum nibh. Phasellus rhoncus sed neque vitae dictum. Nunc
88
+ viverra venenatis pellentesque. Proin lorem massa, ornare in mauris eget,
89
+ commodo malesuada lacus. Phasellus quis purus in velit pharetra malesuada
90
+ sit amet nec libero. Fusce porta nulla id elit condimentum, a aliquam quam
91
+ placerat. Duis cursus vel felis non tincidunt. Cras sed quam at sapien
92
+ posuere scelerisque. Vivamus tortor sem, faucibus faucibus feugiat eu,
93
+ auctor vitae ex. Nunc vitae purus sit amet nulla imperdiet bibendum sit amet
94
+ elementum tortor. Nam vitae dui vitae metus aliquam aliquet. Curabitur
95
+ faucibus lacus ante, eu volutpat urna placerat vitae. Sed et porta mauris.
96
+ Class aptent taciti sociosqu ad litora torquent per conubia nostra, per
97
+ inceptos himenaeos. Praesent vel leo lectus.
98
+ <br />
99
+ <br />
100
+ Fusce ac vehicula dui. Quisque nec lacus a sapien lobortis sagittis eget
101
+ vitae lacus. Aenean quis lorem nec sapien vehicula consequat. Quisque
102
+ efficitur et eros in dapibus. Pellentesque sagittis vel dolor vitae
103
+ hendrerit. Ut elementum euismod iaculis. Maecenas lobortis urna lectus, nec
104
+ consequat quam facilisis a. Praesent aliquam ipsum quam, id dapibus nunc
105
+ facilisis ut. Ut rhoncus eu mauris nec congue. Etiam tempor ante in eros
106
+ ullamcorper feugiat. In nec diam leo. Quisque dignissim, purus nec porttitor
107
+ viverra, nibh odio gravida orci, at tempor odio arcu eget felis.
108
+ <br />
109
+ <br />
110
+ Sed fringilla sem leo, eget molestie elit lobortis eu. Donec eget risus quis
111
+ ante placerat vulputate sit amet at ex. Curabitur pulvinar pellentesque
112
+ justo sed iaculis. Praesent bibendum fringilla eros, at dapibus augue.
113
+ Pellentesque iaculis, nulla vestibulum pretium placerat, leo lorem laoreet
114
+ lorem, vel dignissim urna nunc vel leo. Suspendisse eu ipsum pellentesque,
115
+ pharetra diam sed, sollicitudin neque. Duis ornare dolor at ultricies
116
+ facilisis. Proin vel ullamcorper justo, tincidunt condimentum nunc.
117
+ <br />
118
+ <br />
119
+ Morbi et elementum diam. In et imperdiet sem, in viverra lorem. Fusce sit
120
+ amet urna felis. Cras eget dolor ac diam gravida hendrerit. Proin id urna
121
+ sed lorem mattis vehicula. Nullam nec magna auctor, consequat metus quis,
122
+ fermentum urna. Suspendisse nec turpis sodales, condimentum enim ut, sodales
123
+ diam. Donec luctus enim mauris, at semper lectus sagittis a. Suspendisse mi
124
+ enim, convallis et aliquam quis, pharetra quis lorem. Praesent congue
125
+ posuere tellus, id ullamcorper mi bibendum sit amet. Praesent turpis leo,
126
+ tempor quis ex sit amet, efficitur viverra velit. Praesent nisi sem, aliquet
127
+ non nunc a, fringilla efficitur neque. Pellentesque elit est, malesuada
128
+ finibus orci quis, lobortis varius tellus.
129
+ <br />
130
+ <br />
131
+ Sed interdum nulla massa, non mollis velit imperdiet et. Nam risus magna,
132
+ pulvinar vulputate tristique a, ornare blandit nunc. Nam massa odio,
133
+ venenatis ut accumsan vel, maximus lobortis purus. Vestibulum vitae ultrices
134
+ odio. Morbi vitae ante sed tellus molestie blandit. Morbi porttitor mi quis
135
+ laoreet commodo. Donec vel rutrum ipsum. Nunc sollicitudin lacinia eros quis
136
+ mollis. Sed interdum nulla massa, non mollis velit imperdiet et. Nam risus
137
+ magna, pulvinar vulputate tristique a, ornare blandit nunc. Nam massa odio,
138
+ venenatis ut accumsan vel, maximus lobortis purus. Vestibulum vitae ultrices
139
+ odio. Morbi vitae ante sed tellus molestie blandit. Morbi porttitor mi quis
140
+ laoreet commodo. Donec vel rutrum ipsum. Nunc sollicitudin lacinia eros quis
141
+ mollis. Sed interdum nulla massa, non mollis velit imperdiet et. Nam risus
142
+ magna, pulvinar vulputate tristique a, ornare blandit nunc. Nam massa odio,
143
+ venenatis ut accumsan vel, maximus lobortis purus. Vestibulum vitae ultrices
144
+ odio. Morbi vitae ante sed tellus molestie blandit. Morbi porttitor mi quis
145
+ laoreet commodo. Donec vel rutrum ipsum. Nunc sollicitudin lacinia eros quis
146
+ mollis. Sed interdum nulla massa, non mollis velit imperdiet et. Nam risus
147
+ magna, pulvinar vulputate tristique a, ornare blandit nunc. Nam massa odio,
148
+ venenatis ut accumsan vel, maximus lobortis purus. Vestibulum vitae ultrices
149
+ odio. Morbi vitae ante sed tellus molestie blandit. Morbi porttitor mi quis
150
+ laoreet commodo. Donec vel rutrum ipsum. Nunc sollicitudin lacinia eros quis
151
+ mollis.
152
+ </Text.BodyCopy>
153
+ );
154
+
155
+ const meta: Meta<typeof Drawer> = {
156
+ title: "Components/Drawer",
157
+ component: Drawer,
158
+ args: {
159
+ direction: "right",
160
+ offset: 0,
161
+ isOpen: true,
162
+ width: 600,
163
+ },
164
+ };
165
+ export default meta;
166
+ type Story = StoryObj<typeof Drawer>;
167
+
168
+ export const DrawerWithDefaults: Story = {
169
+ name: "Drawer With Defaults",
170
+ render: (args) => (
171
+ <StatefulDrawer
172
+ direction={args.direction}
173
+ offset={args.offset}
174
+ isOpen={args.isOpen}
175
+ width={args.width}
176
+ onClose={() => {}}
177
+ id="drawer"
178
+ closeButtonLabel="close drawer"
179
+ aria-labeledby="drawer-1-header"
180
+ aria-describedby="drawer-1-content"
181
+ >
182
+ <Drawer.Header title="Drawer" id="drawer-1-header" />
183
+ <Drawer.Content id="drawer-1-content">
184
+ <BigDrawerContent />
185
+ </Drawer.Content>
186
+ </StatefulDrawer>
187
+ ),
188
+ };
189
+
190
+ export const DrawerWithHeaderChildren: Story = {
191
+ name: "Drawer With Header Children",
192
+ render: (args) => (
193
+ <StatefulDrawer
194
+ direction={args.direction}
195
+ offset={args.offset}
196
+ isOpen={args.isOpen}
197
+ width={args.width}
198
+ onClose={() => {}}
199
+ id="drawer"
200
+ closeButtonLabel="close drawer"
201
+ >
202
+ <Drawer.Header>
203
+ <Box flexGrow={1}>
204
+ {/* <Tabs
205
+ fullWidth
206
+ selectedId="1"
207
+ onSelect={() => {
208
+ // eslint-disable-next-line no-console
209
+ console.log("does nothing");
210
+ }}
211
+ >
212
+ <Tabs.Button id="1">
213
+ <Box display="flex" justifyContent="center" alignItems="center">
214
+ <Icon name="bell-outline" mr={350} aria-hidden />
215
+ <Text as="div" fontSize={200} fontWeight="semibold">
216
+ Notifications
217
+ </Text>
218
+ </Box>
219
+ </Tabs.Button>
220
+ <Tabs.Button id="2">
221
+ <Box display="flex" justifyContent="center" alignItems="center">
222
+ <Icon name="triangle-exclamation-outline" mr={350} aria-hidden />
223
+ <Text as="div" fontSize={200} fontWeight="semibold">
224
+ Issues
225
+ </Text>
226
+ </Box>
227
+ </Tabs.Button>
228
+ </Tabs> */}
229
+ </Box>
230
+ <Box display="flex">
231
+ <Button
232
+ onClick={() => {
233
+ // eslint-disable-next-line no-console
234
+ console.log("does nothing");
235
+ }}
236
+ data-qa-button="Filter"
237
+ mr={300}
238
+ aria-label="Filter"
239
+ >
240
+ <Icon name="filter-outline" aria-hidden />
241
+ </Button>
242
+ <Button
243
+ mr={300}
244
+ onClick={() => {
245
+ // eslint-disable-next-line no-console
246
+ console.log("does nothing");
247
+ }}
248
+ aria-label="Settings"
249
+ >
250
+ <Icon name="gear-outline" aria-hidden />
251
+ </Button>
252
+ <Drawer.CloseButton />
253
+ </Box>
254
+ </Drawer.Header>
255
+ <Drawer.Content>
256
+ <BigDrawerContent />
257
+ </Drawer.Content>
258
+ </StatefulDrawer>
259
+ ),
260
+ };
261
+
262
+ export const DrawerWithHeaderRender: Story = {
263
+ name: "Drawer With Header Render",
264
+ render: (args) => (
265
+ <StatefulDrawer
266
+ direction={args.direction}
267
+ offset={args.offset}
268
+ isOpen={args.isOpen}
269
+ width={args.width}
270
+ onClose={() => {}}
271
+ id="drawer"
272
+ closeButtonLabel="close drawer"
273
+ >
274
+ <Drawer.Header
275
+ render={({ onClose }) => (
276
+ <Box
277
+ display="flex"
278
+ justifyContent="space-between"
279
+ p={500}
280
+ border="2px solid purple"
281
+ >
282
+ <Text color="text.body">Type "close" to close drawer</Text>
283
+ <input
284
+ onChange={(event) =>
285
+ event.target.value === "close" && (onClose ? onClose() : null)
286
+ }
287
+ />
288
+ </Box>
289
+ )}
290
+ />
291
+ <Drawer.Content>
292
+ <BigDrawerContent />
293
+ </Drawer.Content>
294
+ </StatefulDrawer>
295
+ ),
296
+ };
297
+
298
+ export const DrawerWithCloseButtonChildren: Story = {
299
+ name: "Drawer With Close Button Children",
300
+ render: (args) => (
301
+ <StatefulDrawer
302
+ direction={args.direction}
303
+ offset={args.offset}
304
+ isOpen={args.isOpen}
305
+ width={args.width}
306
+ onClose={() => {}}
307
+ id="drawer"
308
+ closeButtonLabel="close drawer"
309
+ aria-labeledby="drawer-with-close-button-header"
310
+ aria-describedby="drawer-with-close-button-content"
311
+ >
312
+ <Drawer.Header alignItems="center">
313
+ <Text.Headline as="h2" id="drawer-with-close-button-header">
314
+ Hello
315
+ </Text.Headline>
316
+ <Drawer.CloseButton appearance="primary">Close Me</Drawer.CloseButton>
317
+ </Drawer.Header>
318
+ <Drawer.Content id="drawer-with-close-button-content">
319
+ <BigDrawerContent />
320
+ </Drawer.Content>
321
+ </StatefulDrawer>
322
+ ),
323
+ };
324
+
325
+ export const DrawerWithCloseButtonRender: Story = {
326
+ name: "Drawer With Close Button Render",
327
+ render: (args) => (
328
+ <StatefulDrawer
329
+ direction={args.direction}
330
+ offset={args.offset}
331
+ isOpen={args.isOpen}
332
+ width={args.width}
333
+ onClose={() => {}}
334
+ id="drawer"
335
+ closeButtonLabel="close drawer"
336
+ >
337
+ <Drawer.Header alignItems="center">
338
+ <Text.BodyCopy>
339
+ This Drawer Will Close three seconds after clicking the "X"
340
+ </Text.BodyCopy>
341
+ <Drawer.CloseButton
342
+ render={({ onClose, closeButtonLabel }) => {
343
+ const newOnClose = () => {
344
+ setTimeout(() => {
345
+ // eslint-disable-next-line no-console
346
+ console.log("close");
347
+ onClose && onClose();
348
+ }, 3000);
349
+ };
350
+
351
+ return (
352
+ <Button
353
+ appearance="pill"
354
+ onClick={newOnClose}
355
+ ariaLabel={closeButtonLabel}
356
+ >
357
+ <Icon name="x-outline" aria-hidden />
358
+ </Button>
359
+ );
360
+ }}
361
+ />
362
+ </Drawer.Header>
363
+ <Drawer.Content>
364
+ <BigDrawerContent />
365
+ </Drawer.Content>
366
+ </StatefulDrawer>
367
+ ),
368
+ };
369
+
370
+ export const fromLeft: Story = {
371
+ name: "From left",
372
+ args: {
373
+ direction: "left",
374
+ offset: 0,
375
+ },
376
+ // @ts-ignore We'll come back to this later
377
+ render: (args) => <DrawerComponent {...args} />,
378
+ };
package/src/Drawer.tsx ADDED
@@ -0,0 +1,308 @@
1
+ import * as React from "react";
2
+ import { useContext, useEffect, useRef } from "react";
3
+ import FocusLock from "react-focus-lock";
4
+ import { animated, useTransition } from "@react-spring/web";
5
+ import { MOTION_DURATION_MEDIUM } from "@sproutsocial/seeds-motion/unitless";
6
+ import Box from "@sproutsocial/seeds-react-box";
7
+ import Button from "@sproutsocial/seeds-react-button";
8
+ import Icon from "@sproutsocial/seeds-react-icon";
9
+ // eslint-disable-next-line import/no-deprecated
10
+ import Text from "@sproutsocial/seeds-react-text";
11
+ import Portal from "@sproutsocial/seeds-react-portal";
12
+ import Container, { Content } from "./styles";
13
+ import type {
14
+ TypeDrawerContext,
15
+ TypeDrawerCloseButtonProps,
16
+ TypeDrawerHeaderProps,
17
+ TypeDrawerProps,
18
+ TypeInnerDrawerProps,
19
+ TypeDrawerContentProps,
20
+ TypeUseCloseOnBodyClickProps,
21
+ } from "./DrawerTypes";
22
+
23
+ const useSlideTransition = ({
24
+ isVisible,
25
+ width,
26
+ direction,
27
+ }: {
28
+ isVisible: boolean;
29
+ width: number;
30
+ direction: "left" | "right";
31
+ }) => {
32
+ const offset = width * (direction === "left" ? -1 : 1);
33
+
34
+ return useTransition(isVisible, {
35
+ from: {
36
+ opacity: 0,
37
+ x: offset,
38
+ },
39
+ enter: {
40
+ opacity: 1,
41
+ x: 0,
42
+ },
43
+ leave: {
44
+ opacity: 0,
45
+ x: offset,
46
+ },
47
+ config: {
48
+ duration: MOTION_DURATION_MEDIUM * 1000,
49
+ },
50
+ });
51
+ };
52
+
53
+ const AnimatedDrawer = animated(Container);
54
+
55
+ const doesRefContainEventTarget = (
56
+ ref: { current: { contains: (arg0: any) => any } },
57
+ event: Event
58
+ ) => {
59
+ return (
60
+ ref.current &&
61
+ event.target instanceof Node &&
62
+ ref.current.contains(event.target)
63
+ );
64
+ };
65
+
66
+ const DrawerContext = React.createContext<TypeDrawerContext>({});
67
+
68
+ const DrawerCloseButton = (props: TypeDrawerCloseButtonProps) => {
69
+ const { onClose, closeButtonLabel } = useContext(DrawerContext);
70
+
71
+ if (props.render) {
72
+ return (
73
+ props.render({
74
+ onClose,
75
+ closeButtonLabel,
76
+ }) ?? null
77
+ );
78
+ }
79
+
80
+ return (
81
+ <Button
82
+ appearance="pill"
83
+ aria-label={closeButtonLabel}
84
+ onClick={onClose}
85
+ {...props}
86
+ >
87
+ {props.children || <Icon aria-hidden name="x-outline" />}
88
+ </Button>
89
+ );
90
+ };
91
+
92
+ const DrawerHeader = ({
93
+ title = "",
94
+ id = undefined,
95
+ children,
96
+ render,
97
+ ...rest
98
+ }: TypeDrawerHeaderProps) => {
99
+ const drawerContext = useContext(DrawerContext);
100
+
101
+ if (render) {
102
+ return render(drawerContext);
103
+ }
104
+
105
+ return (
106
+ <Box
107
+ display="flex"
108
+ flex="0 0 auto"
109
+ justifyContent="space-between"
110
+ alignItems="center"
111
+ pt={400}
112
+ px={450}
113
+ {...rest}
114
+ >
115
+ {children || (
116
+ <React.Fragment>
117
+ <Text
118
+ as="h2"
119
+ fontSize={400}
120
+ fontWeight="semibold"
121
+ color="text.headline"
122
+ id={id}
123
+ >
124
+ {title}
125
+ </Text>
126
+ <DrawerCloseButton />
127
+ </React.Fragment>
128
+ )}
129
+ </Box>
130
+ );
131
+ };
132
+
133
+ const DrawerContent = ({ children, ...rest }: TypeDrawerContentProps) => (
134
+ <Content height="100%" p={450} color="text.body" {...rest}>
135
+ {children}
136
+ </Content>
137
+ );
138
+
139
+ const useCloseOnBodyClick = ({
140
+ ref,
141
+ disableCloseOnClickOutside,
142
+ onClose,
143
+ closeTargets,
144
+ }: TypeUseCloseOnBodyClickProps) => {
145
+ useEffect(() => {
146
+ const documentBody = document.body;
147
+
148
+ if (!documentBody) {
149
+ return;
150
+ }
151
+
152
+ const onEsc = (event: KeyboardEvent): void => {
153
+ if (event.key === "Escape") {
154
+ onClose();
155
+ }
156
+ };
157
+
158
+ const bodyClick = (event: Event): void => {
159
+ if (
160
+ // @ts-ignore I'm not sure how to type this ref properly
161
+ !doesRefContainEventTarget(ref, event) &&
162
+ !disableCloseOnClickOutside
163
+ ) {
164
+ onClose();
165
+ }
166
+ };
167
+
168
+ documentBody?.addEventListener("keydown", onEsc, { capture: true });
169
+
170
+ if (closeTargets) {
171
+ closeTargets.forEach((targetElement) =>
172
+ targetElement?.addEventListener("click", bodyClick, { capture: true })
173
+ );
174
+ } else {
175
+ documentBody.firstElementChild?.addEventListener("click", bodyClick, {
176
+ capture: true,
177
+ });
178
+ }
179
+
180
+ return () => {
181
+ documentBody?.removeEventListener("keydown", onEsc, { capture: true });
182
+
183
+ if (closeTargets) {
184
+ closeTargets.forEach((targetElement) =>
185
+ targetElement?.removeEventListener("click", bodyClick, {
186
+ capture: true,
187
+ })
188
+ );
189
+ } else {
190
+ documentBody.firstElementChild?.removeEventListener(
191
+ "click",
192
+ bodyClick,
193
+ { capture: true }
194
+ );
195
+ }
196
+ };
197
+ }, [onClose, disableCloseOnClickOutside, closeTargets, ref]);
198
+ };
199
+
200
+ const Drawer = ({
201
+ id,
202
+ offset,
203
+ direction,
204
+ children,
205
+ disableCloseOnClickOutside,
206
+ onClose,
207
+ zIndex,
208
+ closeTargets,
209
+ width,
210
+ focusLockExemptCheck,
211
+ isOpen,
212
+ ...rest
213
+ }: TypeInnerDrawerProps) => {
214
+ const ref = useRef(null);
215
+ useCloseOnBodyClick({
216
+ ref,
217
+ disableCloseOnClickOutside,
218
+ onClose,
219
+ closeTargets,
220
+ });
221
+
222
+ const transition = useSlideTransition({
223
+ isVisible: isOpen,
224
+ width,
225
+ direction,
226
+ });
227
+
228
+ return (
229
+ <FocusLock
230
+ key={id}
231
+ autoFocus={true}
232
+ returnFocus
233
+ whiteList={
234
+ focusLockExemptCheck ? (e) => !focusLockExemptCheck(e) : undefined
235
+ }
236
+ >
237
+ {transition((style, isVisible) =>
238
+ isVisible ? (
239
+ <AnimatedDrawer
240
+ ref={ref}
241
+ style={{ ...style, zIndex }}
242
+ width={width}
243
+ offset={offset}
244
+ direction={direction}
245
+ data-qa-drawer={id}
246
+ role="dialog"
247
+ {...rest}
248
+ >
249
+ {children}
250
+ </AnimatedDrawer>
251
+ ) : null
252
+ )}
253
+ </FocusLock>
254
+ );
255
+ };
256
+
257
+ const DrawerContainer = ({
258
+ children,
259
+ closeButtonLabel,
260
+ direction = "right",
261
+ disableCloseOnClickOutside = false,
262
+ id,
263
+ isOpen,
264
+ offset = 0,
265
+ onClose,
266
+ zIndex = 7,
267
+ closeTargets = [],
268
+ width = 600,
269
+ ...rest
270
+ }: TypeDrawerProps) => {
271
+ return (
272
+ <Portal id={id}>
273
+ <DrawerContext.Provider
274
+ value={{
275
+ onClose,
276
+ closeButtonLabel,
277
+ }}
278
+ >
279
+ <Drawer
280
+ isOpen={isOpen}
281
+ id={id}
282
+ offset={offset}
283
+ direction={direction}
284
+ disableCloseOnClickOutside={disableCloseOnClickOutside}
285
+ onClose={onClose}
286
+ zIndex={zIndex}
287
+ closeTargets={closeTargets}
288
+ width={width}
289
+ data-qa-drawer={id || ""}
290
+ data-qa-drawer-isopen={isOpen}
291
+ {...rest}
292
+ >
293
+ {children}
294
+ </Drawer>
295
+ </DrawerContext.Provider>
296
+ </Portal>
297
+ );
298
+ };
299
+
300
+ DrawerHeader.displayName = "Drawer.Header";
301
+ DrawerContent.displayName = "Drawer.Content";
302
+ DrawerCloseButton.displayName = "Drawer.CloseButton";
303
+
304
+ DrawerContainer.Header = DrawerHeader;
305
+ DrawerContainer.Content = DrawerContent;
306
+ DrawerContainer.CloseButton = DrawerCloseButton;
307
+
308
+ export default DrawerContainer;