playbook_ui 14.9.0.pre.rc.17 → 14.9.0.pre.rc.18

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d00eca4bbfbc0c7635601ac8ea5bc581b72dc830ef1341b878a85bd7ed1e71fc
4
- data.tar.gz: cfcdad0ccad5a5cc1d02625b5ac13fdbd3abd48ac162b6821968c65f70e93d1b
3
+ metadata.gz: 9f0c08d0cd203e01dea2e3674ddc35b4ebdbad6396d853e198ea07c6a75e26b3
4
+ data.tar.gz: ab8f784b7c089bb1ae91db38ea1f765d6ab726debacc4af65b81e611ba506f79
5
5
  SHA512:
6
- metadata.gz: f19a2d498ee2652e7e20956b8ce047e638135ad3b9274dc19edeabf82b04ed4de1110c003b48bdda87773f44d9f3e09cf4413678ddce5073fcab4ba220a4ac2a
7
- data.tar.gz: aff5d022e2cfd855ecace5ea28927f9c1183c6f25231ce65a6266893fa3a616f6483dbe68270ff8c89cf7f3482ba9586a68b804c50b461406855bc5217d37ddc
6
+ metadata.gz: 7781a84145a08f4541151c7da9de2afa25db63294040953c12432ae2eec6eba065462be94d2d95bfc96a8469ae4d5a47260a42f21f1476eb2475b732b4c51f22
7
+ data.tar.gz: edb1ffa1e1f16cdfb39501d4ff977896fec46f6dfca2c98bf354d3803ac6699914f0407173beed489013beebf4b98ff076c9f0e3befcf5f4549e9ea84a5e1d07
@@ -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'