playbook_ui 14.9.0.pre.rc.17 → 14.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d00eca4bbfbc0c7635601ac8ea5bc581b72dc830ef1341b878a85bd7ed1e71fc
4
- data.tar.gz: cfcdad0ccad5a5cc1d02625b5ac13fdbd3abd48ac162b6821968c65f70e93d1b
3
+ metadata.gz: c7a7f25e68582acb4d819f3a13e444e023d5e9a95bff66d1db87ee30c8697cf8
4
+ data.tar.gz: 4f818bdb6d0a5f7deb43dea03ec99fddc97b0fbfb0cefff7cae577eff2fcabac
5
5
  SHA512:
6
- metadata.gz: f19a2d498ee2652e7e20956b8ce047e638135ad3b9274dc19edeabf82b04ed4de1110c003b48bdda87773f44d9f3e09cf4413678ddce5073fcab4ba220a4ac2a
7
- data.tar.gz: aff5d022e2cfd855ecace5ea28927f9c1183c6f25231ce65a6266893fa3a616f6483dbe68270ff8c89cf7f3482ba9586a68b804c50b461406855bc5217d37ddc
6
+ metadata.gz: 86090fdf6679c81084b2b9e1373730a97b8dbfcc16dd265bf798e6056d65b970aec7e4d70c7f4ad480136b4ee600d98a716ade5deb8ade445fd83e9a6f851ce8
7
+ data.tar.gz: 6b04543f4665c4205c70f887a3ae02d1c7e264b97b0f76bd998320be0da33d067f14f3cce7e819e809b25780256366048a3afb5d6bf04b0d156ea0936b59ae7b
@@ -88,6 +88,7 @@ body.PBDrawer__Body--close {
88
88
  }
89
89
 
90
90
  .pb_drawer.pb_drawer_after_open {
91
+ pointer-events: auto;
91
92
  transform: translate3d(0, 0, 0);
92
93
  }
93
94
 
@@ -15,20 +15,22 @@ type DrawerProps = {
15
15
  aria?: { [key: string]: string };
16
16
  behavior?: "floating" | "push";
17
17
  border?: "full" | "none" | "right" | "left";
18
- breakpoint?: "none" | "xs" | "sm" | "md" | "lg" | "xl";
18
+ openBreakpoint?: "none" | "xs" | "sm" | "md" | "lg" | "xl";
19
+ closeBreakpoint?: "none" | "xs" | "sm" | "md" | "lg" | "xl";
19
20
  children: React.ReactNode | React.ReactNode[] | string;
20
21
  className?: string;
21
22
  data?: { [key: string]: string };
22
23
  htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
23
24
  id?: string;
24
25
  fullHeight?: boolean;
26
+ menuButtonID?: string;
25
27
  onClose?: () => void;
26
28
  opened: boolean;
27
29
  overlay: boolean;
28
30
  placement?: "left" | "right";
29
31
  size?: "xs" | "sm" | "md" | "lg" | "xl";
30
32
  text?: string;
31
- trigger?: string;
33
+ withinElement?: boolean;
32
34
  };
33
35
 
34
36
  const Drawer = (props: DrawerProps): React.ReactElement => {
@@ -36,19 +38,21 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
36
38
  aria = {},
37
39
  behavior = "floating",
38
40
  border = "none",
39
- breakpoint = "none",
41
+ openBreakpoint = "none",
42
+ closeBreakpoint = "none",
40
43
  className,
41
44
  data = {},
42
45
  htmlOptions = {},
43
46
  id,
44
47
  size = "md",
45
48
  children,
46
- fullHeight = false,
49
+ fullHeight = true,
50
+ menuButtonID,
47
51
  opened,
48
52
  onClose,
49
53
  overlay = true,
50
54
  placement = "left",
51
- trigger,
55
+ withinElement = false,
52
56
  } = props;
53
57
  const ariaProps = buildAriaProps(aria);
54
58
  const dataProps = buildDataProps(data);
@@ -80,6 +84,7 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
80
84
  drawer_border_full: border === "full",
81
85
  drawer_border_right: border === "right",
82
86
  drawer_border_left: border === "left",
87
+ pb_drawer_within_element: withinElement,
83
88
  }
84
89
  )} ${globalPropsString}`,
85
90
  afterOpen: "pb_drawer_after_open",
@@ -100,12 +105,11 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
100
105
  };
101
106
 
102
107
  const classes = classnames(buildCss("pb_drawer_wrapper"), className);
103
-
104
108
  const dynamicInlineProps = globalInlineProps(props)
105
-
109
+ const [menuButtonOpened, setMenuButtonOpened] = useState(false);
106
110
  const [triggerOpened, setTriggerOpened] = useState(false);
107
111
 
108
- const breakpointWidths: Record<DrawerProps["breakpoint"], number> = {
112
+ const breakpointWidths: Record<DrawerProps["openBreakpoint"], number> = {
109
113
  none: 0,
110
114
  xs: 575,
111
115
  sm: 768,
@@ -114,20 +118,30 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
114
118
  xl: 1400,
115
119
  };
116
120
 
117
- // State to manage opening the drawer based on breakpoint
118
- const [isBreakpointOpen, setIsBreakpointOpen] = useState(false);
121
+ const breakpointValues = {
122
+ none: 0,
123
+ xs: 575,
124
+ sm: 768,
125
+ md: 992,
126
+ lg: 1200,
127
+ xl: 1400,
128
+ }
129
+
130
+ const [isOpenBreakpointOpen, setIsOpenBreakpointOpen] = useState(false);
131
+ const [isUserClosed, setIsUserClosed] = useState(false);
119
132
 
120
133
  useEffect(() => {
121
- if (breakpoint === "none") return;
134
+ if (openBreakpoint === "none") return;
122
135
 
123
136
  const handleResize = () => {
124
137
  const width = window.innerWidth;
125
- const breakpointWidth = breakpointWidths[breakpoint];
138
+ const openBreakpointWidth = breakpointWidths[openBreakpoint];
126
139
 
127
- if (width <= breakpointWidth) {
128
- setIsBreakpointOpen(true);
140
+ if (width <= openBreakpointWidth) {
141
+ setIsOpenBreakpointOpen(true);
129
142
  } else {
130
- setIsBreakpointOpen(false);
143
+ setIsOpenBreakpointOpen(false);
144
+ setIsUserClosed(false); // Reset when the breakpoint condition changes
131
145
  }
132
146
  };
133
147
 
@@ -139,9 +153,53 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
139
153
  return () => {
140
154
  window.removeEventListener("resize", handleResize);
141
155
  };
142
- }, [breakpoint]);
156
+ }, [openBreakpoint]);
157
+
158
+ useEffect(() => {
159
+ if (closeBreakpoint === "none") return;
160
+
161
+ const handleResize = () => {
162
+ const width = window.innerWidth;
163
+ if (width >= breakpointValues[closeBreakpoint]) {
164
+ setIsOpenBreakpointOpen(true);
165
+ } else {
166
+ setIsOpenBreakpointOpen(false);
167
+ }
168
+ }
169
+
170
+ window.addEventListener("resize", handleResize);
171
+
172
+ handleResize();
173
+
174
+ return () => {
175
+ window.removeEventListener("resize", handleResize);
176
+ };
177
+
178
+ }, [closeBreakpoint]);
179
+
180
+ //hide menu button if breakpoint opens the drawer
181
+ useEffect(() => {
182
+ if (menuButtonID) {
183
+ const menuButton = document.getElementById(menuButtonID);
184
+ if (menuButton) {
185
+ if (isOpenBreakpointOpen) {
186
+ menuButton.style.display = 'none';
187
+ } else {
188
+ menuButton.style.display = '';
189
+ }
190
+ }
191
+ }
192
+ }, [menuButtonID, isOpenBreakpointOpen]);
143
193
 
144
- const modalIsOpened = trigger ? triggerOpened : opened || isBreakpointOpen;
194
+ // Reset isUserClosed when isBreakpointOpen changes
195
+ useEffect(() => {
196
+ if (isOpenBreakpointOpen) {
197
+ setIsUserClosed(false);
198
+ }
199
+ }, [isOpenBreakpointOpen]);
200
+
201
+ const modalIsOpened =
202
+ (isOpenBreakpointOpen && !isUserClosed) || menuButtonOpened || opened;
145
203
 
146
204
  const [animationState, setAnimationState] = useState("");
147
205
 
@@ -152,13 +210,15 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
152
210
  setAnimationState("beforeClose");
153
211
  setTimeout(() => {
154
212
  setAnimationState("");
155
- }, 200); // closeTimeoutMS
213
+ }, 200);
156
214
  }
157
215
  }, [modalIsOpened]);
158
216
 
159
217
  const isModalVisible = modalIsOpened || animationState === "beforeClose";
160
218
 
161
219
  useEffect(() => {
220
+ if (withinElement) return;
221
+
162
222
  const sizeMap: Record<DrawerProps["size"], string> = {
163
223
  xl: "365px",
164
224
  lg: "300px",
@@ -167,7 +227,6 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
167
227
  xs: "64px",
168
228
  };
169
229
  const body = document.querySelector("body");
170
-
171
230
  if (modalIsOpened && behavior === "push" && body) {
172
231
  if (placement === "left") {
173
232
  body.style.cssText = `margin-left: ${sizeMap[size]} !important; margin-right: '' !important;`;
@@ -183,46 +242,98 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
183
242
  body.style.cssText = ""; // Clear the styles when modal is closed or behavior is not 'push'
184
243
  body.classList.remove("PBDrawer__Body--open");
185
244
  }
186
- }, [modalIsOpened, behavior, placement, size]);
245
+ }, [modalIsOpened, behavior, placement, size, withinElement]);
187
246
 
188
247
  const api = {
189
- onClose: trigger
190
- ? function () {
191
- setTriggerOpened(false);
192
- }
193
- : onClose,
248
+ onClose: () => {
249
+ if (menuButtonID) {
250
+ setMenuButtonOpened(false);
251
+ }
252
+ setIsUserClosed(true);
253
+ if (onClose) {
254
+ onClose();
255
+ }
256
+ },
194
257
  };
195
258
 
259
+ useEffect(() => {
260
+ if (menuButtonID) {
261
+ const menuButton = document.getElementById(menuButtonID);
262
+ if (menuButton) {
263
+ const handleMenuButtonClick = () => {
264
+ if (modalIsOpened) {
265
+ // Drawer is open, close it
266
+ setMenuButtonOpened(false);
267
+ setIsUserClosed(true);
268
+ } else {
269
+ // Drawer is closed, open it
270
+ setMenuButtonOpened(true);
271
+ setIsUserClosed(false);
272
+ }
273
+ };
274
+ menuButton.addEventListener("click", handleMenuButtonClick);
275
+ return () => {
276
+ menuButton.removeEventListener("click", handleMenuButtonClick);
277
+ };
278
+ }
279
+ }
280
+ }, [menuButtonID, modalIsOpened]);
281
+
196
282
  return (
197
283
  <DialogContext.Provider value={api}>
198
- <div
199
- {...ariaProps}
200
- {...dataProps}
201
- {...htmlProps}
202
- className={classes}
203
- style={dynamicInlineProps}
204
- >
284
+ {withinElement ? (
285
+ isModalVisible && (
286
+ <div
287
+ {...ariaProps}
288
+ {...dataProps}
289
+ {...htmlProps}
290
+ style={dynamicInlineProps}
291
+ className={classnames(drawerClassNames.base, {
292
+ [drawerClassNames.afterOpen]:
293
+ animationState === "afterOpen",
294
+ [drawerClassNames.beforeClose]:
295
+ animationState === "beforeClose",
296
+ })}
297
+ id={id}
298
+ onClick={(e) => e.stopPropagation()}
299
+ >
300
+ {children}
301
+ </div>
302
+ )
303
+ ) : (
304
+ <div
305
+ {...ariaProps}
306
+ {...dataProps}
307
+ {...htmlProps}
308
+ className={classes}
309
+ style={dynamicInlineProps}
310
+ >
205
311
  {isModalVisible && (
206
312
  <div
207
313
  className={classnames(overlayClassNames.base, {
208
- [overlayClassNames.afterOpen]: animationState === "afterOpen",
209
- [overlayClassNames.beforeClose]: animationState === "beforeClose",
210
- })}
314
+ [overlayClassNames.afterOpen]:
315
+ animationState === "afterOpen",
316
+ [overlayClassNames.beforeClose]:
317
+ animationState === "beforeClose",
318
+ })}
211
319
  id={id}
212
- onClick={overlay ? onClose : undefined}
320
+ onClick={overlay ? api.onClose : undefined}
213
321
  >
214
- <div
215
- className={classnames(drawerClassNames.base, {
216
- [drawerClassNames.afterOpen]: animationState === "afterOpen",
217
- [drawerClassNames.beforeClose]: animationState === "beforeClose",
218
- })}
219
- onClick={(e) => e.stopPropagation()}
220
- >
221
- {children}
222
- </div>
322
+ <div
323
+ className={classnames(drawerClassNames.base, {
324
+ [drawerClassNames.afterOpen]:
325
+ animationState === "afterOpen",
326
+ [drawerClassNames.beforeClose]:
327
+ animationState === "beforeClose",
328
+ })}
329
+ onClick={(e) => e.stopPropagation()}
330
+ >
331
+ {children}
332
+ </div>
223
333
  </div>
224
334
  )}
225
- </div>
335
+ </div>
336
+ )}
226
337
  </DialogContext.Provider>
227
338
  );
228
339
  };
@@ -0,0 +1,31 @@
1
+ import React from "react";
2
+ import { Button, Drawer, Icon, Title } from "playbook-ui";
3
+
4
+ const DrawerMenu = () => {
5
+
6
+ return (
7
+ <>
8
+ <Button id="menuButton"
9
+ padding="sm"
10
+ >
11
+ <Icon icon="bars"
12
+ size="3x"
13
+ />
14
+ </Button>
15
+ <Drawer
16
+ behavior="push"
17
+ closeBreakpoint="md"
18
+ menuButtonID="menuButton"
19
+ overlay={false}
20
+ placement="left"
21
+ size="lg"
22
+ withinElement
23
+ >
24
+ <Title paddingBottom="md">A really neat menu</Title>
25
+ <Button text="This Button does nothing" />
26
+ </Drawer>
27
+ </>
28
+ );
29
+ };
30
+
31
+ export default DrawerMenu;
@@ -0,0 +1,6 @@
1
+ Our drawer kit can fulfill your responsive menu needs! Using the `closeBreakpoint` prop you can have the menu close on smaller screens like phones/tablets.
2
+
3
+ Set a menu button with the `menuButtonID` props. When the Drawer is open, the menu button will be hidden. But when your Brakpoint closes the drawer, you can toggle the Drawer open/close with your menu butotn.
4
+
5
+ Also use the `withinElement` props to have the Drawer open within a specific element, instead of the default behavior of it taking up the entire screen size.
6
+
@@ -6,7 +6,7 @@ examples:
6
6
 
7
7
  react:
8
8
  - drawer_default: Default
9
+ - drawer_menu: Menu Behavior
9
10
  - drawer_sizes: Sizes
10
11
  - drawer_overlay: Overlay
11
12
  - drawer_borders: Borders
12
- - drawer_breakpoints: Open on Breakpoints
@@ -3,3 +3,4 @@ export { default as DrawerSizes } from './_drawer_sizes.jsx'
3
3
  export { default as DrawerOverlay } from './_drawer_overlay.jsx'
4
4
  export { default as DrawerBorders } from './_drawer_borders.jsx'
5
5
  export { default as DrawerBreakpoints } from './_drawer_breakpoints.jsx'
6
+ export { default as DrawerMenu } from './_drawer_menu.jsx'