playbook_ui 16.10.0.pre.rc.1 → 16.10.0.pre.rc.2

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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +2 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +5 -2
  4. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +27 -2
  5. data/app/pb_kits/playbook/pb_advanced_table/Utilities/StickyLayoutHelper.ts +100 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +35 -71
  7. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +27 -77
  8. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +7 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +50 -13
  10. data/app/pb_kits/playbook/pb_advanced_table/advanced_table_action_bar.js +31 -9
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling.jsx +2 -2
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.html.erb +36 -44
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.jsx +10 -19
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_rails.md +0 -4
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_react.md +3 -5
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.json +0 -7
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.overrides.json +0 -7
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +0 -1
  19. data/app/pb_kits/playbook/pb_advanced_table/index.js +20 -29
  20. data/app/pb_kits/playbook/pb_advanced_table/kit.schema.json +0 -12
  21. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +1 -1
  22. data/app/pb_kits/playbook/pb_badge/kit.schema.json +1 -1
  23. data/app/pb_kits/playbook/pb_button_toolbar/kit.schema.json +1 -1
  24. data/app/pb_kits/playbook/pb_checkbox/kit.schema.json +1 -1
  25. data/app/pb_kits/playbook/pb_circle_icon_button/kit.schema.json +1 -1
  26. data/app/pb_kits/playbook/pb_date_picker/kit.schema.json +1 -1
  27. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +1 -1
  28. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners_rails.md +1 -1
  29. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_independent_containers.html.erb +35 -0
  30. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_independent_containers_rails.md +8 -0
  31. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_rails.md +3 -1
  32. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_react.md +1 -1
  33. data/app/pb_kits/playbook/pb_draggable/docs/_playground.json +260 -19
  34. data/app/pb_kits/playbook/pb_draggable/docs/_playground.overrides.json +258 -13
  35. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +1 -0
  36. data/app/pb_kits/playbook/pb_draggable/index.js +10 -3
  37. data/app/pb_kits/playbook/pb_dropdown/docs/_playground.json +1 -0
  38. data/app/pb_kits/playbook/pb_file_upload/docs/_playground.json +2 -1
  39. data/app/pb_kits/playbook/pb_file_upload/kit.schema.json +2 -2
  40. data/app/pb_kits/playbook/pb_filter/_filter.tsx +27 -0
  41. data/app/pb_kits/playbook/pb_filter/docs/_playground.json +301 -5
  42. data/app/pb_kits/playbook/pb_filter/docs/_playground.overrides.json +312 -0
  43. data/app/pb_kits/playbook/pb_filter/kit.schema.json +88 -29
  44. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_playground.json +210 -14
  45. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_playground.overrides.json +231 -0
  46. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/kit.schema.json +1 -1
  47. data/app/pb_kits/playbook/pb_flex/docs/_playground.json +297 -38
  48. data/app/pb_kits/playbook/pb_flex/docs/_playground.overrides.json +300 -40
  49. data/app/pb_kits/playbook/pb_form/docs/_playground.json +1 -13
  50. data/app/pb_kits/playbook/pb_form_group/docs/_playground.json +1 -23
  51. data/app/pb_kits/playbook/pb_form_pill/docs/_playground.json +155 -14
  52. data/app/pb_kits/playbook/pb_form_pill/docs/_playground.overrides.json +147 -0
  53. data/app/pb_kits/playbook/pb_form_pill/kit.schema.json +1 -1
  54. data/app/pb_kits/playbook/pb_hashtag/docs/_playground.json +72 -11
  55. data/app/pb_kits/playbook/pb_hashtag/docs/_playground.overrides.json +75 -0
  56. data/app/pb_kits/playbook/pb_highlight/docs/_playground.json +75 -4
  57. data/app/pb_kits/playbook/pb_highlight/docs/_playground.overrides.json +75 -0
  58. data/app/pb_kits/playbook/pb_home_address_street/docs/_playground.json +138 -12
  59. data/app/pb_kits/playbook/pb_home_address_street/docs/_playground.overrides.json +162 -0
  60. data/app/pb_kits/playbook/pb_icon/docs/_playground.json +79 -40
  61. data/app/pb_kits/playbook/pb_icon/docs/_playground.overrides.json +96 -27
  62. data/app/pb_kits/playbook/pb_icon_button/docs/_playground.json +111 -9
  63. data/app/pb_kits/playbook/pb_icon_button/docs/_playground.overrides.json +131 -0
  64. data/app/pb_kits/playbook/pb_icon_button/kit.schema.json +1 -1
  65. data/app/pb_kits/playbook/pb_icon_circle/docs/_playground.json +92 -7
  66. data/app/pb_kits/playbook/pb_icon_circle/docs/_playground.overrides.json +108 -0
  67. data/app/pb_kits/playbook/pb_icon_stat_value/docs/_playground.json +32 -17
  68. data/app/pb_kits/playbook/pb_icon_stat_value/docs/_playground.overrides.json +81 -8
  69. data/app/pb_kits/playbook/pb_icon_value/docs/_playground.json +28 -18
  70. data/app/pb_kits/playbook/pb_icon_value/docs/_playground.overrides.json +58 -9
  71. data/app/pb_kits/playbook/pb_image/docs/_playground.json +124 -47
  72. data/app/pb_kits/playbook/pb_image/docs/_playground.overrides.json +122 -47
  73. data/app/pb_kits/playbook/pb_label_pill/docs/_playground.json +68 -6
  74. data/app/pb_kits/playbook/pb_label_pill/docs/_playground.overrides.json +85 -0
  75. data/app/pb_kits/playbook/pb_label_value/docs/_playground.json +59 -36
  76. data/app/pb_kits/playbook/pb_label_value/docs/_playground.overrides.json +101 -30
  77. data/app/pb_kits/playbook/pb_layout/docs/_playground.json +1 -40
  78. data/app/pb_kits/playbook/pb_legend/docs/_playground.json +60 -7
  79. data/app/pb_kits/playbook/pb_legend/docs/_playground.overrides.json +77 -0
  80. data/app/pb_kits/playbook/pb_list/docs/_playground.json +165 -17
  81. data/app/pb_kits/playbook/pb_list/docs/_playground.overrides.json +191 -0
  82. data/app/pb_kits/playbook/pb_loading_inline/docs/_playground.json +28 -1
  83. data/app/pb_kits/playbook/pb_loading_inline/docs/_playground.overrides.json +27 -1
  84. data/app/pb_kits/playbook/pb_map/docs/_playground.json +164 -7
  85. data/app/pb_kits/playbook/pb_map/docs/_playground.overrides.json +180 -0
  86. data/app/pb_kits/playbook/pb_message/docs/_playground.json +114 -8
  87. data/app/pb_kits/playbook/pb_message/docs/_playground.overrides.json +144 -0
  88. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +2 -2
  89. data/app/pb_kits/playbook/pb_multi_level_select/docs/_playground.json +310 -61
  90. data/app/pb_kits/playbook/pb_multi_level_select/docs/_playground.overrides.json +327 -44
  91. data/app/pb_kits/playbook/pb_multiple_users/docs/_playground.json +35 -6
  92. data/app/pb_kits/playbook/pb_multiple_users/docs/_playground.overrides.json +35 -6
  93. data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_playground.json +32 -21
  94. data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_playground.overrides.json +32 -21
  95. data/app/pb_kits/playbook/pb_nav/docs/_playground.json +546 -18
  96. data/app/pb_kits/playbook/pb_nav/docs/_playground.overrides.json +561 -14
  97. data/app/pb_kits/playbook/pb_online_status/docs/_playground.json +18 -23
  98. data/app/pb_kits/playbook/pb_online_status/docs/_playground.overrides.json +18 -14
  99. data/app/pb_kits/playbook/pb_overlay/docs/_playground.json +133 -14
  100. data/app/pb_kits/playbook/pb_overlay/docs/_playground.overrides.json +154 -0
  101. data/app/pb_kits/playbook/pb_pagination/docs/_playground.json +35 -14
  102. data/app/pb_kits/playbook/pb_pagination/docs/_playground.overrides.json +35 -14
  103. data/app/pb_kits/playbook/pb_passphrase/docs/_playground.json +129 -14
  104. data/app/pb_kits/playbook/pb_passphrase/docs/_playground.overrides.json +148 -0
  105. data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_playground.json +378 -4
  106. data/app/pb_kits/playbook/pb_pb_bar_graph/docs/_playground.overrides.json +245 -0
  107. data/app/pb_kits/playbook/pb_pb_bar_graph/kit.schema.json +1 -1
  108. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_playground.json +215 -4
  109. data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_playground.overrides.json +224 -0
  110. data/app/pb_kits/playbook/pb_pb_circle_chart/kit.schema.json +1 -1
  111. data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_playground.json +149 -4
  112. data/app/pb_kits/playbook/pb_pb_gauge_chart/docs/_playground.overrides.json +162 -0
  113. data/app/pb_kits/playbook/pb_pb_gauge_chart/kit.schema.json +1 -1
  114. data/app/pb_kits/playbook/pb_pb_line_graph/docs/_playground.json +392 -4
  115. data/app/pb_kits/playbook/pb_pb_line_graph/docs/_playground.overrides.json +212 -0
  116. data/app/pb_kits/playbook/pb_pb_line_graph/kit.schema.json +1 -1
  117. data/app/pb_kits/playbook/pb_person/docs/_playground.json +27 -11
  118. data/app/pb_kits/playbook/pb_person/docs/_playground.overrides.json +34 -9
  119. data/app/pb_kits/playbook/pb_person_contact/docs/_playground.json +72 -21
  120. data/app/pb_kits/playbook/pb_person_contact/docs/_playground.overrides.json +71 -21
  121. data/app/pb_kits/playbook/pb_phone_number_input/docs/_playground.json +179 -21
  122. data/app/pb_kits/playbook/pb_phone_number_input/docs/_playground.overrides.json +180 -0
  123. data/app/pb_kits/playbook/pb_phone_number_input/kit.schema.json +2 -2
  124. data/app/pb_kits/playbook/pb_pill/docs/_playground.json +16 -49
  125. data/app/pb_kits/playbook/pb_pill/docs/_playground.overrides.json +33 -30
  126. data/app/pb_kits/playbook/pb_popover/docs/_playground.json +155 -46
  127. data/app/pb_kits/playbook/pb_popover/docs/_playground.overrides.json +162 -30
  128. data/app/pb_kits/playbook/pb_progress_step/docs/_playground.json +1 -31
  129. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_playground.json +1 -44
  130. data/app/pb_kits/playbook/pb_select/_select.tsx +1 -0
  131. data/app/pb_kits/playbook/pb_select/kit.schema.json +1 -1
  132. data/app/pb_kits/playbook/pb_select/select.html.erb +1 -1
  133. data/app/pb_kits/playbook/pb_selectable_card/kit.schema.json +1 -1
  134. data/app/pb_kits/playbook/pb_selectable_card_icon/docs/_playground.json +1 -38
  135. data/app/pb_kits/playbook/pb_selectable_card_icon/kit.schema.json +1 -1
  136. data/app/pb_kits/playbook/pb_skeleton_loading/docs/_playground.json +1 -30
  137. data/app/pb_kits/playbook/pb_source/docs/_playground.json +1 -27
  138. data/app/pb_kits/playbook/pb_table/docs/_playground.json +1 -57
  139. data/app/pb_kits/playbook/pb_text_input/kit.schema.json +1 -1
  140. data/app/pb_kits/playbook/pb_textarea/kit.schema.json +1 -1
  141. data/app/pb_kits/playbook/pb_time_range_inline/docs/_playground.json +1 -32
  142. data/app/pb_kits/playbook/pb_timeline/docs/_playground.json +1 -27
  143. data/app/pb_kits/playbook/pb_toggle/kit.schema.json +1 -1
  144. data/app/pb_kits/playbook/pb_typeahead/kit.schema.json +1 -1
  145. data/dist/chunks/{_typeahead-CuXG_NFx.js → _typeahead-CbiY8rnB.js} +1 -1
  146. data/dist/chunks/time_picker_helper-CVMV9ync.js +1 -0
  147. data/dist/chunks/vendor.js +3 -3
  148. data/dist/playbook-rails-react-bindings.js +1 -1
  149. data/dist/playbook-rails.js +1 -1
  150. data/dist/playbook.css +1 -1
  151. data/lib/playbook/version.rb +1 -1
  152. metadata +27 -6
  153. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.jsx +0 -92
  154. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_fullscreen.md +0 -3
  155. data/dist/chunks/time_picker_helper-Bx8nzyM8.js +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0c56cffd7ae20d303e7ebfb111960cd77e6b3ef3020867b335b91ad0743ec88c
4
- data.tar.gz: 12ed387ffcb0607f46a4ef6f231bb7823b5b3c81f7a988783b8b652491ef29cf
3
+ metadata.gz: 9c106506aaabdf972085be91718db366bd7fedcd876fbb790451952f6be69f40
4
+ data.tar.gz: 658df9449e22d82fee8e4faeaa020c81876b6cbb435e399f1deeb3f9ab877426
5
5
  SHA512:
6
- metadata.gz: dc097cb2fe1d11fefe23ea335188808e0a15abcf214e0de13c7f8b6f1320974af4f1d33c813bf46c3650007ab0e903e838e91738ae8cb48c93c9875f28ccfc66
7
- data.tar.gz: 2ef66b6d238eb564c593ceb9eaad541f898a5bbad90afd2c834b53dfbcf4624ce56e350eae499b674f7cccece8ff40d1c50201838529782fbf330a92c920b86a
6
+ metadata.gz: 04f3e7df0c8f462350f090b3da1b59becb573547690516c09e9f7e4836ade7afb78cf8bbf635741fc9d61da70cb63263ce67d6e56e29450575f32c38dcec98fe
7
+ data.tar.gz: 8598d0d5d9884ae6bf320b3bd6538ef6db48edde4b853d4252aa20e9b6e5f4df5c5eb7e162a7d9ae0e139513ce5152fbcca5a8a0ae4f96cbca5b163a559a3865
@@ -136,6 +136,7 @@ export const RegularTableView = ({
136
136
  pinnedRows,
137
137
  headerHeight,
138
138
  rowHeight,
139
+ actionBarHeight,
139
140
  rowStyling = [],
140
141
  sampleRowRef,
141
142
  } = useContext(AdvancedTableContext)
@@ -172,7 +173,7 @@ export const RegularTableView = ({
172
173
  position: 'sticky',
173
174
  top:
174
175
  row.getIsPinned() === 'top'
175
- ? `${row.getPinnedIndex() * rowHeight + headerHeight}px`
176
+ ? `${row.getPinnedIndex() * rowHeight + headerHeight + actionBarHeight}px`
176
177
  : undefined,
177
178
  zIndex: '3'
178
179
  }}
@@ -17,6 +17,7 @@ import {
17
17
  showActionBar,
18
18
  hideActionBar,
19
19
  } from "../Utilities/ActionBarAnimationHelper";
20
+ import { scheduleStickyActionBarHeightUpdate } from "../Utilities/StickyLayoutHelper";
20
21
  import { GenericObject } from "../../types";
21
22
 
22
23
  interface TableActionBarProps {
@@ -39,7 +40,7 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
39
40
  type = "row-selection",
40
41
  }) => {
41
42
  const cardRef = useRef(null);
42
- const { table, columnVisibilityControl, columnDefinitions } =
43
+ const { table, columnVisibilityControl, columnDefinitions, tableContainerRef } =
43
44
  useContext(AdvancedTableContext);
44
45
 
45
46
  // ----------- Column visibility logic -----------
@@ -131,8 +132,10 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
131
132
  } else {
132
133
  hideActionBar(cardRef.current);
133
134
  }
135
+
136
+ scheduleStickyActionBarHeightUpdate(tableContainerRef?.current ?? null);
134
137
  }
135
- }, [isVisible, type]);
138
+ }, [isVisible, type, tableContainerRef]);
136
139
 
137
140
  const [showPopover, setShowPopover] = useState(false)
138
141
 
@@ -4,6 +4,7 @@ import { useVirtualizer } from '@tanstack/react-virtual';
4
4
  import { Row } from "@tanstack/react-table";
5
5
  import { GenericObject } from "../../types";
6
6
  import { getRowHeightEstimate } from '../Utilities/TableContainerStyles';
7
+ import { measureElementHeight } from '../Utilities/StickyLayoutHelper';
7
8
 
8
9
  const AdvancedTableContext = createContext<any>({});
9
10
 
@@ -30,8 +31,11 @@ export const AdvancedTableProvider = ({ children, ...props }: {
30
31
 
31
32
  const [headerHeight, setHeaderHeight] = useState(44);
32
33
  const [rowHeight, setRowHeight] = useState(38);
34
+ const [actionBarHeight, setActionBarHeight] = useState(0);
33
35
 
34
36
  const measureHeights = useCallback(() => {
37
+ const wrapper = (props.tableContainerRef?.current || tableContainerRef.current) as HTMLElement | null;
38
+
35
39
  if (headerRef.current) {
36
40
  const headerElement = headerRef.current as HTMLElement;
37
41
  const headerRect = headerElement.getBoundingClientRect();
@@ -45,7 +49,21 @@ export const AdvancedTableProvider = ({ children, ...props }: {
45
49
  setRowHeight(rowRect.height);
46
50
  }
47
51
  }
48
- }, []);
52
+
53
+ if (wrapper) {
54
+ const actionBar = wrapper.querySelector(
55
+ ".row-selection-actions-card.is-visible, .row-selection-actions-card.show-action-card"
56
+ ) as HTMLElement | null;
57
+ const measuredActionBarHeight = actionBar
58
+ ? measureElementHeight(actionBar)
59
+ : 0;
60
+ setActionBarHeight(measuredActionBarHeight);
61
+ wrapper.style.setProperty(
62
+ "--advanced-table-action-bar-height",
63
+ `${measuredActionBarHeight}px`
64
+ );
65
+ }
66
+ }, [props.tableContainerRef]);
49
67
 
50
68
  useEffect(() => {
51
69
  const resizeObserver = new ResizeObserver(() => {
@@ -56,6 +74,12 @@ export const AdvancedTableProvider = ({ children, ...props }: {
56
74
  resizeObserver.observe(headerRef.current);
57
75
  }
58
76
 
77
+ const wrapper = (props.tableContainerRef?.current || tableContainerRef.current) as HTMLElement | null;
78
+ const actionBar = wrapper?.querySelector(".row-selection-actions-card");
79
+ if (actionBar) {
80
+ resizeObserver.observe(actionBar);
81
+ }
82
+
59
83
  if (sampleRowRef.current) {
60
84
  resizeObserver.observe(sampleRowRef.current);
61
85
  }
@@ -72,7 +96,7 @@ export const AdvancedTableProvider = ({ children, ...props }: {
72
96
 
73
97
  useEffect(() => {
74
98
  measureHeights();
75
- }, [table?.getRowModel().rows.length, headerGroupCount, measureHeights]);
99
+ }, [table?.getRowModel().rows.length, headerGroupCount, props.isActionBarVisible, measureHeights]);
76
100
 
77
101
 
78
102
  // Create a flattened data array that includes ALL components for virtualization
@@ -202,6 +226,7 @@ export const AdvancedTableProvider = ({ children, ...props }: {
202
226
  keepPinnedRows: props.keepPinnedRows,
203
227
  headerHeight,
204
228
  rowHeight,
229
+ actionBarHeight,
205
230
  headerRef,
206
231
  sampleRowRef,
207
232
  measureHeights,
@@ -0,0 +1,100 @@
1
+ const VISIBLE_ACTION_BAR_SELECTOR =
2
+ ".row-selection-actions-card.is-visible, .row-selection-actions-card.show-action-card";
3
+
4
+ const ACTION_BAR_HEIGHT_TRANSITION_MS = 350;
5
+
6
+ export const measureElementHeight = (element: HTMLElement): number => {
7
+ const { height: rectHeight } = element.getBoundingClientRect();
8
+ const scrollHeight = element.scrollHeight;
9
+ const offsetHeight = element.offsetHeight;
10
+
11
+ return Math.ceil(Math.max(rectHeight, scrollHeight, offsetHeight));
12
+ };
13
+
14
+ export const updateStickyActionBarHeight = (
15
+ advancedTableWrapper: HTMLElement | null
16
+ ): number => {
17
+ if (!advancedTableWrapper) return 0;
18
+
19
+ const actionBar = advancedTableWrapper.querySelector(
20
+ VISIBLE_ACTION_BAR_SELECTOR
21
+ ) as HTMLElement | null;
22
+
23
+ if (!actionBar) {
24
+ advancedTableWrapper.style.setProperty(
25
+ "--advanced-table-action-bar-height",
26
+ "0px"
27
+ );
28
+ return 0;
29
+ }
30
+
31
+ const actionBarHeight = measureElementHeight(actionBar);
32
+
33
+ advancedTableWrapper.style.setProperty(
34
+ "--advanced-table-action-bar-height",
35
+ `${actionBarHeight}px`
36
+ );
37
+
38
+ return actionBarHeight;
39
+ };
40
+
41
+ export const scheduleStickyActionBarHeightUpdate = (
42
+ advancedTableWrapper: HTMLElement | null
43
+ ): void => {
44
+ if (!advancedTableWrapper) return;
45
+
46
+ updateStickyActionBarHeight(advancedTableWrapper);
47
+
48
+ requestAnimationFrame(() => {
49
+ updateStickyActionBarHeight(advancedTableWrapper);
50
+ requestAnimationFrame(() => {
51
+ updateStickyActionBarHeight(advancedTableWrapper);
52
+ });
53
+ });
54
+
55
+ window.setTimeout(() => {
56
+ updateStickyActionBarHeight(advancedTableWrapper);
57
+ }, ACTION_BAR_HEIGHT_TRANSITION_MS);
58
+ };
59
+
60
+ export const updateStickyHeaderRowHeights = (
61
+ advancedTableWrapper: HTMLElement | null
62
+ ): void => {
63
+ if (!advancedTableWrapper) return;
64
+
65
+ const table = advancedTableWrapper.querySelector("table.pb_table");
66
+ const thead = table?.querySelector("thead");
67
+ if (!thead) return;
68
+
69
+ const rows = Array.from(thead.querySelectorAll("tr"));
70
+ let totalHeight = 0;
71
+
72
+ rows.forEach((tr, index) => {
73
+ const height = tr.offsetHeight;
74
+ if (index === 0) {
75
+ advancedTableWrapper.style.setProperty(
76
+ "--advanced-table-header-row-0-height",
77
+ `${height}px`
78
+ );
79
+ } else if (index === 1) {
80
+ advancedTableWrapper.style.setProperty(
81
+ "--advanced-table-header-row-1-height",
82
+ `${height}px`
83
+ );
84
+ }
85
+ totalHeight += height;
86
+ });
87
+
88
+ advancedTableWrapper.style.setProperty(
89
+ "--advanced-table-header-height",
90
+ `${totalHeight}px`
91
+ );
92
+
93
+ updateStickyActionBarHeight(advancedTableWrapper);
94
+ };
95
+
96
+ export const updateStickyLayoutHeights = (
97
+ advancedTableWrapper: HTMLElement | null
98
+ ): void => {
99
+ updateStickyHeaderRowHeights(advancedTableWrapper);
100
+ };
@@ -364,6 +364,34 @@
364
364
  }
365
365
  }
366
366
 
367
+ &.advanced-table-sticky-header {
368
+ .row-selection-actions-card.show-action-card,
369
+ .row-selection-actions-card.is-visible {
370
+ background-color: $white;
371
+ left: 0;
372
+ position: sticky;
373
+ top: 0;
374
+ z-index: 5;
375
+ }
376
+
377
+ .pb_table.sticky-header {
378
+ thead,
379
+ .pb_advanced_table_header {
380
+ top: var(--advanced-table-action-bar-height, 0px);
381
+ z-index: 3;
382
+ }
383
+ }
384
+
385
+ &.hidden-action-bar {
386
+ .pb_table.sticky-header {
387
+ thead,
388
+ .pb_advanced_table_header {
389
+ top: 0;
390
+ }
391
+ }
392
+ }
393
+ }
394
+
367
395
  // Max height overflow - the below prevents expansion from overflowing container at full screen for responsive and nonresponsive tables
368
396
  &.advanced-table-max-height-xs {
369
397
  max-height: 320px;
@@ -401,55 +429,6 @@
401
429
  @include scrollbar-styling;
402
430
  }
403
431
 
404
- // Fullscreen
405
- &.advanced-table-allow-fullscreen {
406
- transition: all 0.3s ease;
407
- }
408
-
409
- &.advanced-table-fullscreen {
410
- background-color: $bg_light;
411
- box-sizing: border-box;
412
- height: 100vh;
413
- left: 0;
414
- overflow: auto;
415
- position: fixed;
416
- top: 0;
417
- width: 100%;
418
- z-index: $z_10;
419
-
420
- .pb_table {
421
- th,
422
- td,
423
- div,
424
- button {
425
- font-size: calc(100%);
426
- }
427
- box-sizing: border-box;
428
- margin: $space_lg;
429
- max-width: calc(100% - 64px);
430
- width: calc(100% - 64px);
431
- }
432
-
433
- .pb_table.sticky-header {
434
- thead,
435
- .pb_advanced_table_header {
436
- position: sticky !important;
437
- top: 44px !important;
438
- z-index: $z_10;
439
- }
440
- }
441
- }
442
-
443
- .advanced-table-fullscreen-header {
444
- background-color: $white;
445
- height: 44px;
446
- padding: 13px 20px;
447
- position: sticky;
448
- top: 0;
449
- width: 100%;
450
- z-index: $z_10;
451
- }
452
-
453
432
  // Icons
454
433
  .button-icon {
455
434
  display: flex;
@@ -507,16 +486,6 @@
507
486
  }
508
487
  }
509
488
 
510
- .fullscreen-icon {
511
- @extend .button-icon;
512
- @extend %primary-color-pseudo;
513
- padding: 2px 0;
514
-
515
- &:focus-visible {
516
- border-radius: $border_rad_lighter;
517
- }
518
- }
519
-
520
489
  // First column separator/border
521
490
  .table-header-cells:first-child,
522
491
  .table-header-cells-custom:first-child,
@@ -987,6 +956,13 @@
987
956
  background-color: $bg_dark_card;
988
957
  }
989
958
 
959
+ &.advanced-table-sticky-header {
960
+ .row-selection-actions-card.show-action-card,
961
+ .row-selection-actions-card.is-visible {
962
+ background-color: $bg_dark_card;
963
+ }
964
+ }
965
+
990
966
  .loading-toggle-icon,
991
967
  .loading-cell {
992
968
  &::after {
@@ -1002,18 +978,6 @@
1002
978
  }
1003
979
  }
1004
980
 
1005
- // Fullscreen
1006
- &.advanced-table-fullscreen {
1007
- background: $bg_dark;
1008
- }
1009
-
1010
- .advanced-table-fullscreen-header {
1011
- background-color: $bg_dark_card;
1012
- position: sticky;
1013
- top: 0;
1014
- z-index: $z_10;
1015
- }
1016
-
1017
981
  &[class*="advanced-table-sticky-left-columns"] {
1018
982
  .sticky-left {
1019
983
  background-color: $bg_dark;
@@ -1,4 +1,4 @@
1
- import React, { useRef, useEffect, useState, useCallback } from "react";
1
+ import React, { useRef, useEffect } from "react";
2
2
  import classnames from "classnames";
3
3
 
4
4
  import { GenericObject } from "../types";
@@ -18,15 +18,7 @@ import TableActionBar from "./Components/TableActionBar";
18
18
 
19
19
  import { useTableState } from "./Hooks/useTableState";
20
20
  import { useTableActions } from "./Hooks/useTableActions";
21
-
22
- import Card from "../pb_card/_card"
23
- import Flex from "../pb_flex/_flex"
24
- import Icon from "../pb_icon/_icon"
25
-
26
- type FullscreenControls = {
27
- toggleFullscreen: () => void;
28
- isFullscreen: boolean;
29
- };
21
+ import { updateStickyLayoutHeights, scheduleStickyActionBarHeightUpdate } from "./Utilities/StickyLayoutHelper";
30
22
 
31
23
  type AdvancedTableProps = {
32
24
  aria?: { [key: string]: string }
@@ -74,8 +66,6 @@ type AdvancedTableProps = {
74
66
  onRowSelectionChange?: (arg: RowSelectionState) => void
75
67
  onCustomSortClick?: (arg: GenericObject[]) => void
76
68
  virtualizedRows?: boolean
77
- allowFullScreen?: boolean
78
- fullScreenControl?: (controls: FullscreenControls) => void
79
69
  } & GlobalProps;
80
70
 
81
71
  /**
@@ -135,8 +125,6 @@ const AdvancedTable = (props: AdvancedTableProps) => {
135
125
  toggleExpansionIcon = "arrows-from-line",
136
126
  onRowSelectionChange,
137
127
  virtualizedRows = false,
138
- allowFullScreen = false,
139
- fullScreenControl,
140
128
  } = props;
141
129
 
142
130
  const noTableCardContainer = tableProps?.container === false;
@@ -214,87 +202,51 @@ const AdvancedTable = (props: AdvancedTableProps) => {
214
202
  );
215
203
  }, [fetchMoreOnBottomReached, fetchNextPage, isFetching, totalFetched, fullData.length]);
216
204
 
217
- // Fullscreen
218
- const [isFullscreen, setIsFullscreen] = useState(false)
205
+ // Build CSS classes and props
206
+ const ariaProps = buildAriaProps(aria);
207
+ const dataProps = buildDataProps(data);
208
+ const htmlProps = buildHtmlProps(htmlOptions);
219
209
 
220
- const toggleFullscreen = useCallback(() => {
221
- setIsFullscreen(prevState => !prevState)
222
- }, [])
210
+ // Visibility flag for action bar
211
+ const isActionBarVisible = (selectableRows && showActionsBar && selectedRowsLength > 0) || columnVisibilityControl;
212
+ const isStickyHeader = Boolean(tableProps?.sticky);
223
213
 
224
214
  useEffect(() => {
225
- if (allowFullScreen && fullScreenControl) {
226
- fullScreenControl({
227
- toggleFullscreen,
228
- isFullscreen
229
- })
230
- }
231
- }, [allowFullScreen, fullScreenControl, toggleFullscreen, isFullscreen])
215
+ if (!isStickyHeader || !tableWrapperRef.current) return;
232
216
 
233
- const renderFullscreenHeader = () => {
234
- if (!isFullscreen) return null
217
+ const wrapper = tableWrapperRef.current;
218
+ const updateHeights = () => updateStickyLayoutHeights(wrapper);
235
219
 
236
- const defaultMinimizeIcon = (
237
- <button
238
- className="gray-icon fullscreen-icon"
239
- onClick={toggleFullscreen}
240
- >
241
- <Icon
242
- cursor="pointer"
243
- fixedWidth
244
- icon="arrow-down-left-and-arrow-up-right-to-center"
245
- {...props}
246
- />
247
- </button>
248
- )
249
-
250
- return (
251
- <Card
252
- borderNone
253
- borderRadius="none"
254
- className="advanced-table-fullscreen-header"
255
- {...props}
256
- >
257
- <Flex justify="end">
258
- {defaultMinimizeIcon}
259
- </Flex>
260
- </Card>
261
- )
262
- }
220
+ updateHeights();
221
+ scheduleStickyActionBarHeightUpdate(wrapper);
263
222
 
264
- useEffect(() => {
265
- if (!allowFullScreen) return
223
+ const resizeObserver = new ResizeObserver(updateHeights);
224
+ resizeObserver.observe(wrapper);
266
225
 
267
- const handleKeyDown = (event: KeyboardEvent) => {
268
- if (event.key === 'Escape' && isFullscreen) {
269
- event.preventDefault()
270
- toggleFullscreen()
271
- }
226
+ const actionBar = wrapper.querySelector(".row-selection-actions-card");
227
+ if (actionBar) {
228
+ resizeObserver.observe(actionBar);
272
229
  }
273
- document.addEventListener('keydown', handleKeyDown)
274
- return () => {
275
- document.removeEventListener('keydown', handleKeyDown)
276
- }
277
- }, [allowFullScreen, toggleFullscreen, isFullscreen])
278
230
 
279
- // Build CSS classes and props
280
- const ariaProps = buildAriaProps(aria);
281
- const dataProps = buildDataProps(data);
282
- const htmlProps = buildHtmlProps(htmlOptions);
231
+ const table = wrapper.querySelector("table.pb_table");
232
+ const thead = table?.querySelector("thead");
233
+ if (thead) {
234
+ resizeObserver.observe(thead);
235
+ }
283
236
 
284
- // Visibility flag for action bar
285
- const isActionBarVisible = (selectableRows && showActionsBar && selectedRowsLength > 0) || columnVisibilityControl;
237
+ return () => resizeObserver.disconnect();
238
+ }, [isStickyHeader, isActionBarVisible, columnDefinitions, tableData]);
286
239
 
287
240
  const classes = classnames(
288
241
  buildCss("pb_advanced_table"),
289
242
  `advanced-table-responsive-${responsive}`,
290
243
  maxHeight ? `advanced-table-max-height-${maxHeight}` : '',
291
244
  {
292
- 'advanced-table-fullscreen': isFullscreen,
293
- 'advanced-table-allow-fullscreen': allowFullScreen,
294
245
  // Add the hidden-action-bar class when action bar functionality exists but is not visible
295
246
  'hidden-action-bar': (selectableRows || columnVisibilityControl) && !isActionBarVisible,
296
247
  },
297
248
  {'advanced-table-sticky-left-columns': stickyLeftColumn && stickyLeftColumn.length > 0},
249
+ { 'advanced-table-sticky-header': isStickyHeader },
298
250
  { 'advanced-table-no-table-container': noTableCardContainer },
299
251
  columnGroupBorderColor ? `column-group-border-${columnGroupBorderColor}` : '',
300
252
  scrollBarNone ? 'advanced-table-hide-scrollbar' : '',
@@ -358,7 +310,6 @@ const AdvancedTable = (props: AdvancedTableProps) => {
358
310
  ref={tableWrapperRef}
359
311
  style={tableWrapperStyle as React.CSSProperties}
360
312
  >
361
- {renderFullscreenHeader()}
362
313
  <AdvancedTableProvider
363
314
  cascadeCollapse={cascadeCollapse}
364
315
  columnDefinitions={columnDefinitions}
@@ -375,7 +326,6 @@ const AdvancedTable = (props: AdvancedTableProps) => {
375
326
  hasAnySubRows={hasAnySubRows}
376
327
  inlineRowLoading={inlineRowLoading}
377
328
  isActionBarVisible={isActionBarVisible}
378
- isFullscreen={isFullscreen}
379
329
  loading={loading}
380
330
  onCustomSortClick={onCustomSortClick}
381
331
  onExpandByDepthClick={onExpandByDepthClick}
@@ -46,6 +46,7 @@ module Playbook
46
46
  max_height_classname,
47
47
  hide_scroll_bar_class,
48
48
  hidden_action_bar_class,
49
+ sticky_header_class,
49
50
  ]
50
51
  additional_classes << "column-group-border-#{column_group_border_color}" if column_group_border_color != "none"
51
52
  additional_classes << "advanced-table-no-table-container" if no_table_card_container?
@@ -75,6 +76,12 @@ module Playbook
75
76
  selectable_rows && !is_action_bar_visible ? "hidden-action-bar" : ""
76
77
  end
77
78
 
79
+ def sticky_header_class
80
+ return "" unless table_props.is_a?(Hash)
81
+
82
+ table_props[:sticky] || table_props["sticky"] ? "advanced-table-sticky-header" : ""
83
+ end
84
+
78
85
  def selected_rows
79
86
  @selected_rows ||= []
80
87
  end
@@ -418,6 +418,56 @@ test("tableProps prop functions as expected", () => {
418
418
  const kit = screen.getByTestId(testId)
419
419
  const table = kit.querySelector('table')
420
420
  expect(table).toHaveClass("pb_table table-sm table-responsive-none data_table sticky-header ns_tabular")
421
+ expect(kit).toHaveClass("advanced-table-sticky-header")
422
+ })
423
+
424
+ test("sticky header with column visibility control offsets layout heights", async () => {
425
+ const columnDefsWithIds = columnDefinitions.map((col) => ({
426
+ ...col,
427
+ id: col.accessor,
428
+ }))
429
+
430
+ render(
431
+ <AdvancedTable
432
+ columnDefinitions={columnDefsWithIds}
433
+ columnVisibilityControl={{ default: true }}
434
+ data={{ testid: testId }}
435
+ responsive="none"
436
+ tableData={MOCK_DATA}
437
+ tableProps={{ sticky: true }}
438
+ />
439
+ )
440
+
441
+ const kit = screen.getByTestId(testId)
442
+ expect(kit).toHaveClass("advanced-table-sticky-header")
443
+ expect(kit).not.toHaveClass("hidden-action-bar")
444
+
445
+ const actionBar = kit.querySelector(".row-selection-actions-card.show-action-card")
446
+ expect(actionBar).toBeInTheDocument()
447
+
448
+ await waitFor(() => {
449
+ expect(kit.style.getPropertyValue("--advanced-table-action-bar-height")).toMatch(/^\d+px$/)
450
+ })
451
+ })
452
+
453
+ test("sticky header without column visibility control keeps zero action bar offset", async () => {
454
+ render(
455
+ <AdvancedTable
456
+ columnDefinitions={columnDefinitions}
457
+ data={{ testid: testId }}
458
+ responsive="none"
459
+ tableData={MOCK_DATA}
460
+ tableProps={{ sticky: true }}
461
+ />
462
+ )
463
+
464
+ const kit = screen.getByTestId(testId)
465
+ expect(kit).toHaveClass("advanced-table-sticky-header")
466
+ expect(kit).not.toHaveClass("hidden-action-bar")
467
+
468
+ await waitFor(() => {
469
+ expect(kit.style.getPropertyValue("--advanced-table-action-bar-height")).toBe("0px")
470
+ })
421
471
  })
422
472
 
423
473
  test("enableExpansionIcon changes icon", () => {
@@ -646,19 +696,6 @@ test("customRenderer prop functions as expected", () => {
646
696
  expect(pill).toBeInTheDocument()
647
697
  })
648
698
 
649
- test("allowFullScreen prop adds fullscreen class", () => {
650
- render(
651
- <AdvancedTable
652
- allowFullScreen
653
- columnDefinitions={columnDefinitions}
654
- tableData={MOCK_DATA}
655
- />
656
- )
657
-
658
- const tableContainer = screen.getByRole("table").closest("div")
659
- expect(tableContainer).toHaveClass("advanced-table-allow-fullscreen")
660
- })
661
-
662
699
  test("pinnedRows prop renders pinned rows at top", () => {
663
700
  const pinnedRowsControl = {
664
701
  value: { top: ["1", "3"] },