playbook_ui 14.11.1.pre.alpha.responsivetablerails5364 → 14.12.0.pre.alpha.PLAY1602lightboxoverlapnitrobug5646

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.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +2 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +18 -2
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +27 -5
  5. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +17 -2
  6. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +23 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +29 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +61 -4
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.jsx +50 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination.jsx +1 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pagination_with_props.jsx +1 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows.jsx +60 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows.md +5 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions.jsx +78 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions.md +1 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header.jsx +53 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header.md +1 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows.jsx +52 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows.md +1 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_control.md +2 -2
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_no_subrows.json +42 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_with_id.json +299 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +5 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +6 -1
  25. data/app/pb_kits/playbook/pb_button/button.html.erb +2 -3
  26. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +1 -6
  27. data/app/pb_kits/playbook/pb_collapsible/collapsible.html.erb +3 -1
  28. data/app/pb_kits/playbook/pb_collapsible/collapsible.rb +3 -0
  29. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +24 -16
  30. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +2 -0
  31. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_default_date.md +1 -1
  32. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_turbo_frames.html.erb +13 -0
  33. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_turbo_frames_rails.md +3 -0
  34. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +1 -0
  35. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.html.erb +3 -9
  36. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.md +5 -0
  37. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.html.erb +38 -0
  38. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.md +3 -0
  39. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +1 -0
  40. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +145 -183
  41. data/app/pb_kits/playbook/pb_drawer/_drawer.tsx +158 -268
  42. data/app/pb_kits/playbook/pb_drawer/context.ts +11 -0
  43. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_behavior.jsx +38 -0
  44. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.jsx +3 -45
  45. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.jsx +0 -1
  46. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_default.jsx +9 -16
  47. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.jsx +44 -19
  48. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.md +21 -3
  49. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.jsx +16 -21
  50. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_sizes.jsx +2 -19
  51. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +2 -1
  52. data/app/pb_kits/playbook/pb_drawer/docs/index.js +1 -0
  53. data/app/pb_kits/playbook/pb_drawer/drawer.test.jsx +5 -5
  54. data/app/pb_kits/playbook/pb_drawer/hooks/useBreakpoint.tsx +60 -0
  55. data/app/pb_kits/playbook/pb_drawer/hooks/useDrawerAnimation.tsx +21 -0
  56. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.md +1 -1
  57. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +7 -12
  58. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +9 -14
  59. data/app/pb_kits/playbook/pb_dropdown/dropdown_option.html.erb +6 -11
  60. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +8 -14
  61. data/app/pb_kits/playbook/pb_icon_button/_icon_button.scss +78 -0
  62. data/app/pb_kits/playbook/pb_icon_button/docs/_icon_button_default.html.erb +3 -0
  63. data/app/pb_kits/playbook/pb_icon_button/docs/example.yml +7 -0
  64. data/app/pb_kits/playbook/pb_icon_button/icon_button.html.erb +16 -0
  65. data/app/pb_kits/playbook/pb_icon_button/icon_button.rb +22 -0
  66. data/app/pb_kits/playbook/pb_lightbox/lightbox.scss +5 -5
  67. data/app/pb_kits/playbook/pb_list/item.html.erb +30 -8
  68. data/app/pb_kits/playbook/pb_list/item.rb +7 -0
  69. data/app/pb_kits/playbook/pb_list/list.html.erb +31 -11
  70. data/app/pb_kits/playbook/pb_list/list.rb +4 -0
  71. data/app/pb_kits/playbook/pb_loading_inline/_loading_inline.tsx +6 -1
  72. data/app/pb_kits/playbook/pb_multiple_users/_multiple_users.scss +4 -0
  73. data/app/pb_kits/playbook/pb_multiple_users/_multiple_users.tsx +1 -0
  74. data/app/pb_kits/playbook/pb_multiple_users/multiple_users.html.erb +1 -1
  75. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +30 -12
  76. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.html.erb +15 -0
  77. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.jsx +24 -0
  78. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_format.md +1 -0
  79. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +3 -1
  80. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  81. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  82. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +20 -1
  83. data/app/pb_kits/playbook/pb_radio/_radio.scss +12 -8
  84. data/app/pb_kits/playbook/pb_radio/docs/_radio_custom_children.jsx +8 -3
  85. data/app/pb_kits/playbook/pb_select/_select.scss +3 -5
  86. data/app/pb_kits/playbook/pb_select/_select.tsx +5 -1
  87. data/app/pb_kits/playbook/pb_select/select.html.erb +2 -2
  88. data/app/pb_kits/playbook/pb_selectable_icon/_selectable_icon.tsx +9 -1
  89. data/app/pb_kits/playbook/pb_selectable_icon/docs/_selectable_icon_default.jsx +4 -1
  90. data/app/pb_kits/playbook/pb_selectable_icon/docs/_selectable_icon_single_select.jsx +4 -1
  91. data/app/pb_kits/playbook/pb_selectable_list/selectable_list.html.erb +17 -3
  92. data/app/pb_kits/playbook/pb_selectable_list/selectable_list.rb +3 -0
  93. data/app/pb_kits/playbook/pb_selectable_list/selectable_list_item.html.erb +11 -4
  94. data/app/pb_kits/playbook/pb_selectable_list/selectable_list_item.rb +3 -0
  95. data/app/pb_kits/playbook/pb_table/_table.tsx +2 -3
  96. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns.html.erb +74 -0
  97. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns_rails.md +3 -0
  98. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_rails.md +2 -2
  99. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns.html.erb +74 -0
  100. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns_rails.md +3 -0
  101. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible.html.erb +47 -0
  102. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_rails.md +2 -0
  103. data/app/pb_kits/playbook/pb_table/docs/example.yml +3 -0
  104. data/app/pb_kits/playbook/pb_table/index.ts +187 -88
  105. data/app/pb_kits/playbook/pb_table/styles/_collapsible.scss +12 -0
  106. data/app/pb_kits/playbook/pb_table/styles/_scroll.scss +2 -1
  107. data/app/pb_kits/playbook/pb_table/table.html.erb +1 -1
  108. data/app/pb_kits/playbook/pb_table/table.rb +17 -2
  109. data/app/pb_kits/playbook/pb_table/table_row.html.erb +20 -1
  110. data/app/pb_kits/playbook/pb_table/table_row.rb +5 -0
  111. data/app/pb_kits/playbook/pb_table/utilities/addDataTitle.ts +22 -0
  112. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.html.erb +46 -0
  113. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask_rails.md +3 -0
  114. data/app/pb_kits/playbook/pb_text_input/docs/example.yml +2 -1
  115. data/app/pb_kits/playbook/pb_text_input/index.js +103 -0
  116. data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +4 -0
  117. data/app/pb_kits/playbook/pb_text_input/text_input.rb +33 -3
  118. data/app/pb_kits/playbook/pb_timeline/_timeline.scss +30 -30
  119. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_truncated_text.html.erb +19 -0
  120. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_truncated_text.jsx +27 -0
  121. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_truncated_text.md +1 -0
  122. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
  123. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  124. data/dist/chunks/_typeahead-BWwaAo_0.js +36 -0
  125. data/dist/chunks/_weekday_stacked-zyBCd1s8.js +45 -0
  126. data/dist/chunks/{lib-B7sgJtGS.js → lib-kMuhBuU7.js} +2 -2
  127. data/dist/chunks/{pb_form_validation-C5Cc0-1v.js → pb_form_validation-DBJ0wZuS.js} +1 -1
  128. data/dist/chunks/vendor.js +1 -1
  129. data/dist/menu.yml +6 -0
  130. data/dist/playbook-doc.js +1 -1
  131. data/dist/playbook-rails-react-bindings.js +1 -1
  132. data/dist/playbook-rails.js +1 -1
  133. data/dist/playbook.css +1 -1
  134. data/lib/playbook/version.rb +2 -2
  135. metadata +62 -7
  136. data/dist/chunks/_typeahead-BNULwihE.js +0 -36
  137. data/dist/chunks/_weekday_stacked-BKWemDAe.js +0 -45
  138. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_collapsible.md → _table_with_collapsible_react.md} +0 -0
@@ -1,230 +1,81 @@
1
- import React, { useState, useEffect } from "react";
2
- import classnames from "classnames";
1
+ import React, { useState, useEffect, useRef } from "react"
2
+ import classnames from "classnames"
3
3
 
4
4
  import {
5
5
  buildAriaProps,
6
6
  buildCss,
7
7
  buildDataProps,
8
8
  buildHtmlProps,
9
- } from "../utilities/props";
10
- import { globalProps, globalInlineProps } from "../utilities/globalProps";
11
-
12
- import { DialogContext } from "../pb_dialog/_dialog_context";
9
+ } from "../utilities/props"
10
+ import { globalProps, globalInlineProps } from "../utilities/globalProps"
11
+ import { DrawerContext } from "./context"
12
+ import { useBreakpoint } from "./hooks/useBreakpoint"
13
13
 
14
14
  type DrawerProps = {
15
- aria?: { [key: string]: string };
16
- behavior?: "floating" | "push";
17
- border?: "full" | "none" | "right" | "left";
18
- openBreakpoint?: "none" | "xs" | "sm" | "md" | "lg" | "xl";
19
- closeBreakpoint?: "none" | "xs" | "sm" | "md" | "lg" | "xl";
20
- children: React.ReactNode | React.ReactNode[] | string;
21
- className?: string;
22
- data?: { [key: string]: string };
23
- htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
24
- id?: string;
25
- fullHeight?: boolean;
26
- menuButtonID?: string;
27
- onClose?: () => void;
28
- opened: boolean;
29
- overlay: boolean;
30
- placement?: "left" | "right";
31
- size?: "xs" | "sm" | "md" | "lg" | "xl";
32
- text?: string;
33
- withinElement?: boolean;
34
- };
35
-
36
- const Drawer = (props: DrawerProps): React.ReactElement => {
15
+ aria?: { [key: string]: string }
16
+ behavior?: "floating" | "push"
17
+ border?: "full" | "none" | "right" | "left"
18
+ breakpoint?: "none" | "xs" | "sm" | "md" | "lg" | "xl"
19
+ children: React.ReactNode | React.ReactNode[] | string
20
+ className?: string
21
+ data?: { [key: string]: string }
22
+ htmlOptions?: { [key: string]: string | number | boolean | (() => void) }
23
+ id?: string
24
+ triggerId?: string
25
+ onClose?: () => void
26
+ opened: boolean
27
+ overlay: boolean
28
+ placement?: "left" | "right" | "top" | "bottom"
29
+ size?: "xs" | "sm" | "md" | "lg" | "xl" | "full"
30
+ text?: string
31
+ withinElement?: boolean
32
+ }
33
+
34
+ const Drawer = (props: DrawerProps): React.ReactElement | null => {
37
35
  const {
38
36
  aria = {},
39
37
  behavior = "floating",
40
38
  border = "none",
41
- openBreakpoint = "none",
42
- closeBreakpoint = "none",
39
+ breakpoint = "none",
43
40
  className,
44
41
  data = {},
45
42
  htmlOptions = {},
46
43
  id,
47
44
  size = "md",
48
45
  children,
49
- fullHeight = true,
50
- menuButtonID,
46
+ triggerId,
51
47
  opened,
52
48
  onClose,
53
49
  overlay = true,
54
50
  placement = "left",
55
51
  withinElement = false,
56
- } = props;
57
- const ariaProps = buildAriaProps(aria);
58
- const dataProps = buildDataProps(data);
59
- const htmlProps = buildHtmlProps(htmlOptions);
60
-
61
- let globalPropsString: string = globalProps(props);
62
-
63
- // Check if the string contains any of the prefixes
64
- const containsPrefix = [
65
- "p_",
66
- "pb_",
67
- "pt_",
68
- "pl_",
69
- "pr_",
70
- "px_",
71
- "py_",
72
- ].some((prefix) => globalPropsString.includes(prefix));
73
-
74
- // If none of the prefixes are found, append 'p_sm' to the string
75
- if (!containsPrefix) {
76
- globalPropsString += " p_sm";
77
- }
78
-
79
- const drawerClassNames = {
80
- base: `${classnames(
81
- "pb_drawer",
82
- buildCss("pb_drawer", size, placement),
83
- {
84
- drawer_border_full: border === "full",
85
- drawer_border_right: border === "right",
86
- drawer_border_left: border === "left",
87
- pb_drawer_within_element: withinElement,
88
- }
89
- )} ${globalPropsString}`,
90
- afterOpen: "pb_drawer_after_open",
91
- beforeClose: "pb_drawer_before_close",
92
- };
93
-
94
- const fullHeightClassNames = () => {
95
- if (!fullHeight) return null;
96
- return `full_height_${placement}`;
97
- };
98
-
99
- const overlayClassNames = {
100
- base: `pb_drawer${overlay ? "_overlay" : "_no_overlay"} ${
101
- fullHeight !== null && fullHeightClassNames()
102
- } ${!overlay ? "no-background" : ""}`,
103
- afterOpen: "pb_drawer_overlay_after_open",
104
- beforeClose: "pb_drawer_overlay_before_close",
105
- };
106
-
107
- const classes = classnames(buildCss("pb_drawer_wrapper"), className);
108
- const dynamicInlineProps = globalInlineProps(props)
109
- const [menuButtonOpened, setMenuButtonOpened] = useState(false);
110
- const [triggerOpened, setTriggerOpened] = useState(false);
111
-
112
- const breakpointWidths: Record<DrawerProps["openBreakpoint"], number> = {
113
- none: 0,
114
- xs: 575,
115
- sm: 768,
116
- md: 992,
117
- lg: 1200,
118
- xl: 1400,
119
- };
120
-
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);
132
-
133
- useEffect(() => {
134
- if (openBreakpoint === "none") return;
135
-
136
- const handleResize = () => {
137
- const width = window.innerWidth;
138
- const openBreakpointWidth = breakpointWidths[openBreakpoint];
139
-
140
- if (width <= openBreakpointWidth) {
141
- setIsOpenBreakpointOpen(true);
142
- } else {
143
- setIsOpenBreakpointOpen(false);
144
- setIsUserClosed(false); // Reset when the breakpoint condition changes
145
- }
146
- };
147
-
148
- window.addEventListener("resize", handleResize);
149
-
150
- // Call handler once on mount to set initial state
151
- handleResize();
152
-
153
- return () => {
154
- window.removeEventListener("resize", handleResize);
155
- };
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
- }
52
+ } = props
169
53
 
170
- window.addEventListener("resize", handleResize);
54
+ const drawerRef = useRef<HTMLDivElement>(null)
55
+ const [menuButtonOpened, setMenuButtonOpened] = useState(false)
56
+ const [shouldRender, setShouldRender] = useState(false)
57
+ const [isAnimating, setIsAnimating] = useState(false)
171
58
 
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
- }
59
+ const { isOpenBreakpointOpen, isUserClosed, setIsUserClosed } = useBreakpoint(
60
+ {
61
+ breakpoint: breakpoint,
62
+ triggerId,
191
63
  }
192
- }, [menuButtonID, isOpenBreakpointOpen]);
193
-
194
- // Reset isUserClosed when isBreakpointOpen changes
195
- useEffect(() => {
196
- if (isOpenBreakpointOpen) {
197
- setIsUserClosed(false);
198
- }
199
- }, [isOpenBreakpointOpen]);
64
+ )
200
65
 
201
66
  const modalIsOpened =
202
- (isOpenBreakpointOpen && !isUserClosed) || menuButtonOpened || opened;
203
-
204
- const [animationState, setAnimationState] = useState("");
205
-
206
- useEffect(() => {
207
- if (modalIsOpened) {
208
- setAnimationState("afterOpen");
209
- } else if (!modalIsOpened && animationState === "afterOpen") {
210
- setAnimationState("beforeClose");
211
- setTimeout(() => {
212
- setAnimationState("");
213
- }, 200);
214
- }
215
- }, [modalIsOpened]);
216
-
217
- const isModalVisible = modalIsOpened || animationState === "beforeClose";
67
+ (isOpenBreakpointOpen && !isUserClosed) || menuButtonOpened || opened
218
68
 
219
69
  useEffect(() => {
220
70
  if (withinElement) return;
221
71
 
222
- const sizeMap: Record<DrawerProps["size"], string> = {
72
+ const sizeMap: { [key: string]: string } = {
223
73
  xl: "365px",
224
74
  lg: "300px",
225
75
  md: "250px",
226
76
  sm: "200px",
227
77
  xs: "64px",
78
+ full: "100%",
228
79
  };
229
80
  const body = document.querySelector("body");
230
81
  if (modalIsOpened && behavior === "push" && body) {
@@ -239,103 +90,142 @@ const Drawer = (props: DrawerProps): React.ReactElement => {
239
90
  if (body.classList.contains("PBDrawer__Body--open")) {
240
91
  body.classList.add("PBDrawer__Body--close");
241
92
  }
242
- body.style.cssText = ""; // Clear the styles when modal is closed or behavior is not 'push'
93
+ body.style.cssText = "";
243
94
  body.classList.remove("PBDrawer__Body--open");
244
95
  }
245
- }, [modalIsOpened, behavior, placement, size, withinElement]);
96
+ }, [modalIsOpened]);
97
+
98
+ // Helper functions
99
+ const updateDrawerHeight = () => {
100
+ if (drawerRef.current) {
101
+ const height = drawerRef.current.scrollHeight;
102
+ drawerRef.current.style.setProperty('--drawer-height', `${height}px`);
103
+ }
104
+ }
105
+
106
+ useEffect(() => {
107
+ if (modalIsOpened) {
108
+ setShouldRender(true)
109
+ if (withinElement) {
110
+ const timer = setTimeout(() => {
111
+ updateDrawerHeight()
112
+ setIsAnimating(true)
113
+ }, 10)
114
+ return () => clearTimeout(timer)
115
+ } else {
116
+ setIsAnimating(true)
117
+ }
118
+ } else {
119
+ setIsAnimating(false)
120
+ const timer = setTimeout(() => {
121
+ setShouldRender(false)
122
+ }, 250)
123
+ return () => clearTimeout(timer)
124
+ }
125
+ }, [modalIsOpened])
126
+
127
+
128
+
129
+ const handleMenuButtonClick = () => {
130
+ if (modalIsOpened) {
131
+ setMenuButtonOpened(false)
132
+ setIsUserClosed(true)
133
+ } else {
134
+ setMenuButtonOpened(true)
135
+ setIsUserClosed(false)
136
+ }
137
+ }
138
+
139
+ // Setup menu button click handler
140
+ useEffect(() => {
141
+ if (!triggerId) return;
142
+
143
+ const menuButton = document.getElementById(triggerId)
144
+ if (menuButton) {
145
+ menuButton.addEventListener("click", handleMenuButtonClick)
146
+ return () => menuButton.removeEventListener("click", handleMenuButtonClick)
147
+ }
148
+ }, [modalIsOpened])
149
+
150
+ const ariaProps = buildAriaProps(aria)
151
+ const dataProps = buildDataProps(data)
152
+ const htmlProps = buildHtmlProps(htmlOptions)
153
+ const dynamicInlineProps = globalInlineProps(props)
154
+
155
+ const drawerClasses = classnames(
156
+ "pb_drawer",
157
+ buildCss("pb_drawer", size as string, placement as string),
158
+ {
159
+ "drawer_border-full": border === "full",
160
+ "drawer_border-right": border === "right",
161
+ "drawer_border-left": border === "left",
162
+ pb_drawer_within_element: withinElement,
163
+ pb_drawer_after_open: isAnimating,
164
+ pb_drawer_before_close: !isAnimating && shouldRender,
165
+ },
166
+ withinElement ? "shadow_none" : "shadow_deepest",
167
+ globalProps(props),
168
+ className
169
+ )
170
+
171
+ const overlayClasses = classnames(
172
+ `pb_drawer${overlay ? "_overlay" : "_no_overlay"}`,
173
+ `drawer_content_${placement}`,
174
+ !overlay && "no-background",
175
+ {
176
+ pb_drawer_overlay_after_open: isAnimating,
177
+ pb_drawer_overlay_before_close: !isAnimating && shouldRender,
178
+ }
179
+ )
246
180
 
247
181
  const api = {
248
182
  onClose: () => {
249
- if (menuButtonID) {
250
- setMenuButtonOpened(false);
183
+ if (triggerId) {
184
+ setMenuButtonOpened(false)
251
185
  }
252
- setIsUserClosed(true);
186
+ setIsUserClosed(true)
253
187
  if (onClose) {
254
- onClose();
188
+ onClose()
255
189
  }
256
190
  },
257
- };
191
+ }
258
192
 
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]);
193
+ const drawerContent = (
194
+ <div
195
+ className={drawerClasses}
196
+ onClick={(e) => e.stopPropagation()}
197
+ ref={drawerRef}
198
+ >
199
+ {children}
200
+ </div>
201
+ )
202
+
203
+ // Step 5: Only render when shouldRender is true
204
+ if (!shouldRender) return null
281
205
 
282
206
  return (
283
- <DialogContext.Provider value={api}>
207
+ <DrawerContext.Provider value={api}>
284
208
  {withinElement ? (
285
- isModalVisible && (
286
- <div
287
- {...ariaProps}
288
- {...dataProps}
289
- {...htmlProps}
290
- className={classnames(drawerClassNames.base, {
291
- [drawerClassNames.afterOpen]:
292
- animationState === "afterOpen",
293
- [drawerClassNames.beforeClose]:
294
- animationState === "beforeClose",
295
- })}
296
- id={id}
297
- onClick={(e) => e.stopPropagation()}
298
- style={dynamicInlineProps}
299
- >
300
- {children}
301
- </div>
302
- )
209
+ drawerContent
303
210
  ) : (
304
211
  <div
305
212
  {...ariaProps}
306
213
  {...dataProps}
307
214
  {...htmlProps}
308
- className={classes}
215
+ className={classnames(buildCss("pb_drawer_wrapper"), className)}
216
+ style={dynamicInlineProps}
309
217
  >
310
- {isModalVisible && (
311
- <div
312
- className={classnames(overlayClassNames.base, {
313
- [overlayClassNames.afterOpen]:
314
- animationState === "afterOpen",
315
- [overlayClassNames.beforeClose]:
316
- animationState === "beforeClose",
317
- })}
318
- id={id}
319
- onClick={overlay ? api.onClose : undefined}
320
- >
321
- <div
322
- className={classnames(drawerClassNames.base, {
323
- [drawerClassNames.afterOpen]:
324
- animationState === "afterOpen",
325
- [drawerClassNames.beforeClose]:
326
- animationState === "beforeClose",
327
- })}
328
- onClick={(e) => e.stopPropagation()}
329
- style={dynamicInlineProps}
330
- >
331
- {children}
332
- </div>
333
- </div>
334
- )}
218
+ <div
219
+ className={overlayClasses}
220
+ id={id}
221
+ onClick={overlay ? api.onClose : undefined}
222
+ >
223
+ {drawerContent}
224
+ </div>
335
225
  </div>
336
226
  )}
337
- </DialogContext.Provider>
338
- );
339
- };
227
+ </DrawerContext.Provider>
228
+ )
229
+ }
340
230
 
341
- export default Drawer;
231
+ export default Drawer
@@ -0,0 +1,11 @@
1
+ import React from 'react'
2
+
3
+ const noop = (): void => void 0
4
+
5
+ type DrawerContextType = {
6
+ onClose: () => void
7
+ }
8
+
9
+ export const DrawerContext = React.createContext<DrawerContextType>({
10
+ onClose: noop,
11
+ })
@@ -0,0 +1,38 @@
1
+ import React, { useState } from "react"
2
+ import { Button, Drawer, Flex } from "playbook-ui"
3
+
4
+ const useDrawer = (visible = false) => {
5
+ const [opened, setOpened] = useState(visible)
6
+ const toggle = () => setOpened(!opened)
7
+
8
+ return [opened, toggle]
9
+ }
10
+
11
+ const DrawerBehavior = () => {
12
+ const [drawerOpen, toggleDrawerOpen] = useDrawer()
13
+
14
+ return (
15
+ <>
16
+ <Flex wrap>
17
+ <Button id='sm'
18
+ marginRight='md'
19
+ onClick={toggleDrawerOpen}
20
+ >
21
+ {"Push Behavior"}
22
+ </Button>
23
+ </Flex>
24
+ <Flex>
25
+ <Drawer
26
+ behavior={"push"}
27
+ onClose={toggleDrawerOpen}
28
+ opened={drawerOpen}
29
+ size={"lg"}
30
+ >
31
+ Test me (Push Behavior)
32
+ </Drawer>
33
+ </Flex>
34
+ </>
35
+ )
36
+ }
37
+
38
+ export default DrawerBehavior
@@ -6,19 +6,15 @@ const DrawerBorders = () => {
6
6
  const [openedBRightDrawer, setOpenedBRightDrawer] = useState(false);
7
7
  const [openedBLeftDrawer, setOpenedBLeftDrawer] = useState(false);
8
8
  const [openedBFullDrawer, setOpenedBFullDrawer] = useState(false);
9
- const [openedBDefaultDrawer, setOpenedBDefaultDrawer] = useState(false);
10
- const [openedBRoundedDrawer, setOpenedBRoundedDrawer] = useState(false);
11
9
 
12
10
  // Toggle functions for each drawer
13
11
  const toggleBRightDrawer = () => setOpenedBRightDrawer(!openedBRightDrawer);
14
12
  const toggleBLeftDrawer = () => setOpenedBLeftDrawer(!openedBLeftDrawer);
15
13
  const toggleBFullDrawer = () => setOpenedBFullDrawer(!openedBFullDrawer);
16
- const toggleBDefaultDrawer = () => setOpenedBDefaultDrawer(!openedBDefaultDrawer);
17
- const toggleBRoundedDrawer = () => setOpenedBRoundedDrawer(!openedBRoundedDrawer);
18
14
 
19
15
  return (
20
16
  <>
21
- <Flex padding="md"
17
+ <Flex
22
18
  wrap
23
19
  >
24
20
  <Button marginRight="md"
@@ -36,23 +32,12 @@ const DrawerBorders = () => {
36
32
  >
37
33
  Drawer with border full
38
34
  </Button>
39
- <Button marginRight="md"
40
- onClick={toggleBDefaultDrawer}
41
- >
42
- Default Drawer
43
- </Button>
44
- <Button marginRight="md"
45
- onClick={toggleBRoundedDrawer}
46
- >
47
- Rounded Drawer
48
- </Button>
49
35
  </Flex>
50
36
 
51
37
  {/* Drawers for each size */}
52
38
  <Drawer
53
39
  behavior="float"
54
40
  border="right"
55
- fullHeight
56
41
  onClose={toggleBRightDrawer}
57
42
  opened={openedBRightDrawer}
58
43
  overlay={false}
@@ -64,11 +49,10 @@ const DrawerBorders = () => {
64
49
  <Drawer
65
50
  behavior="float"
66
51
  border="left"
67
- fullHeight
68
52
  onClose={toggleBLeftDrawer}
69
53
  opened={openedBLeftDrawer}
70
54
  overlay={false}
71
- placement="right"
55
+ placement="left"
72
56
  size="lg"
73
57
  >
74
58
  This is a Drawer with border left
@@ -76,40 +60,14 @@ const DrawerBorders = () => {
76
60
  <Drawer
77
61
  behavior="float"
78
62
  border="full"
79
- fullHeight
80
63
  onClose={toggleBFullDrawer}
81
64
  opened={openedBFullDrawer}
82
65
  overlay={false}
83
- placement="right"
66
+ placement="left"
84
67
  size="lg"
85
68
  >
86
69
  This is a Drawer with border full
87
70
  </Drawer>
88
- <Drawer
89
- behavior="float"
90
- fullHeight
91
- onClose={toggleBDefaultDrawer}
92
- opened={openedBDefaultDrawer}
93
- overlay={false}
94
- placement="right"
95
- size="lg"
96
- >
97
- This is a Default Drawer
98
- </Drawer>
99
- <Drawer
100
- behavior="float"
101
- borderRadius="rounded"
102
- fullHeight
103
- onClose={toggleBRoundedDrawer}
104
- opened={openedBRoundedDrawer}
105
- overlay={false}
106
- placement="right"
107
- size="lg"
108
- >
109
- <div style={{ paddingTop: '100px', paddingLeft: '12px' }}>
110
- This is a Rounded Drawer
111
- </div>
112
- </Drawer>
113
71
  </>
114
72
  );
115
73
  };
@@ -26,7 +26,6 @@ const DrawerBreakpoints = () => {
26
26
  <Drawer
27
27
  behavior={"push"}
28
28
  breakpoint="sm"
29
- fullHeight
30
29
  onClose={toggleSmallDrawer}
31
30
  opened={smallDrawerOpened}
32
31
  overlay={false}