feat(Pagination): added dynamic sticky and plain#12388
feat(Pagination): added dynamic sticky and plain#12388thatblindgeye wants to merge 6 commits intopatternfly:mainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds two beta props ( Changes
Sequence Diagram(s)sequenceDiagram
participant User as User (scroll)
participant ScrollParent as ScrollParent
participant Hook as useIsStuckFromScrollParent (hook)
participant Pagination as Pagination (component)
participant DOM as DOM (CSS classes)
User->>ScrollParent: scrolls container
ScrollParent->>Hook: scroll event
Hook->>Hook: compute stuck state (top/bottom)
Hook->>Pagination: provide isStickyBase / isStickyStuck
Pagination->>Pagination: evaluate sticky class logic with isSticky/isStickyBase/isStickyStuck
Pagination->>DOM: apply appropriate modifier classes (stickyBase, stickyStuck, sticky)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.Comment |
|
Preview: https://pf-react-pr-12388.surge.sh A11y report: https://pf-react-pr-12388-a11y.surge.sh |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
packages/react-core/src/components/Pagination/__tests__/Pagination.test.tsx (1)
132-141: ScopeisNoPlainOnGlasstests to the bottom variant for intent clarity.At Line 132 and Line 139, these assertions currently run against default pagination. Since this prop is intended for bottom-variant styling, setting
variant={PaginationVariant.bottom}here will better lock behavior to the target use case.💡 Suggested test adjustment
- test(`should not render ${styles.modifiers.noPlainOnGlass} class by default`, () => { - render(<Pagination data-testid="pagination-no-plain-on-glass-default" itemCount={20} />); + test(`should not render ${styles.modifiers.noPlainOnGlass} class by default`, () => { + render( + <Pagination + data-testid="pagination-no-plain-on-glass-default" + itemCount={20} + variant={PaginationVariant.bottom} + /> + ); expect(screen.getByTestId('pagination-no-plain-on-glass-default')).not.toHaveClass( styles.modifiers.noPlainOnGlass ); }); test(`should render ${styles.modifiers.noPlainOnGlass} class when isNoPlainOnGlass is true`, () => { - render(<Pagination data-testid="pagination-no-plain-on-glass" itemCount={20} isNoPlainOnGlass />); + render( + <Pagination + data-testid="pagination-no-plain-on-glass" + itemCount={20} + variant={PaginationVariant.bottom} + isNoPlainOnGlass + /> + ); expect(screen.getByTestId('pagination-no-plain-on-glass')).toHaveClass(styles.modifiers.noPlainOnGlass); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/react-core/src/components/Pagination/__tests__/Pagination.test.tsx` around lines 132 - 141, The tests for the isNoPlainOnGlass prop are asserting against the default Pagination variant but this prop is intended for the bottom variant; update both tests that reference isNoPlainOnGlass to render the Pagination component with variant={PaginationVariant.bottom} (the two tests named "should not render ... noPlainOnGlass class by default" and "should render ... noPlainOnGlass class when isNoPlainOnGlass is true") so they target the bottom variant behavior and then assert on the data-testid elements as currently written.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/react-core/src/components/Pagination/Pagination.tsx`:
- Around line 132-134: Typo in the JSDoc for the Pagination sticky prop: change
the word "contro" to "control" in the comment above the Pagination prop block
(the JSDoc that references isStickyBase and isStickyStuck) so the sentence reads
"...For dynamic sticky control, use isStickyBase and isStickyStuck instead."
Update the comment in the Pagination component's JSDoc where
isStickyBase/isStickyStuck are mentioned.
In `@packages/react-core/src/helpers/useIsStuckFromScrollParent.ts`:
- Around line 6-35: The hook useIsStuckFromScrollParent currently hardcodes
top-based detection (syncFromScroll uses scrollElement.scrollTop > 0); make it
accept an optional position param with a default of 'top' to preserve backward
compatibility, then compute isStuck based on that position: for 'top' use
scrollTop > 0, for 'bottom' use (scrollTop + clientHeight < scrollHeight) (i.e.,
not at bottom). Update the function signature/type to include position?: 'top' |
'bottom', use that inside syncFromScroll to setIsStuck accordingly, and add
position to the useLayoutEffect dependency array so changes re-run.
---
Nitpick comments:
In `@packages/react-core/src/components/Pagination/__tests__/Pagination.test.tsx`:
- Around line 132-141: The tests for the isNoPlainOnGlass prop are asserting
against the default Pagination variant but this prop is intended for the bottom
variant; update both tests that reference isNoPlainOnGlass to render the
Pagination component with variant={PaginationVariant.bottom} (the two tests
named "should not render ... noPlainOnGlass class by default" and "should render
... noPlainOnGlass class when isNoPlainOnGlass is true") so they target the
bottom variant behavior and then assert on the data-testid elements as currently
written.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 914dc2de-6abf-4564-882c-49635f9a93fa
⛔ Files ignored due to path filters (2)
packages/react-core/src/components/Pagination/__tests__/__snapshots__/Pagination.test.tsx.snapis excluded by!**/*.snapyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (16)
packages/react-core/package.jsonpackages/react-core/src/components/Pagination/Pagination.tsxpackages/react-core/src/components/Pagination/__tests__/Pagination.test.tsxpackages/react-core/src/components/Pagination/examples/Pagination.mdpackages/react-core/src/components/Pagination/examples/PaginationDynamicStickyBottom.tsxpackages/react-core/src/components/Pagination/examples/PaginationDynamicStickyTop.tsxpackages/react-core/src/components/Pagination/examples/PaginationPlainBottom.tsxpackages/react-core/src/components/Pagination/examples/PaginationPlainTop.tsxpackages/react-core/src/components/Toolbar/examples/ToolbarDynamicSticky.tsxpackages/react-core/src/helpers/index.tspackages/react-core/src/helpers/useIsStuckFromScrollParent.tspackages/react-docs/package.jsonpackages/react-icons/package.jsonpackages/react-styles/package.jsonpackages/react-table/src/components/Table/examples/TableStickyHeaderDynamic.tsxpackages/react-tokens/package.json
2e0c4c0 to
7a996a5
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/react-core/src/components/Pagination/examples/Pagination.md (2)
69-76: Enhance documentation per PR objectives.The dynamic sticky top section explains the behavior well, but per the linked issue
#12331, the documentation should include:
Hook reference: The PR objectives mention "a new example using a generic hook" - consider mentioning
useIsStuckFromScrollParent(or the relevant hook name) so users know where this functionality comes from.Scroll parent guidance: The objectives mention adding "notes about the scroll parent container." Consider adding a brief note about scroll parent requirements, such as:
- What qualifies as a scroll parent
- How to ensure proper scroll parent detection
- Any container setup requirements
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/react-core/src/components/Pagination/examples/Pagination.md` around lines 69 - 76, Update the "Dynamic sticky top" docs to reference the hook and add scroll-parent guidance: mention the hook name useIsStuckFromScrollParent (or the actual exported hook used in PaginationDynamicStickyTop) as the source of the dynamic isStickyStuck behavior and briefly note what counts as a scroll parent (an ancestor with overflow:auto/scroll or a positioned container), how to ensure the hook detects it (make the scrollable ancestor a containing block with overflow set and not the document body), and any container setup needed (fixed height/overflow on the scroll parent so stickiness can be observed). Ensure you reference isStickyBase and isStickyStuck in the same paragraph so readers can map the props to the hook behavior.
9-9: Consider clarifying hook import scope.The import statement now includes
useRefanduseLayoutEffect, which are only used in the new dynamic sticky examples. Users following earlier examples (Top, Bottom, etc.) might be confused about whether these hooks are required for basic usage.Consider either:
- Adding a note that these additional imports are only needed for dynamic sticky examples
- Moving hook-specific imports to the relevant example sections
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/react-core/src/components/Pagination/examples/Pagination.md` at line 9, The import line in Pagination.md pulls in useRef and useLayoutEffect alongside Fragment and useState, which confuses readers of basic examples (Top, Bottom); update the file so that the global import only includes hooks required by every example (Fragment, useState) and either add a short note above the dynamic "Sticky" examples stating “useRef and useLayoutEffect are only required for dynamic sticky examples” or move useRef and useLayoutEffect into the specific Sticky example sections' import snippets; reference the import statement and the use of useRef/useLayoutEffect in the dynamic sticky examples to make the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/react-core/src/components/Pagination/examples/Pagination.md`:
- Around line 69-76: Update the "Dynamic sticky top" docs to reference the hook
and add scroll-parent guidance: mention the hook name useIsStuckFromScrollParent
(or the actual exported hook used in PaginationDynamicStickyTop) as the source
of the dynamic isStickyStuck behavior and briefly note what counts as a scroll
parent (an ancestor with overflow:auto/scroll or a positioned container), how to
ensure the hook detects it (make the scrollable ancestor a containing block with
overflow set and not the document body), and any container setup needed (fixed
height/overflow on the scroll parent so stickiness can be observed). Ensure you
reference isStickyBase and isStickyStuck in the same paragraph so readers can
map the props to the hook behavior.
- Line 9: The import line in Pagination.md pulls in useRef and useLayoutEffect
alongside Fragment and useState, which confuses readers of basic examples (Top,
Bottom); update the file so that the global import only includes hooks required
by every example (Fragment, useState) and either add a short note above the
dynamic "Sticky" examples stating “useRef and useLayoutEffect are only required
for dynamic sticky examples” or move useRef and useLayoutEffect into the
specific Sticky example sections' import snippets; reference the import
statement and the use of useRef/useLayoutEffect in the dynamic sticky examples
to make the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4c0f6bd6-ac78-4a78-b8a2-df2652f90c34
⛔ Files ignored due to path filters (2)
packages/react-core/src/components/Pagination/__tests__/__snapshots__/Pagination.test.tsx.snapis excluded by!**/*.snapyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (16)
packages/react-core/package.jsonpackages/react-core/src/components/Pagination/Pagination.tsxpackages/react-core/src/components/Pagination/__tests__/Pagination.test.tsxpackages/react-core/src/components/Pagination/examples/Pagination.mdpackages/react-core/src/components/Pagination/examples/PaginationDynamicStickyBottom.tsxpackages/react-core/src/components/Pagination/examples/PaginationDynamicStickyTop.tsxpackages/react-core/src/components/Pagination/examples/PaginationPlainBottom.tsxpackages/react-core/src/components/Pagination/examples/PaginationPlainTop.tsxpackages/react-core/src/components/Toolbar/examples/ToolbarDynamicSticky.tsxpackages/react-core/src/helpers/index.tspackages/react-core/src/helpers/useIsStuckFromScrollParent.tspackages/react-docs/package.jsonpackages/react-icons/package.jsonpackages/react-styles/package.jsonpackages/react-table/src/components/Table/examples/TableStickyHeaderDynamic.tsxpackages/react-tokens/package.json
✅ Files skipped from review due to trivial changes (9)
- packages/react-core/src/helpers/index.ts
- packages/react-docs/package.json
- packages/react-styles/package.json
- packages/react-tokens/package.json
- packages/react-core/src/components/Pagination/examples/PaginationPlainTop.tsx
- packages/react-core/package.json
- packages/react-core/src/components/Pagination/examples/PaginationPlainBottom.tsx
- packages/react-core/src/components/Pagination/examples/PaginationDynamicStickyTop.tsx
- packages/react-core/src/components/Pagination/examples/PaginationDynamicStickyBottom.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
- packages/react-icons/package.json
- packages/react-table/src/components/Table/examples/TableStickyHeaderDynamic.tsx
- packages/react-core/src/components/Pagination/tests/Pagination.test.tsx
- packages/react-core/src/components/Toolbar/examples/ToolbarDynamicSticky.tsx
- packages/react-core/src/helpers/useIsStuckFromScrollParent.ts
- packages/react-core/src/components/Pagination/Pagination.tsx
| import { useState } from 'react'; | ||
| import { Pagination } from '@patternfly/react-core'; | ||
|
|
||
| export const PaginationPlainTop: React.FunctionComponent = () => { |
There was a problem hiding this comment.
Can be removed - top is already plain
kmcfaul
left a comment
There was a problem hiding this comment.
couple small changes above but rest lgtm
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@packages/react-core/src/components/Pagination/examples/PaginationDynamicStickyBottom.tsx`:
- Around line 15-33: The sticky-state measurement only runs on scroll; update
the useLayoutEffect to also re-run when pagination-driven layout changes occur
by including the pagination state (e.g., page and perPage) in the effect
dependencies and/or attach a ResizeObserver to the scroll container to call the
same syncFromScroll callback; modify the effect around useLayoutEffect,
shouldTrack, scrollParentRef, setIsStuck and syncFromScroll so that measurements
run on page/perPage changes and container resize in addition to scroll, and
ensure the cleanup removes both the scroll listener and observer.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 761b084c-8530-4f2f-aad8-c5f838f81021
📒 Files selected for processing (2)
packages/react-core/src/components/Pagination/examples/PaginationDynamicStickyBottom.tsxpackages/react-core/src/components/Pagination/examples/PaginationDynamicStickyTop.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/react-core/src/components/Pagination/examples/PaginationDynamicStickyTop.tsx
edonehoo
left a comment
There was a problem hiding this comment.
minor phrasing suggestions - the main thing is to swap "may" for "can", and the rest are my own preferences for flow, so I'll let you decide
|
|
||
| ### Dynamic sticky top | ||
|
|
||
| A pagination may alternatively be made sticky with two properties: `isStickyBase` and `isStickyStuck`, which allows separate control of the sticky position and sticky styling respectively. In this example, `isStickyStuck` is only applied when the pagination is not at the top of the scroll parent container. |
There was a problem hiding this comment.
| A pagination may alternatively be made sticky with two properties: `isStickyBase` and `isStickyStuck`, which allows separate control of the sticky position and sticky styling respectively. In this example, `isStickyStuck` is only applied when the pagination is not at the top of the scroll parent container. | |
| Pagination can be made sticky via two properties: `isStickyBase`, which allows separate control of the sticky position, and `isStickyStuck`, which applies the sticky styling. In this example, `isStickyStuck` is only applied when the pagination is not at the top of the scroll parent container. |
|
|
||
| ### Dynamic sticky bottom | ||
|
|
||
| A bottom pagination may alternatively be made sticky with two properties: `isStickyBase` and `isStickyStuck`, which allows separate control of the sticky position and sticky styling respectively. In this example, `isStickyStuck` is only applied when the pagination is not at the bottom of the scroll parent container. |
There was a problem hiding this comment.
| A bottom pagination may alternatively be made sticky with two properties: `isStickyBase` and `isStickyStuck`, which allows separate control of the sticky position and sticky styling respectively. In this example, `isStickyStuck` is only applied when the pagination is not at the bottom of the scroll parent container. | |
| Bottom pagination can be made sticky via two properties: `isStickyBase`, which allows separate control of the sticky position, and `isStickyStuck`, which applies the sticky styling. In this example, `isStickyStuck` is only applied when the pagination is not at the bottom of the scroll parent container. |
e7553cb to
444af0a
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/react-core/src/components/Pagination/examples/PaginationDynamicStickyTop.tsx (1)
4-36: ⚡ Quick winExtract the shared sticky-tracking hook to avoid example drift.
This hook is duplicated in both dynamic sticky examples with only the stuck predicate changed. Consider a small shared utility/hook with a predicate callback so future fixes land in one place.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/react-core/src/components/Pagination/examples/PaginationDynamicStickyTop.tsx` around lines 4 - 36, The current useIsStuckFromScrollParent hook is duplicated across examples; extract a reusable hook (e.g., useStickyFromScrollParent) that accepts the same shouldTrack and scrollParentRef parameters plus a predicate callback (e.g., isStuckPredicate: (scrollTop: number, el: HTMLElement) => boolean) and returns the boolean stuck state; update useIsStuckFromScrollParent to delegate to the new hook (or replace both example hooks) so each example passes its specific predicate (like scrollTop > 0) while the shared hook handles event wiring, initial sync, passive scroll listener setup/removal, and cleanup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@packages/react-core/src/components/Pagination/examples/PaginationDynamicStickyTop.tsx`:
- Around line 4-36: The current useIsStuckFromScrollParent hook is duplicated
across examples; extract a reusable hook (e.g., useStickyFromScrollParent) that
accepts the same shouldTrack and scrollParentRef parameters plus a predicate
callback (e.g., isStuckPredicate: (scrollTop: number, el: HTMLElement) =>
boolean) and returns the boolean stuck state; update useIsStuckFromScrollParent
to delegate to the new hook (or replace both example hooks) so each example
passes its specific predicate (like scrollTop > 0) while the shared hook handles
event wiring, initial sync, passive scroll listener setup/removal, and cleanup.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6a588a83-59fc-4a54-85ff-aa6ed4e4fe7b
⛔ Files ignored due to path filters (2)
packages/react-core/src/components/Pagination/__tests__/__snapshots__/Pagination.test.tsx.snapis excluded by!**/*.snapyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (10)
packages/react-core/package.jsonpackages/react-core/src/components/Pagination/Pagination.tsxpackages/react-core/src/components/Pagination/__tests__/Pagination.test.tsxpackages/react-core/src/components/Pagination/examples/Pagination.mdpackages/react-core/src/components/Pagination/examples/PaginationDynamicStickyBottom.tsxpackages/react-core/src/components/Pagination/examples/PaginationDynamicStickyTop.tsxpackages/react-docs/package.jsonpackages/react-icons/package.jsonpackages/react-styles/package.jsonpackages/react-tokens/package.json
✅ Files skipped from review due to trivial changes (6)
- packages/react-core/package.json
- packages/react-styles/package.json
- packages/react-tokens/package.json
- packages/react-docs/package.json
- packages/react-icons/package.json
- packages/react-core/src/components/Pagination/examples/Pagination.md
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/react-core/src/components/Pagination/tests/Pagination.test.tsx
What: Closes #12361, closes #12331
Additional issues:
Summary by CodeRabbit
New Features
Tests
Documentation