@patternfly/react-core 6.5.0-prerelease.71 → 6.5.0-prerelease.72

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 (147) 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/package.json +1 -1
  105. package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
  106. package/dist/dynamic/helpers/typeUtils/package.json +1 -1
  107. package/dist/dynamic/helpers/useInterval/package.json +1 -1
  108. package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
  109. package/dist/dynamic/helpers/useSSRSafeId/package.json +1 -1
  110. package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
  111. package/dist/dynamic/helpers/util/package.json +1 -1
  112. package/dist/dynamic/layouts/Bullseye/package.json +1 -1
  113. package/dist/dynamic/layouts/Flex/package.json +1 -1
  114. package/dist/dynamic/layouts/Gallery/package.json +1 -1
  115. package/dist/dynamic/layouts/Grid/package.json +1 -1
  116. package/dist/dynamic/layouts/Level/package.json +1 -1
  117. package/dist/dynamic/layouts/Split/package.json +1 -1
  118. package/dist/dynamic/layouts/Stack/package.json +1 -1
  119. package/dist/dynamic/styles/package.json +1 -1
  120. package/dist/esm/components/Page/PageGroup.d.ts +5 -1
  121. package/dist/esm/components/Page/PageGroup.d.ts.map +1 -1
  122. package/dist/esm/components/Page/PageGroup.js +2 -2
  123. package/dist/esm/components/Page/PageGroup.js.map +1 -1
  124. package/dist/esm/components/Page/PageSection.d.ts +4 -0
  125. package/dist/esm/components/Page/PageSection.d.ts.map +1 -1
  126. package/dist/esm/components/Page/PageSection.js +2 -2
  127. package/dist/esm/components/Page/PageSection.js.map +1 -1
  128. package/dist/js/components/Page/PageGroup.d.ts +5 -1
  129. package/dist/js/components/Page/PageGroup.d.ts.map +1 -1
  130. package/dist/js/components/Page/PageGroup.js +2 -2
  131. package/dist/js/components/Page/PageGroup.js.map +1 -1
  132. package/dist/js/components/Page/PageSection.d.ts +4 -0
  133. package/dist/js/components/Page/PageSection.d.ts.map +1 -1
  134. package/dist/js/components/Page/PageSection.js +2 -2
  135. package/dist/js/components/Page/PageSection.js.map +1 -1
  136. package/dist/umd/assets/{output-BA8-zZeB.css → output-BCOpkUJr.css} +21762 -21652
  137. package/dist/umd/react-core.min.js +1 -1
  138. package/helpers/package.json +1 -1
  139. package/layouts/package.json +1 -1
  140. package/next/package.json +1 -1
  141. package/package.json +6 -6
  142. package/src/components/Page/PageGroup.tsx +10 -0
  143. package/src/components/Page/PageSection.tsx +10 -0
  144. package/src/components/Page/__tests__/PageGroup.test.tsx +52 -0
  145. package/src/components/Page/__tests__/PageSection.test.tsx +64 -0
  146. package/src/components/Page/examples/Page.md +11 -1
  147. package/src/components/Page/examples/PageDynamicStickySection.tsx +108 -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.5.0-prerelease.70","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.5.0-prerelease.71","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.5.0-prerelease.70","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.5.0-prerelease.71","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.5.0-prerelease.70","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.5.0-prerelease.71","private":true}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "6.5.0-prerelease.71",
3
+ "version": "6.5.0-prerelease.72",
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.5.0-prerelease.32",
50
- "@patternfly/react-styles": "^6.5.0-prerelease.22",
51
- "@patternfly/react-tokens": "^6.5.0-prerelease.21",
49
+ "@patternfly/react-icons": "^6.5.0-prerelease.33",
50
+ "@patternfly/react-styles": "^6.5.0-prerelease.23",
51
+ "@patternfly/react-tokens": "^6.5.0-prerelease.22",
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.5.0-prerelease.79",
57
+ "@patternfly/patternfly": "6.5.0-prerelease.80",
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": "46565481de4856d5e426669178a4731918d60410"
66
+ "gitHead": "ea832af189f62520e49b172f13cac22df6c5d3a4"
67
67
  }
@@ -17,6 +17,10 @@ export interface PageGroupProps extends React.HTMLProps<HTMLDivElement> {
17
17
  xl?: 'top' | 'bottom';
18
18
  '2xl'?: 'top' | 'bottom';
19
19
  };
20
+ /** @beta Applies the base sticky positioning to the top or bottom of the scroll parent container. */
21
+ stickyBase?: 'top' | 'bottom';
22
+ /** @beta Flag indicating if the group has stuck styling, applied when the group is not at the edge of the scroll parent container. */
23
+ isStickyStuck?: boolean;
20
24
  /** Enables the page group to fill the available vertical space if true, or disable filling if false. */
21
25
  isFilled?: boolean;
22
26
  /** Modifier indicating if PageGroup should have a shadow at the top */
@@ -37,6 +41,8 @@ export const PageGroup = ({
37
41
  className = '',
38
42
  children,
39
43
  stickyOnBreakpoint,
44
+ stickyBase,
45
+ isStickyStuck = false,
40
46
  isFilled,
41
47
  hasShadowTop = false,
42
48
  hasShadowBottom = false,
@@ -61,6 +67,10 @@ export const PageGroup = ({
61
67
  className={css(
62
68
  styles.pageMainGroup,
63
69
  formatBreakpointMods(stickyOnBreakpoint, styles, 'sticky-', getVerticalBreakpoint(height), true),
70
+ stickyBase === 'top' && styles.modifiers.stickyTopBase,
71
+ stickyBase === 'bottom' && styles.modifiers.stickyBottomBase,
72
+ isStickyStuck && stickyBase === 'top' && styles.modifiers.stickyTopStuck,
73
+ isStickyStuck && stickyBase === 'bottom' && styles.modifiers.stickyBottomStuck,
64
74
  isFilled === false && styles.modifiers.noFill,
65
75
  isFilled === true && styles.modifiers.fill,
66
76
  hasShadowTop && styles.modifiers.shadowTop,
@@ -51,6 +51,10 @@ export interface PageSectionProps extends React.HTMLProps<HTMLDivElement> {
51
51
  xl?: 'top' | 'bottom';
52
52
  '2xl'?: 'top' | 'bottom';
53
53
  };
54
+ /** @beta Applies the base sticky positioning to the top or bottom of the scroll parent container. */
55
+ stickyBase?: 'top' | 'bottom';
56
+ /** @beta Flag indicating if the section has stuck styling, applied when the section is not at the edge of the scroll parent container. */
57
+ isStickyStuck?: boolean;
54
58
  /** Modifier indicating if PageSection should have a shadow at the top */
55
59
  hasShadowTop?: boolean;
56
60
  /** Modifier indicating if PageSection should have a shadow at the bottom */
@@ -96,6 +100,8 @@ export const PageSection: React.FunctionComponent<PageSectionProps> = ({
96
100
  isWidthLimited = false,
97
101
  isCenterAligned = false,
98
102
  stickyOnBreakpoint,
103
+ stickyBase,
104
+ isStickyStuck = false,
99
105
  hasShadowTop = false,
100
106
  hasShadowBottom = false,
101
107
  hasOverflowScroll = false,
@@ -124,6 +130,10 @@ export const PageSection: React.FunctionComponent<PageSectionProps> = ({
124
130
  variantType[type],
125
131
  formatBreakpointMods(padding, styles),
126
132
  formatBreakpointMods(stickyOnBreakpoint, styles, 'sticky-', getVerticalBreakpoint(height), true),
133
+ stickyBase === 'top' && styles.modifiers.stickyTopBase,
134
+ stickyBase === 'bottom' && styles.modifiers.stickyBottomBase,
135
+ isStickyStuck && stickyBase === 'top' && styles.modifiers.stickyTopStuck,
136
+ isStickyStuck && stickyBase === 'bottom' && styles.modifiers.stickyBottomStuck,
127
137
  type === PageSectionTypes.default && variantStyle[variant],
128
138
  isFilled === false && styles.modifiers.noFill,
129
139
  isFilled === true && styles.modifiers.fill,
@@ -101,3 +101,55 @@ test(`Renders with ${styles.modifiers.noPlainOnGlass} class when isNoPlainOnGlas
101
101
 
102
102
  expect(screen.getByText('test')).toHaveClass(styles.modifiers.noPlainOnGlass);
103
103
  });
104
+
105
+ test(`Does not add sticky base or sticky stuck classes by default`, () => {
106
+ render(<PageGroup>test</PageGroup>);
107
+ const group = screen.getByText('test');
108
+ expect(group).not.toHaveClass(styles.modifiers.stickyTopBase);
109
+ expect(group).not.toHaveClass(styles.modifiers.stickyBottomBase);
110
+ expect(group).not.toHaveClass(styles.modifiers.stickyTopStuck);
111
+ expect(group).not.toHaveClass(styles.modifiers.stickyBottomStuck);
112
+ });
113
+
114
+ test(`Adds ${styles.modifiers.stickyTopBase} without stuck class when stickyBase="top"`, () => {
115
+ render(<PageGroup stickyBase="top">test</PageGroup>);
116
+ const group = screen.getByText('test');
117
+ expect(group).toHaveClass(styles.modifiers.stickyTopBase);
118
+ expect(group).not.toHaveClass(styles.modifiers.stickyTopStuck);
119
+ });
120
+
121
+ test(`Adds ${styles.modifiers.stickyBottomBase} without stuck class when stickyBase="bottom"`, () => {
122
+ render(<PageGroup stickyBase="bottom">test</PageGroup>);
123
+ const group = screen.getByText('test');
124
+ expect(group).toHaveClass(styles.modifiers.stickyBottomBase);
125
+ expect(group).not.toHaveClass(styles.modifiers.stickyBottomStuck);
126
+ });
127
+
128
+ test(`Adds ${styles.modifiers.stickyTopStuck} when stickyBase="top" and isStickyStuck`, () => {
129
+ render(
130
+ <PageGroup stickyBase="top" isStickyStuck>
131
+ test
132
+ </PageGroup>
133
+ );
134
+ const group = screen.getByText('test');
135
+ expect(group).toHaveClass(styles.modifiers.stickyTopBase);
136
+ expect(group).toHaveClass(styles.modifiers.stickyTopStuck);
137
+ });
138
+
139
+ test(`Adds ${styles.modifiers.stickyBottomStuck} when stickyBase="bottom" and isStickyStuck`, () => {
140
+ render(
141
+ <PageGroup stickyBase="bottom" isStickyStuck>
142
+ test
143
+ </PageGroup>
144
+ );
145
+ const group = screen.getByText('test');
146
+ expect(group).toHaveClass(styles.modifiers.stickyBottomBase);
147
+ expect(group).toHaveClass(styles.modifiers.stickyBottomStuck);
148
+ });
149
+
150
+ test(`Does not add stuck class when isStickyStuck is true but stickyBase is not set`, () => {
151
+ render(<PageGroup isStickyStuck>test</PageGroup>);
152
+ const group = screen.getByText('test');
153
+ expect(group).not.toHaveClass(styles.modifiers.stickyTopStuck);
154
+ expect(group).not.toHaveClass(styles.modifiers.stickyBottomStuck);
155
+ });
@@ -199,3 +199,67 @@ test(`Renders with ${styles.modifiers.noPlainOnGlass} class when isNoPlainOnGlas
199
199
 
200
200
  expect(screen.getByText('test')).toHaveClass(styles.modifiers.noPlainOnGlass);
201
201
  });
202
+
203
+ test(`Does not add sticky base or sticky stuck classes by default`, () => {
204
+ render(<PageSection component="main">test</PageSection>);
205
+ const section = screen.getByRole('main');
206
+ expect(section).not.toHaveClass(styles.modifiers.stickyTopBase);
207
+ expect(section).not.toHaveClass(styles.modifiers.stickyBottomBase);
208
+ expect(section).not.toHaveClass(styles.modifiers.stickyTopStuck);
209
+ expect(section).not.toHaveClass(styles.modifiers.stickyBottomStuck);
210
+ });
211
+
212
+ test(`Adds ${styles.modifiers.stickyTopBase} without stuck class when stickyBase="top"`, () => {
213
+ render(
214
+ <PageSection component="main" stickyBase="top">
215
+ test
216
+ </PageSection>
217
+ );
218
+ const section = screen.getByRole('main');
219
+ expect(section).toHaveClass(styles.modifiers.stickyTopBase);
220
+ expect(section).not.toHaveClass(styles.modifiers.stickyTopStuck);
221
+ });
222
+
223
+ test(`Adds ${styles.modifiers.stickyBottomBase} without stuck class when stickyBase="bottom"`, () => {
224
+ render(
225
+ <PageSection component="main" stickyBase="bottom">
226
+ test
227
+ </PageSection>
228
+ );
229
+ const section = screen.getByRole('main');
230
+ expect(section).toHaveClass(styles.modifiers.stickyBottomBase);
231
+ expect(section).not.toHaveClass(styles.modifiers.stickyBottomStuck);
232
+ });
233
+
234
+ test(`Adds ${styles.modifiers.stickyTopStuck} when stickyBase="top" and isStickyStuck`, () => {
235
+ render(
236
+ <PageSection component="main" stickyBase="top" isStickyStuck>
237
+ test
238
+ </PageSection>
239
+ );
240
+ const section = screen.getByRole('main');
241
+ expect(section).toHaveClass(styles.modifiers.stickyTopBase);
242
+ expect(section).toHaveClass(styles.modifiers.stickyTopStuck);
243
+ });
244
+
245
+ test(`Adds ${styles.modifiers.stickyBottomStuck} when stickyBase="bottom" and isStickyStuck`, () => {
246
+ render(
247
+ <PageSection component="main" stickyBase="bottom" isStickyStuck>
248
+ test
249
+ </PageSection>
250
+ );
251
+ const section = screen.getByRole('main');
252
+ expect(section).toHaveClass(styles.modifiers.stickyBottomBase);
253
+ expect(section).toHaveClass(styles.modifiers.stickyBottomStuck);
254
+ });
255
+
256
+ test(`Does not add stuck class when isStickyStuck is true but stickyBase is not set`, () => {
257
+ render(
258
+ <PageSection component="main" isStickyStuck>
259
+ test
260
+ </PageSection>
261
+ );
262
+ const section = screen.getByRole('main');
263
+ expect(section).not.toHaveClass(styles.modifiers.stickyTopStuck);
264
+ expect(section).not.toHaveClass(styles.modifiers.stickyBottomStuck);
265
+ });
@@ -6,7 +6,7 @@ propComponents:
6
6
  ['Page', 'PageSidebar', 'PageSidebarBody', 'PageSection', 'PageGroup', 'PageBreadcrumb', 'PageToggleButton']
7
7
  ---
8
8
 
9
- import { useState } from 'react';
9
+ import { useState, useLayoutEffect, useRef } from 'react';
10
10
  import BarsIcon from '@patternfly/react-icons/dist/js/icons/bars-icon';
11
11
  import pageSectionWidthLimitMaxWidth from '@patternfly/react-tokens/dist/esm/c_page_section_m_limit_width_MaxWidth';
12
12
 
@@ -131,3 +131,13 @@ To remove the default background color from a page section or group, use the `is
131
131
  ```ts file="./PagePlainSections.tsx"
132
132
 
133
133
  ```
134
+
135
+ ### Dynamic sticky section
136
+
137
+ A page section may be made sticky with separate control of its sticky positioning and stuck styling using the `stickyBase` and `isStickyStuck` properties. The `stickyBase` property accepts a value of `"top"` or `"bottom"` and applies the base sticky positioning in the given direction. The `isStickyStuck` property applies visual "stuck" styling such as a background, box shadow, and border, and should be toggled based on the scroll position of the scroll parent container.
138
+
139
+ In this example, a scroll event listener on the scroll parent container toggles `isStickyStuck` when `scrollTop > 0`, so the stuck styling appears only when the content is scrolled.
140
+
141
+ ```ts file="./PageDynamicStickySection.tsx"
142
+
143
+ ```
@@ -0,0 +1,108 @@
1
+ import { useLayoutEffect, useState, useRef } from 'react';
2
+ import {
3
+ Page,
4
+ Masthead,
5
+ MastheadMain,
6
+ MastheadBrand,
7
+ MastheadLogo,
8
+ MastheadContent,
9
+ PageSection,
10
+ Toolbar,
11
+ ToolbarContent,
12
+ ToolbarItem,
13
+ Breadcrumb,
14
+ BreadcrumbItem,
15
+ Content
16
+ } from '@patternfly/react-core';
17
+
18
+ const useIsStuckFromScrollParent = ({
19
+ shouldTrack,
20
+ scrollParentRef
21
+ }: {
22
+ shouldTrack: boolean;
23
+ scrollParentRef: React.RefObject<any>;
24
+ }): boolean => {
25
+ const [isStuck, setIsStuck] = useState(false);
26
+
27
+ useLayoutEffect(() => {
28
+ if (!shouldTrack) {
29
+ setIsStuck(false);
30
+ return;
31
+ }
32
+
33
+ const scrollElement = scrollParentRef.current;
34
+ if (!scrollElement) {
35
+ setIsStuck(false);
36
+ return;
37
+ }
38
+
39
+ const syncFromScroll = () => {
40
+ setIsStuck(scrollElement.scrollTop > 0);
41
+ };
42
+ syncFromScroll();
43
+ scrollElement.addEventListener('scroll', syncFromScroll, { passive: true });
44
+ return () => scrollElement.removeEventListener('scroll', syncFromScroll);
45
+ }, [shouldTrack, scrollParentRef]);
46
+
47
+ return isStuck;
48
+ };
49
+
50
+ export const PageDynamicStickySection: React.FunctionComponent = () => {
51
+ const scrollParentRef = useRef<HTMLDivElement>(null);
52
+ const isStickyStuck = useIsStuckFromScrollParent({ shouldTrack: true, scrollParentRef });
53
+
54
+ const headerToolbar = (
55
+ <Toolbar id="dynamic-sticky-toolbar">
56
+ <ToolbarContent>
57
+ <ToolbarItem>header-tools</ToolbarItem>
58
+ </ToolbarContent>
59
+ </Toolbar>
60
+ );
61
+
62
+ const masthead = (
63
+ <Masthead>
64
+ <MastheadMain>
65
+ <MastheadBrand>
66
+ <MastheadLogo href="https://patternfly.org" target="_blank">
67
+ Logo
68
+ </MastheadLogo>
69
+ </MastheadBrand>
70
+ </MastheadMain>
71
+ <MastheadContent>{headerToolbar}</MastheadContent>
72
+ </Masthead>
73
+ );
74
+
75
+ return (
76
+ <Page masthead={masthead}>
77
+ <div ref={scrollParentRef} style={{ overflowY: 'auto', height: '100%' }}>
78
+ <PageSection type="breadcrumb" stickyBase="top" isStickyStuck={isStickyStuck}>
79
+ <Breadcrumb>
80
+ <BreadcrumbItem>Section home</BreadcrumbItem>
81
+ <BreadcrumbItem to="#">Section title</BreadcrumbItem>
82
+ <BreadcrumbItem to="#" isActive>
83
+ Section landing
84
+ </BreadcrumbItem>
85
+ </Breadcrumb>
86
+ </PageSection>
87
+ <PageSection>
88
+ <Content>
89
+ <h1>Main title</h1>
90
+ <p>
91
+ Scroll the container to see the breadcrumb section above dynamically apply its stuck styling. The section
92
+ uses <code>stickyBase=&quot;top&quot;</code> to remain fixed at the top of the scroll parent, and{' '}
93
+ <code>isStickyStuck</code> is toggled via a scroll event listener to apply visual styling when the section
94
+ is no longer at the top edge.
95
+ </p>
96
+ </Content>
97
+ </PageSection>
98
+ {Array.from({ length: 30 }, (_, i) => (
99
+ <PageSection key={i} variant={i % 2 === 0 ? 'default' : 'secondary'}>
100
+ <Content>
101
+ <p>{`Section ${i + 1} content`}</p>
102
+ </Content>
103
+ </PageSection>
104
+ ))}
105
+ </div>
106
+ </Page>
107
+ );
108
+ };