@patternfly/react-core 6.7.0-prerelease.3 → 6.7.0-prerelease.4

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 (165) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/components/package.json +1 -1
  3. package/deprecated/package.json +1 -1
  4. package/dist/dynamic/components/AboutModal/package.json +1 -1
  5. package/dist/dynamic/components/Accordion/package.json +1 -1
  6. package/dist/dynamic/components/ActionList/package.json +1 -1
  7. package/dist/dynamic/components/Alert/package.json +1 -1
  8. package/dist/dynamic/components/Avatar/package.json +1 -1
  9. package/dist/dynamic/components/BackToTop/package.json +1 -1
  10. package/dist/dynamic/components/Backdrop/package.json +1 -1
  11. package/dist/dynamic/components/BackgroundImage/package.json +1 -1
  12. package/dist/dynamic/components/Badge/package.json +1 -1
  13. package/dist/dynamic/components/Banner/package.json +1 -1
  14. package/dist/dynamic/components/Brand/package.json +1 -1
  15. package/dist/dynamic/components/Breadcrumb/package.json +1 -1
  16. package/dist/dynamic/components/Button/package.json +1 -1
  17. package/dist/dynamic/components/CalendarMonth/package.json +1 -1
  18. package/dist/dynamic/components/Card/package.json +1 -1
  19. package/dist/dynamic/components/Checkbox/package.json +1 -1
  20. package/dist/dynamic/components/ClipboardCopy/package.json +1 -1
  21. package/dist/dynamic/components/CodeBlock/package.json +1 -1
  22. package/dist/dynamic/components/Compass/package.json +1 -1
  23. package/dist/dynamic/components/Content/package.json +1 -1
  24. package/dist/dynamic/components/DataList/package.json +1 -1
  25. package/dist/dynamic/components/DatePicker/package.json +1 -1
  26. package/dist/dynamic/components/DescriptionList/package.json +1 -1
  27. package/dist/dynamic/components/Divider/package.json +1 -1
  28. package/dist/dynamic/components/Drawer/package.json +1 -1
  29. package/dist/dynamic/components/Dropdown/package.json +1 -1
  30. package/dist/dynamic/components/DualListSelector/package.json +1 -1
  31. package/dist/dynamic/components/EmptyState/package.json +1 -1
  32. package/dist/dynamic/components/ExpandableSection/package.json +1 -1
  33. package/dist/dynamic/components/FileUpload/package.json +1 -1
  34. package/dist/dynamic/components/Form/package.json +1 -1
  35. package/dist/dynamic/components/FormSelect/package.json +1 -1
  36. package/dist/dynamic/components/HelperText/package.json +1 -1
  37. package/dist/dynamic/components/Hero/package.json +1 -1
  38. package/dist/dynamic/components/Hint/package.json +1 -1
  39. package/dist/dynamic/components/Icon/package.json +1 -1
  40. package/dist/dynamic/components/InputGroup/package.json +1 -1
  41. package/dist/dynamic/components/JumpLinks/package.json +1 -1
  42. package/dist/dynamic/components/Label/package.json +1 -1
  43. package/dist/dynamic/components/List/package.json +1 -1
  44. package/dist/dynamic/components/LoginPage/package.json +1 -1
  45. package/dist/dynamic/components/Masthead/package.json +1 -1
  46. package/dist/dynamic/components/Menu/package.json +1 -1
  47. package/dist/dynamic/components/MenuToggle/package.json +1 -1
  48. package/dist/dynamic/components/Modal/package.json +1 -1
  49. package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
  50. package/dist/dynamic/components/Nav/package.json +1 -1
  51. package/dist/dynamic/components/NotificationBadge/package.json +1 -1
  52. package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
  53. package/dist/dynamic/components/NumberInput/package.json +1 -1
  54. package/dist/dynamic/components/OverflowMenu/package.json +1 -1
  55. package/dist/dynamic/components/Page/package.json +1 -1
  56. package/dist/dynamic/components/Pagination/package.json +1 -1
  57. package/dist/dynamic/components/Panel/package.json +1 -1
  58. package/dist/dynamic/components/Popover/package.json +1 -1
  59. package/dist/dynamic/components/Progress/package.json +1 -1
  60. package/dist/dynamic/components/ProgressStepper/package.json +1 -1
  61. package/dist/dynamic/components/Radio/package.json +1 -1
  62. package/dist/dynamic/components/SearchInput/package.json +1 -1
  63. package/dist/dynamic/components/Select/package.json +1 -1
  64. package/dist/dynamic/components/Sidebar/package.json +1 -1
  65. package/dist/dynamic/components/SimpleList/package.json +1 -1
  66. package/dist/dynamic/components/Skeleton/package.json +1 -1
  67. package/dist/dynamic/components/SkipToContent/package.json +1 -1
  68. package/dist/dynamic/components/Slider/package.json +1 -1
  69. package/dist/dynamic/components/Spinner/package.json +1 -1
  70. package/dist/dynamic/components/Switch/package.json +1 -1
  71. package/dist/dynamic/components/Tabs/package.json +1 -1
  72. package/dist/dynamic/components/TextArea/package.json +1 -1
  73. package/dist/dynamic/components/TextInput/package.json +1 -1
  74. package/dist/dynamic/components/TextInputGroup/package.json +1 -1
  75. package/dist/dynamic/components/TimePicker/package.json +1 -1
  76. package/dist/dynamic/components/Timestamp/package.json +1 -1
  77. package/dist/dynamic/components/Title/package.json +1 -1
  78. package/dist/dynamic/components/ToggleGroup/package.json +1 -1
  79. package/dist/dynamic/components/Toolbar/package.json +1 -1
  80. package/dist/dynamic/components/Tooltip/package.json +1 -1
  81. package/dist/dynamic/components/TreeView/package.json +1 -1
  82. package/dist/dynamic/components/Truncate/package.json +1 -1
  83. package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
  84. package/dist/dynamic/components/Wizard/package.json +1 -1
  85. package/dist/dynamic/deprecated/components/Chip/package.json +1 -1
  86. package/dist/dynamic/deprecated/components/DragDrop/package.json +1 -1
  87. package/dist/dynamic/deprecated/components/DualListSelector/package.json +1 -1
  88. package/dist/dynamic/deprecated/components/Modal/package.json +1 -1
  89. package/dist/dynamic/deprecated/components/Tile/package.json +1 -1
  90. package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
  91. package/dist/dynamic/deprecated/components/package.json +1 -1
  92. package/dist/dynamic/helpers/AnimationsProvider/AnimationsProvider/package.json +1 -1
  93. package/dist/dynamic/helpers/AnimationsProvider/package.json +1 -1
  94. package/dist/dynamic/helpers/FocusTrap/FocusTrap/package.json +1 -1
  95. package/dist/dynamic/helpers/GenerateId/GenerateId/package.json +1 -1
  96. package/dist/dynamic/helpers/KeyboardHandler/package.json +1 -1
  97. package/dist/dynamic/helpers/OUIA/ouia/package.json +1 -1
  98. package/dist/dynamic/helpers/Popper/Popper/package.json +1 -1
  99. package/dist/dynamic/helpers/SSRSafeIds/SSRSafeIds/package.json +1 -1
  100. package/dist/dynamic/helpers/constants/package.json +1 -1
  101. package/dist/dynamic/helpers/datetimeUtils/package.json +1 -1
  102. package/dist/dynamic/helpers/fileUtils/package.json +1 -1
  103. package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
  104. package/dist/dynamic/helpers/inert/package.json +1 -1
  105. package/dist/dynamic/helpers/package.json +1 -1
  106. package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
  107. package/dist/dynamic/helpers/typeUtils/package.json +1 -1
  108. package/dist/dynamic/helpers/useInterval/package.json +1 -1
  109. package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
  110. package/dist/dynamic/helpers/useSSRSafeId/package.json +1 -1
  111. package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
  112. package/dist/dynamic/helpers/util/package.json +1 -1
  113. package/dist/dynamic/layouts/Bullseye/package.json +1 -1
  114. package/dist/dynamic/layouts/Flex/package.json +1 -1
  115. package/dist/dynamic/layouts/Gallery/package.json +1 -1
  116. package/dist/dynamic/layouts/Grid/package.json +1 -1
  117. package/dist/dynamic/layouts/Level/package.json +1 -1
  118. package/dist/dynamic/layouts/Split/package.json +1 -1
  119. package/dist/dynamic/layouts/Stack/package.json +1 -1
  120. package/dist/dynamic/styles/package.json +1 -1
  121. package/dist/esm/components/Toolbar/Toolbar.d.ts +11 -1
  122. package/dist/esm/components/Toolbar/Toolbar.d.ts.map +1 -1
  123. package/dist/esm/components/Toolbar/Toolbar.js +60 -20
  124. package/dist/esm/components/Toolbar/Toolbar.js.map +1 -1
  125. package/dist/esm/components/Toolbar/ToolbarItem.d.ts +1 -0
  126. package/dist/esm/components/Toolbar/ToolbarItem.d.ts.map +1 -1
  127. package/dist/esm/components/Toolbar/ToolbarItem.js.map +1 -1
  128. package/dist/esm/components/Toolbar/ToolbarToggleGroup.d.ts +1 -1
  129. package/dist/esm/components/Toolbar/ToolbarToggleGroup.d.ts.map +1 -1
  130. package/dist/esm/components/Toolbar/ToolbarToggleGroup.js +9 -9
  131. package/dist/esm/components/Toolbar/ToolbarToggleGroup.js.map +1 -1
  132. package/dist/esm/components/Toolbar/ToolbarUtils.d.ts +4 -0
  133. package/dist/esm/components/Toolbar/ToolbarUtils.d.ts.map +1 -1
  134. package/dist/esm/components/Toolbar/ToolbarUtils.js.map +1 -1
  135. package/dist/js/components/Toolbar/Toolbar.d.ts +11 -1
  136. package/dist/js/components/Toolbar/Toolbar.d.ts.map +1 -1
  137. package/dist/js/components/Toolbar/Toolbar.js +59 -19
  138. package/dist/js/components/Toolbar/Toolbar.js.map +1 -1
  139. package/dist/js/components/Toolbar/ToolbarItem.d.ts +1 -0
  140. package/dist/js/components/Toolbar/ToolbarItem.d.ts.map +1 -1
  141. package/dist/js/components/Toolbar/ToolbarItem.js.map +1 -1
  142. package/dist/js/components/Toolbar/ToolbarToggleGroup.d.ts +1 -1
  143. package/dist/js/components/Toolbar/ToolbarToggleGroup.d.ts.map +1 -1
  144. package/dist/js/components/Toolbar/ToolbarToggleGroup.js +8 -8
  145. package/dist/js/components/Toolbar/ToolbarToggleGroup.js.map +1 -1
  146. package/dist/js/components/Toolbar/ToolbarUtils.d.ts +4 -0
  147. package/dist/js/components/Toolbar/ToolbarUtils.d.ts.map +1 -1
  148. package/dist/js/components/Toolbar/ToolbarUtils.js.map +1 -1
  149. package/dist/styles/base-no-reset.css +1 -1
  150. package/dist/styles/base.css +1 -1
  151. package/dist/umd/assets/{output-DjqlL2o3.css → output-DDYpZoPY.css} +19785 -19770
  152. package/dist/umd/react-core.min.js +3 -3
  153. package/helpers/package.json +1 -1
  154. package/layouts/package.json +1 -1
  155. package/next/package.json +1 -1
  156. package/package.json +6 -6
  157. package/src/components/Toolbar/Toolbar.tsx +120 -57
  158. package/src/components/Toolbar/ToolbarItem.tsx +1 -0
  159. package/src/components/Toolbar/ToolbarToggleGroup.tsx +10 -9
  160. package/src/components/Toolbar/ToolbarUtils.tsx +4 -0
  161. package/src/components/Toolbar/__tests__/Toolbar.test.tsx +38 -0
  162. package/src/components/Toolbar/__tests__/ToolbarToggleGroup.test.tsx +22 -1
  163. package/src/components/Toolbar/examples/Toolbar.md +16 -0
  164. package/src/components/Toolbar/examples/ToolbarContainerQuery.css +8 -0
  165. package/src/components/Toolbar/examples/ToolbarContainerQuery.tsx +35 -0
@@ -1 +1 @@
1
- {"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.7.0-prerelease.2","private":true}
1
+ {"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.7.0-prerelease.3","private":true}
@@ -1 +1 @@
1
- {"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.7.0-prerelease.2","private":true}
1
+ {"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.7.0-prerelease.3","private":true}
package/next/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.7.0-prerelease.2","private":true}
1
+ {"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.7.0-prerelease.3","private":true}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "6.7.0-prerelease.3",
3
+ "version": "6.7.0-prerelease.4",
4
4
  "description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
5
5
  "main": "dist/js/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -46,15 +46,15 @@
46
46
  "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json"
47
47
  },
48
48
  "dependencies": {
49
- "@patternfly/react-icons": "^6.7.0-prerelease.1",
50
- "@patternfly/react-styles": "^6.7.0-prerelease.1",
51
- "@patternfly/react-tokens": "^6.7.0-prerelease.2",
49
+ "@patternfly/react-icons": "^6.7.0-prerelease.2",
50
+ "@patternfly/react-styles": "^6.7.0-prerelease.2",
51
+ "@patternfly/react-tokens": "^6.7.0-prerelease.3",
52
52
  "focus-trap": "7.6.6",
53
53
  "react-dropzone": "^14.3.5",
54
54
  "tslib": "^2.8.1"
55
55
  },
56
56
  "devDependencies": {
57
- "@patternfly/patternfly": "6.6.0-prerelease.50",
57
+ "@patternfly/patternfly": "6.7.0-prerelease.1",
58
58
  "case-anything": "^3.1.2",
59
59
  "css": "^3.0.0",
60
60
  "fs-extra": "^11.3.3"
@@ -63,5 +63,5 @@
63
63
  "react": "^17 || ^18 || ^19",
64
64
  "react-dom": "^17 || ^18 || ^19"
65
65
  },
66
- "gitHead": "32056428bd221fb8009157d7f7d29bae84f7fe3f"
66
+ "gitHead": "59fa2ced55ee25977627a4ee87024e65702eefa5"
67
67
  }
@@ -3,7 +3,8 @@ import styles from '@patternfly/react-styles/css/components/Toolbar/toolbar';
3
3
  import { css } from '@patternfly/react-styles';
4
4
  import { ToolbarContext } from './ToolbarUtils';
5
5
  import { ToolbarLabelGroupContent } from './ToolbarLabelGroupContent';
6
- import { formatBreakpointMods, canUseDOM } from '../../helpers/util';
6
+ import { formatBreakpointMods, canUseDOM, getBreakpoint } from '../../helpers/util';
7
+ import { getResizeObserver } from '../../helpers/resizeObserver';
7
8
  import { getOUIAProps, OUIAProps } from '../../helpers';
8
9
  import { SSRSafeIds } from '../../helpers/SSRSafeIds/SSRSafeIds';
9
10
  import { PageContext } from '../Page/PageContext';
@@ -34,6 +35,8 @@ export interface ToolbarProps extends React.HTMLProps<HTMLDivElement>, OUIAProps
34
35
  children?: React.ReactNode;
35
36
  /** Id of the data toolbar */
36
37
  id?: string;
38
+ /** Flag indicating if the toolbar is a container for CSS container queries */
39
+ isContainer?: boolean;
37
40
  /** Flag indicating the toolbar height should expand to the full height of the container */
38
41
  isFullHeight?: boolean;
39
42
  /** Flag indicating the toolbar is static */
@@ -84,6 +87,9 @@ interface FilterInfo {
84
87
  class Toolbar extends Component<ToolbarProps, ToolbarState> {
85
88
  static displayName = 'Toolbar';
86
89
  labelGroupContentRef = createRef<HTMLDivElement>();
90
+ toolbarRef = createRef<HTMLDivElement>();
91
+ resizeObserver: () => void = () => {};
92
+ containerBreakpoint: ReturnType<typeof getBreakpoint>;
87
93
  staticFilterInfo = {};
88
94
  hasNoPadding = false;
89
95
  state = {
@@ -100,8 +106,8 @@ class Toolbar extends Component<ToolbarProps, ToolbarState> {
100
106
  }));
101
107
  };
102
108
 
103
- closeExpandableContent = (e: any) => {
104
- if (e.target.innerWidth !== this.state.windowWidth) {
109
+ closeExpandableContent = (e?: any) => {
110
+ if (e && e.target.innerWidth !== this.state.windowWidth) {
105
111
  this.setState(() => ({
106
112
  isManagedToggleExpanded: false,
107
113
  windowWidth: e.target.innerWidth
@@ -109,19 +115,58 @@ class Toolbar extends Component<ToolbarProps, ToolbarState> {
109
115
  }
110
116
  };
111
117
 
118
+ closeExpandableContentOnContainerResize = () => {
119
+ const containerWidth = this.toolbarRef.current?.clientWidth;
120
+ if (!containerWidth) {
121
+ return;
122
+ }
123
+
124
+ const breakpoint = getBreakpoint(containerWidth);
125
+ const isInitialMeasurement = this.containerBreakpoint === undefined;
126
+ if (breakpoint !== this.containerBreakpoint) {
127
+ this.containerBreakpoint = breakpoint;
128
+ if (!isInitialMeasurement && this.state.isManagedToggleExpanded) {
129
+ this.setState({ isManagedToggleExpanded: false });
130
+ }
131
+ }
132
+ };
133
+
134
+ setupResizeHandling = () => {
135
+ if (!this.isToggleManaged() || !canUseDOM) {
136
+ return;
137
+ }
138
+
139
+ this.containerBreakpoint = undefined;
140
+ const reference = this.props.isContainer ? this.toolbarRef.current : undefined;
141
+ const handler = this.props.isContainer ? this.closeExpandableContentOnContainerResize : this.closeExpandableContent;
142
+
143
+ this.resizeObserver = getResizeObserver(reference, handler, true);
144
+ };
145
+
146
+ cleanupResizeHandling = () => {
147
+ this.resizeObserver();
148
+ this.resizeObserver = () => {};
149
+ };
150
+
112
151
  componentDidMount() {
113
152
  if (canUseDOM) {
114
153
  this.setState({ windowWidth: window.innerWidth });
115
154
  }
116
- if (this.isToggleManaged() && canUseDOM) {
117
- window.addEventListener('resize', this.closeExpandableContent);
155
+ this.setupResizeHandling();
156
+ }
157
+
158
+ componentDidUpdate(prevProps: ToolbarProps) {
159
+ const wasToggleManaged = !(prevProps.isExpanded || !!prevProps.toggleIsExpanded);
160
+ const isToggleManaged = this.isToggleManaged();
161
+
162
+ if (prevProps.isContainer !== this.props.isContainer || wasToggleManaged !== isToggleManaged) {
163
+ this.cleanupResizeHandling();
164
+ this.setupResizeHandling();
118
165
  }
119
166
  }
120
167
 
121
168
  componentWillUnmount() {
122
- if (this.isToggleManaged() && canUseDOM) {
123
- window.removeEventListener('resize', this.closeExpandableContent);
124
- }
169
+ this.cleanupResizeHandling();
125
170
  }
126
171
 
127
172
  updateNumberFilters = (categoryName: string, numberOfFilters: number) => {
@@ -146,6 +191,7 @@ class Toolbar extends Component<ToolbarProps, ToolbarState> {
146
191
  toggleIsExpanded,
147
192
  className,
148
193
  children,
194
+ isContainer,
149
195
  isFullHeight,
150
196
  isStatic,
151
197
  isStickyBase,
@@ -169,56 +215,73 @@ class Toolbar extends Component<ToolbarProps, ToolbarState> {
169
215
 
170
216
  return (
171
217
  <PageContext.Consumer>
172
- {({ width, getBreakpoint }) => (
173
- <div
174
- className={css(
175
- styles.toolbar,
176
- hasNoPadding && styles.modifiers.noPadding,
177
- isFullHeight && styles.modifiers.fullHeight,
178
- isStatic && styles.modifiers.static,
179
- isSticky && styles.modifiers.sticky,
180
- isStickyBase && styles.modifiers.stickyBase,
181
- isStickyStuck && styles.modifiers.stickyStuck,
182
- isVertical && styles.modifiers.vertical,
183
- formatBreakpointMods(inset, styles, '', getBreakpoint(width)),
184
- colorVariant === 'primary' && styles.modifiers.primary,
185
- colorVariant === 'secondary' && styles.modifiers.secondary,
186
- colorVariant === 'no-background' && styles.modifiers.noBackground,
187
- className
188
- )}
189
- id={randomId}
190
- {...getOUIAProps(Toolbar.displayName, ouiaId !== undefined ? ouiaId : generatedOuiaId)}
191
- {...props}
192
- >
193
- <ToolbarContext.Provider
194
- value={{
195
- isExpanded,
196
- toggleIsExpanded: isToggleManaged ? this.toggleIsExpanded : toggleIsExpanded,
197
- labelGroupContentRef: this.labelGroupContentRef,
198
- updateNumberFilters: this.updateNumberFilters,
199
- numberOfFilters,
200
- clearAllFilters,
201
- clearFiltersButtonText,
202
- showClearFiltersButton,
203
- toolbarId: randomId,
204
- customLabelGroupContent
205
- }}
218
+ {(pageContext) => {
219
+ const toolbarContent = (
220
+ <div
221
+ className={css(
222
+ styles.toolbar,
223
+ hasNoPadding && styles.modifiers.noPadding,
224
+ isContainer && styles.modifiers.container,
225
+ isFullHeight && styles.modifiers.fullHeight,
226
+ isStatic && styles.modifiers.static,
227
+ isSticky && styles.modifiers.sticky,
228
+ isStickyBase && styles.modifiers.stickyBase,
229
+ isStickyStuck && styles.modifiers.stickyStuck,
230
+ isVertical && styles.modifiers.vertical,
231
+ formatBreakpointMods(
232
+ inset,
233
+ styles,
234
+ '',
235
+ !isContainer ? pageContext.getBreakpoint(pageContext.width) : undefined
236
+ ),
237
+ colorVariant === 'primary' && styles.modifiers.primary,
238
+ colorVariant === 'secondary' && styles.modifiers.secondary,
239
+ colorVariant === 'no-background' && styles.modifiers.noBackground,
240
+ className
241
+ )}
242
+ id={randomId}
243
+ ref={this.toolbarRef}
244
+ {...getOUIAProps(Toolbar.displayName, ouiaId !== undefined ? ouiaId : generatedOuiaId)}
245
+ {...props}
206
246
  >
207
- {children}
208
- <ToolbarLabelGroupContent
209
- isExpanded={isExpanded}
210
- labelGroupContentRef={this.labelGroupContentRef}
211
- clearAllFilters={clearAllFilters}
212
- showClearFiltersButton={showClearFiltersButton}
213
- clearFiltersButtonText={clearFiltersButtonText}
214
- numberOfFilters={numberOfFilters}
215
- numberOfFiltersText={numberOfFiltersText}
216
- collapseListedFiltersBreakpoint={collapseListedFiltersBreakpoint}
217
- customLabelGroupContent={customLabelGroupContent}
218
- />
219
- </ToolbarContext.Provider>
220
- </div>
221
- )}
247
+ <ToolbarContext.Provider
248
+ value={{
249
+ isExpanded,
250
+ toggleIsExpanded: isToggleManaged ? this.toggleIsExpanded : toggleIsExpanded,
251
+ labelGroupContentRef: this.labelGroupContentRef,
252
+ updateNumberFilters: this.updateNumberFilters,
253
+ numberOfFilters,
254
+ clearAllFilters,
255
+ clearFiltersButtonText,
256
+ showClearFiltersButton,
257
+ toolbarId: randomId,
258
+ customLabelGroupContent,
259
+ isContainer,
260
+ toolbarRef: this.toolbarRef
261
+ }}
262
+ >
263
+ {children}
264
+ <ToolbarLabelGroupContent
265
+ isExpanded={isExpanded}
266
+ labelGroupContentRef={this.labelGroupContentRef}
267
+ clearAllFilters={clearAllFilters}
268
+ showClearFiltersButton={showClearFiltersButton}
269
+ clearFiltersButtonText={clearFiltersButtonText}
270
+ numberOfFilters={numberOfFilters}
271
+ numberOfFiltersText={numberOfFiltersText}
272
+ collapseListedFiltersBreakpoint={collapseListedFiltersBreakpoint}
273
+ customLabelGroupContent={customLabelGroupContent}
274
+ />
275
+ </ToolbarContext.Provider>
276
+ </div>
277
+ );
278
+
279
+ return isContainer ? (
280
+ <PageContext.Provider value={{ ...pageContext, width: null }}>{toolbarContent}</PageContext.Provider>
281
+ ) : (
282
+ toolbarContent
283
+ );
284
+ }}
222
285
  </PageContext.Consumer>
223
286
  );
224
287
  };
@@ -21,6 +21,7 @@ export interface ToolbarItemProps extends React.HTMLProps<HTMLDivElement> {
21
21
  /** Visibility at various width breakpoints. */
22
22
  visibility?: {
23
23
  default?: 'hidden' | 'visible';
24
+ sm?: 'hidden' | 'visible';
24
25
  md?: 'hidden' | 'visible';
25
26
  lg?: 'hidden' | 'visible';
26
27
  xl?: 'hidden' | 'visible';
@@ -3,12 +3,11 @@ import * as ReactDOM from 'react-dom';
3
3
  import styles from '@patternfly/react-styles/css/components/Toolbar/toolbar';
4
4
  import { css } from '@patternfly/react-styles';
5
5
  import { ToolbarGroupProps } from './ToolbarGroup';
6
- import { ToolbarContext, ToolbarContentContext } from './ToolbarUtils';
6
+ import { globalBreakpoints, ToolbarContext, ToolbarContentContext } from './ToolbarUtils';
7
7
  import { Button } from '../Button';
8
- import globalBreakpointLg from '@patternfly/react-tokens/dist/esm/t_global_breakpoint_lg';
9
8
  import { formatBreakpointMods, toCamel } from '../../helpers/util';
10
- import { PageContext } from '../Page/PageContext';
11
9
  import { ToolbarExpandableContent } from './ToolbarExpandableContent';
10
+ import { PageContext } from '../Page/PageContext';
12
11
 
13
12
  export interface ToolbarToggleGroupProps extends ToolbarGroupProps {
14
13
  /** Flag indicating when toggle group is expanded for non-managed toolbar toggle groups. */
@@ -156,10 +155,9 @@ class ToolbarToggleGroup extends Component<ToolbarToggleGroupProps> {
156
155
  toggleRef = createRef<HTMLButtonElement>();
157
156
  expandableContentRef = createRef<HTMLDivElement>();
158
157
 
159
- isContentPopup = () => {
160
- const viewportSize = typeof window !== 'undefined' ? window.innerWidth : 1200;
161
- const lgBreakpointValue = parseInt(globalBreakpointLg.value);
162
- return viewportSize < lgBreakpointValue;
158
+ isContentPopup = (width?: number) => {
159
+ const size = width ?? (typeof window !== 'undefined' ? window.innerWidth : 1200);
160
+ return size < globalBreakpoints.lg;
163
161
  };
164
162
 
165
163
  render() {
@@ -191,7 +189,7 @@ class ToolbarToggleGroup extends Component<ToolbarToggleGroupProps> {
191
189
  <PageContext.Consumer>
192
190
  {({ width, getBreakpoint }) => (
193
191
  <ToolbarContext.Consumer>
194
- {({ toggleIsExpanded: managedOnToggle }) => {
192
+ {({ toggleIsExpanded: managedOnToggle, isContainer, toolbarRef }) => {
195
193
  const _onToggle = onToggle !== undefined ? onToggle : managedOnToggle;
196
194
 
197
195
  return (
@@ -238,7 +236,10 @@ class ToolbarToggleGroup extends Component<ToolbarToggleGroupProps> {
238
236
  onClick={_onToggle}
239
237
  aria-label="Show Filters"
240
238
  {...(_isExpanded && { 'aria-expanded': true })}
241
- aria-haspopup={_isExpanded && this.isContentPopup()}
239
+ aria-haspopup={
240
+ _isExpanded &&
241
+ this.isContentPopup(isContainer ? toolbarRef?.current?.clientWidth : undefined)
242
+ }
242
243
  aria-controls={_isExpanded ? expandableContentId : undefined}
243
244
  ref={this.toggleRef}
244
245
  icon={toggleIcon}
@@ -15,6 +15,10 @@ export interface ToolbarContextProps {
15
15
  showClearFiltersButton?: boolean;
16
16
  toolbarId?: string;
17
17
  customLabelGroupContent?: React.ReactNode;
18
+ /** Flag indicating if the toolbar is a container */
19
+ isContainer?: boolean;
20
+ /** Ref to the toolbar root element */
21
+ toolbarRef?: RefObject<HTMLDivElement | null>;
18
22
  }
19
23
 
20
24
  export const ToolbarContext = createContext<ToolbarContextProps>({
@@ -299,4 +299,42 @@ describe('Toolbar', () => {
299
299
  );
300
300
  expect(screen.getByTestId('toolbar-sticky-stuck')).toHaveClass(styles.modifiers.stickyStuck);
301
301
  });
302
+
303
+ it('renders the container modifier when isContainer is true', () => {
304
+ render(<Toolbar isContainer data-testid="toolbar-container" />);
305
+
306
+ expect(screen.getByTestId('toolbar-container')).toHaveClass(styles.modifiers.container);
307
+ });
308
+
309
+ it('renders all responsive visibility modifiers', () => {
310
+ render(<ToolbarItem data-testid="toolbar-item" visibility={{ md: 'hidden', xl: 'visible' }} />);
311
+
312
+ const item = screen.getByTestId('toolbar-item');
313
+
314
+ expect(item).toHaveClass('pf-m-hidden-on-md');
315
+ expect(item).toHaveClass('pf-m-visible-on-xl');
316
+ });
317
+
318
+ it('renders all responsive row wrap modifiers', () => {
319
+ render(<ToolbarContent data-testid="toolbar-content" rowWrap={{ md: 'nowrap', xl: 'wrap' }} />);
320
+
321
+ const contentSection = screen.getByTestId('toolbar-content').querySelector('div');
322
+
323
+ expect(contentSection).toHaveClass('pf-m-nowrap-on-md');
324
+ expect(contentSection).toHaveClass('pf-m-wrap-on-xl');
325
+ });
326
+
327
+ it('renders the toggle group breakpoint modifier', () => {
328
+ render(
329
+ <Toolbar>
330
+ <ToolbarContent>
331
+ <ToolbarToggleGroup data-testid="toolbar-toggle-group" breakpoint="xl" toggleIcon={<span />}>
332
+ Content
333
+ </ToolbarToggleGroup>
334
+ </ToolbarContent>
335
+ </Toolbar>
336
+ );
337
+
338
+ expect(screen.getByTestId('toolbar-toggle-group')).toHaveClass('pf-m-show-on-xl');
339
+ });
302
340
  });
@@ -1,5 +1,6 @@
1
1
  import { Fragment } from 'react';
2
- import { render } from '@testing-library/react';
2
+ import { fireEvent, render, screen } from '@testing-library/react';
3
+ import '@testing-library/jest-dom';
3
4
  import { ToolbarToggleGroup } from '../ToolbarToggleGroup';
4
5
  import { Toolbar } from '../Toolbar';
5
6
  import { ToolbarContent } from '../ToolbarContent';
@@ -25,4 +26,24 @@ describe('ToolbarToggleGroup', () => {
25
26
 
26
27
  expect(myMock).toHaveBeenCalled();
27
28
  });
29
+
30
+ it('sets aria-haspopup when expandable content is a popup in a narrow toolbar container', () => {
31
+ const clientWidthMock = jest.spyOn(HTMLElement.prototype, 'clientWidth', 'get').mockReturnValue(600);
32
+
33
+ render(
34
+ <Toolbar isContainer>
35
+ <ToolbarContent>
36
+ <ToolbarToggleGroup breakpoint="lg" toggleIcon={<span />}>
37
+ Filter controls
38
+ </ToolbarToggleGroup>
39
+ </ToolbarContent>
40
+ </Toolbar>
41
+ );
42
+
43
+ const toggle = screen.getByRole('button', { name: 'Show Filters' });
44
+ fireEvent.click(toggle);
45
+
46
+ expect(toggle).toHaveAttribute('aria-haspopup', 'true');
47
+ clientWidthMock.mockRestore();
48
+ });
28
49
  });
@@ -6,6 +6,7 @@ section: components
6
6
  ---
7
7
 
8
8
  import { Fragment, useState, useLayoutEffect, useRef } from 'react';
9
+ import './ToolbarContainerQuery.css';
9
10
 
10
11
  import EditIcon from '@patternfly/react-icons/dist/esm/icons/edit-icon';
11
12
  import RhUiCopyFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-copy-fill-icon';
@@ -78,6 +79,21 @@ To change the background color of a toolbar, use the `colorVariant` property on
78
79
 
79
80
  ```
80
81
 
82
+ ## Responsive toolbar behavior
83
+
84
+ Toolbar width-based responsive modifiers use `@container` CSS queries with the global PatternFly breakpoints. Responsive inset modifiers (via the `inset` property) are an exception and use viewport media queries. Insets are an exception and rely on viewport media queries.
85
+
86
+ By default, the PatternFly CSS establishes the `container-name` property with a value of `pf-v6-contain-toolbar` on `:root`, so the breakpoints behave like viewport breakpoints.
87
+
88
+ Alternatively, if another wrapping element creates a container in the CSS with a `container-name` property value of `pf-v6-contain-toolbar` and `container-type` value of `inline-size` or `size` , the breakpoints will apply to that container's width instead.
89
+
90
+ ### Toolbar as container
91
+ Add `isContainer` to the toolbar so width-based modifiers respond to the toolbar's width. Resize the dashed box in this example to see items and groups show and hide at the global breakpoints.
92
+
93
+ ```ts file="./ToolbarContainerQuery.tsx"
94
+
95
+ ```
96
+
81
97
  ## Examples with toggle groups and filters
82
98
 
83
99
  The following examples use toggle groups to allow for more responsive and complex toolbars with multiple items and groups of items. To visualize responsive toolbar behavior in the following examples, resize the browser to a smaller screen width.
@@ -0,0 +1,8 @@
1
+ .toolbar-container-query-resize {
2
+ width: 100%;
3
+ min-width: 300px;
4
+ padding: var(--pf-t--global--spacer--sm);
5
+ overflow: auto;
6
+ resize: horizontal;
7
+ border: var(--pf-t--global--border--width--extra-strong) dashed var(--pf-t--global--border--color--default);
8
+ }
@@ -0,0 +1,35 @@
1
+ import { Button, Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem } from '@patternfly/react-core';
2
+
3
+ export const ToolbarContainerQuery: React.FunctionComponent = () => (
4
+ <div className="toolbar-container-query-resize">
5
+ <Toolbar id="toolbar-container-query-example" isContainer>
6
+ <ToolbarContent>
7
+ <ToolbarItem visibility={{ md: 'hidden' }}>
8
+ <Button variant="secondary">Hide on md</Button>
9
+ </ToolbarItem>
10
+ <ToolbarItem>
11
+ <Button variant="secondary">Item</Button>
12
+ </ToolbarItem>
13
+ <ToolbarItem visibility={{ default: 'hidden', sm: 'visible' }}>
14
+ <Button variant="secondary">Show on sm</Button>
15
+ </ToolbarItem>
16
+ <ToolbarGroup visibility={{ xl: 'hidden' }}>
17
+ <ToolbarItem>
18
+ <Button variant="secondary">Hide group on xl</Button>
19
+ </ToolbarItem>
20
+ <ToolbarItem>
21
+ <Button variant="secondary">Hide group on xl</Button>
22
+ </ToolbarItem>
23
+ </ToolbarGroup>
24
+ <ToolbarGroup visibility={{ default: 'hidden', lg: 'visible' }}>
25
+ <ToolbarItem>
26
+ <Button variant="secondary">Show group on lg</Button>
27
+ </ToolbarItem>
28
+ <ToolbarItem>
29
+ <Button variant="secondary">Show group on lg</Button>
30
+ </ToolbarItem>
31
+ </ToolbarGroup>
32
+ </ToolbarContent>
33
+ </Toolbar>
34
+ </div>
35
+ );