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 +4 -4
- data/app/pb_kits/playbook/pb_drawer/_drawer.scss +1 -0
- data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +157 -46
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +31 -0
- data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.md +6 -0
- data/app/pb_kits/playbook/pb_drawer/docs/example.yml +1 -1
- data/app/pb_kits/playbook/pb_drawer/docs/index.js +1 -0
- data/dist/chunks/_weekday_stacked-CiL8BjKa.js +45 -0
- data/dist/chunks/vendor.js +1 -1
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +4 -2
- data/dist/chunks/_weekday_stacked-4d5sISq_.js +0 -45
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9f0c08d0cd203e01dea2e3674ddc35b4ebdbad6396d853e198ea07c6a75e26b3
|
|
4
|
+
data.tar.gz: ab8f784b7c089bb1ae91db38ea1f765d6ab726debacc4af65b81e611ba506f79
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7781a84145a08f4541151c7da9de2afa25db63294040953c12432ae2eec6eba065462be94d2d95bfc96a8469ae4d5a47260a42f21f1476eb2475b732b4c51f22
|
|
7
|
+
data.tar.gz: edb1ffa1e1f16cdfb39501d4ff977896fec46f6dfca2c98bf354d3803ac6699914f0407173beed489013beebf4b98ff076c9f0e3befcf5f4549e9ea84a5e1d07
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
49
|
+
fullHeight = true,
|
|
50
|
+
menuButtonID,
|
|
47
51
|
opened,
|
|
48
52
|
onClose,
|
|
49
53
|
overlay = true,
|
|
50
54
|
placement = "left",
|
|
51
|
-
|
|
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["
|
|
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
|
-
|
|
118
|
-
|
|
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 (
|
|
134
|
+
if (openBreakpoint === "none") return;
|
|
122
135
|
|
|
123
136
|
const handleResize = () => {
|
|
124
137
|
const width = window.innerWidth;
|
|
125
|
-
const
|
|
138
|
+
const openBreakpointWidth = breakpointWidths[openBreakpoint];
|
|
126
139
|
|
|
127
|
-
if (width <=
|
|
128
|
-
|
|
140
|
+
if (width <= openBreakpointWidth) {
|
|
141
|
+
setIsOpenBreakpointOpen(true);
|
|
129
142
|
} else {
|
|
130
|
-
|
|
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
|
-
}, [
|
|
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
|
-
|
|
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);
|
|
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:
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
|
|
209
|
-
|
|
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
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
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
|
+
|
|
@@ -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'
|