Add Pagination component - #131
Conversation
Given that we're a UI component library we shouldn't be making assumptions about how the caller is handling pagination. Instead of taking a current page and total pages and calculating which pages to show, we now just take a previous and next URL, and the caller decides which pages to show (including where to place gaps) using the +pages+ slot.
There was a problem hiding this comment.
Pull request overview
Adds a new Flowbite::Pagination ViewComponent (plus supporting subcomponents) and integrates it into the demo Lookbook previews, with accompanying tests and documentation updates.
Changes:
- Introduces
Flowbite::Paginationwith page slots plus previous/next controls, gap element, and chevron icon components. - Adds Lookbook previews for the new Pagination component and refactors existing previews to share a
RenderToStringhelper. - Adds comprehensive component tests and updates the changelog / YARD checksums.
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/components/flowbite/pagination_test.rb | Adds rendering and behavior tests for Pagination and its subcomponents. |
| demo/test/components/previews/sidebar_preview.rb | Refactors preview slot rendering to use shared RenderToString. |
| demo/test/components/previews/render_to_string.rb | Adds shared helper module for rendering components to strings inside slot blocks. |
| demo/test/components/previews/pagination_preview.rb | Adds Lookbook preview scenarios for Pagination. |
| demo/test/components/previews/breadcrumb_preview.rb | Refactors preview to use shared RenderToString. |
| demo/.yardoc/checksums | Updates YARD checksums for new/updated component files. |
| CHANGELOG.md | Documents the new Pagination component. |
| app/components/flowbite/pagination.rb | Adds the main Pagination component API and slot definition. |
| app/components/flowbite/pagination/pagination.html.erb | Adds the Pagination template rendering previous/next controls and page slots. |
| app/components/flowbite/pagination/link.rb | Adds page-number link component (supports aria-current). |
| app/components/flowbite/pagination/gap.rb | Adds gap/ellipsis component for skipped page ranges. |
| app/components/flowbite/pagination/previous_link.rb | Adds Previous control component. |
| app/components/flowbite/pagination/next_link.rb | Adds Next control component. |
| app/components/flowbite/pagination/chevron_left_icon.rb | Adds left chevron SVG icon component. |
| app/components/flowbite/pagination/chevron_right_icon.rb | Adds right chevron SVG icon component. |
Suppressed comments (2)
test/components/flowbite/pagination_test.rb:51
- This assertion enforces the current behavior where a disabled link is still an element. If the component is updated to render a non-link element when disabled (to avoid href="#" navigation), update this selector accordingly.
def test_disables_next_link_when_no_next_url_given
render_inline(Flowbite::Pagination.new)
assert_selector("li a[aria-disabled='true'] span.sr-only", text: "Next")
end
test/components/flowbite/pagination_test.rb:126
- This test currently asserts that the disabled state uses href="#". That behavior causes navigation/jumping when clicked; prefer asserting against a non-link disabled element instead.
def test_renders_disabled_state
render_inline(Flowbite::Pagination::NextLink.new(url: "/posts?page=2", disabled: true))
assert_selector("a[href='#'][aria-disabled='true'].opacity-50.cursor-not-allowed")
end
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Prevents them from being focused or activated, and removes the need for a dummy href, which is better for accessibility.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 15 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (4)
app/components/flowbite/pagination/previous_link.rb:23
- The
classesarray is defined on a single very long line, which makes it hard to scan and maintain. Consider formatting it as a multi-line array (as done elsewhere in the codebase) to improve readability.
def classes(disabled: false)
classes = ["flex", "items-center", "justify-center", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "hover:text-heading", "font-medium", "rounded-s-base", "text-sm", "w-9", "h-9", "focus:outline-none"]
classes += ["opacity-50", "cursor-not-allowed"] if disabled
classes
end
app/components/flowbite/pagination/next_link.rb:23
- The
classesarray is defined on a single very long line, which makes it hard to scan and maintain. Consider formatting it as a multi-line array (as done elsewhere in the codebase) to improve readability.
def classes(disabled: false)
classes = ["flex", "items-center", "justify-center", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "hover:text-heading", "font-medium", "rounded-e-base", "text-sm", "w-9", "h-9", "focus:outline-none"]
classes += ["opacity-50", "cursor-not-allowed"] if disabled
classes
end
app/components/flowbite/pagination/gap.rb:17
- The
classesarray is defined on a single very long line, which makes it hard to scan and maintain. Consider formatting it as a multi-line array to improve readability.
class << self
def classes
["flex", "items-center", "justify-center", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "hover:text-heading", "font-medium", "text-sm", "w-9", "h-9", "focus:outline-none"]
end
app/components/flowbite/pagination/link.rb:24
- Both branches of
classesreturn large class lists on single lines. Splitting these into multi-line arrays would improve readability and make future tweaks less error-prone.
def classes(current: false)
if current
["flex", "items-center", "justify-center", "text-fg-brand", "bg-neutral-tertiary-medium", "box-border", "border", "border-default-medium", "hover:text-fg-brand", "font-medium", "text-sm", "w-9", "h-9", "focus:outline-none"]
else
["flex", "items-center", "justify-center", "text-body", "bg-neutral-secondary-medium", "box-border", "border", "border-default-medium", "hover:bg-neutral-tertiary-medium", "hover:text-heading", "font-medium", "text-sm", "w-9", "h-9", "focus:outline-none"]
Uh oh!
There was an error while loading. Please reload this page.