Skip to content

fix(Pagination): mirror default control icons in RTL via CSS#6767

Open
61021 wants to merge 2 commits into
nuxt:v4from
61021:fix/pagination-rtl-icons
Open

fix(Pagination): mirror default control icons in RTL via CSS#6767
61021 wants to merge 2 commits into
nuxt:v4from
61021:fix/pagination-rtl-icons

Conversation

@61021

@61021 61021 commented Jul 23, 2026

Copy link
Copy Markdown

🔗 Linked issue

Resolves #6438

❓ Type of change

  • 📖 Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

The first/prev/next/last icons are swapped in JS based on useLocale().dir, while the list layout follows the DOM direction (dir attribute + logical properties). The two disagree whenever RTL is set through htmlAttrs.dir (as in #6438) or through UApp's dir prop without also passing a locale: the layout mirrors but the icons keep their LTR glyphs, so the controls point inward.

This is reproducible in the playground itself: set dir: 'rtl' in playgrounds/nuxt/app/app.config.ts (it wires htmlAttrs.dir and UApp's dir, but no locale) and open /components/pagination.

Following the RTL guideline added in #6724 (direction-dependent transforms get an rtl: counterpart), this keeps the LTR default icons and mirrors them with rtl:-scale-x-100, so the icons and the layout react to the same source of truth and can't disagree — with a locale, without one, or inside a dir="rtl" subtree.

Before (RTL) After (RTL) After (LTR, unchanged)
before RTL after RTL after LTR

Notes:

  • Custom first-icon / prev-icon / next-icon / last-icon props are mirrored the same way (the component managed direction for them before too). Slot content is not affected.
  • The same useLocale().dir icon swap exists in Breadcrumb, Calendar, Carousel, ContextMenu/DropdownMenu (submenu icon) and ContentSurround — happy to align those in a follow-up PR if this approach looks right.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

The first/prev/next/last icons were swapped in JS based on useLocale().dir,
while the list layout follows the DOM direction. When RTL comes from
htmlAttrs.dir or UApp's dir prop without a locale, the layout flips but the
icons don't, leaving the controls pointing inward.

Keep the LTR default icons and mirror them with rtl:-scale-x-100 so icons
and layout react to the same source of truth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@61021
61021 requested a review from benjamincanac as a code owner July 23, 2026 12:16
@github-actions github-actions Bot added the v4 #4488 label Jul 23, 2026
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Pagination.vue removes locale-based RTL icon swapping. Pagination icons now come from explicit props or appConfig.ui.icons.*. First, previous, next, and last controls receive the computed icons and an RTL leadingIcon transform, while their existing navigation targets and page constraints remain unchanged. Tests verify mirroring for navigation icons and exclude the ellipsis icon.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: mirroring Pagination icons in RTL via CSS.
Description check ✅ Passed The description matches the implemented RTL Pagination icon mirroring fix.
Linked Issues check ✅ Passed The changes address #6438 by mirroring Pagination arrows in RTL without requiring manual icon overrides.
Out of Scope Changes check ✅ Passed The edits stay within the Pagination RTL fix and related test coverage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/runtime/components/Pagination.vue (1)

153-172: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add RTL regression coverage for pagination controls.

Test default and custom first/previous/next/last icons under dir="rtl" and verify rtl:-scale-x-100 reaches the leading icon, while slot content remains unaffected.

Also applies to: 200-219

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/components/Pagination.vue` around lines 153 - 172, Add RTL
regression coverage for the Pagination controls around the first/previous and
corresponding next/last button render paths. Under dir="rtl", verify default and
custom first, previous, next, and last icons receive the rtl:-scale-x-100
leading-icon styling, while slotted control content does not receive or alter
that styling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/runtime/components/Pagination.vue`:
- Around line 153-172: Add RTL regression coverage for the Pagination controls
around the first/previous and corresponding next/last button render paths. Under
dir="rtl", verify default and custom first, previous, next, and last icons
receive the rtl:-scale-x-100 leading-icon styling, while slotted control content
does not receive or alter that styling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a483b32b-4dca-4206-a22a-4533cb0ece87

📥 Commits

Reviewing files that changed from the base of the PR and between 8897318 and d82d799.

⛔ Files ignored due to path filters (2)
  • test/components/__snapshots__/Pagination-vue.spec.ts.snap is excluded by !**/*.snap
  • test/components/__snapshots__/Pagination.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (1)
  • src/runtime/components/Pagination.vue

@pkg-pr-new

pkg-pr-new Bot commented Jul 23, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/@nuxt/ui@6767

commit: e5aded6

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/components/Pagination.spec.ts`:
- Around line 59-76: Update the “mirrors default control icons in RTL” test to
mount Pagination with an RTL direction context, then provide explicit firstIcon,
prevIcon, nextIcon, and lastIcon props and verify those custom controls receive
the expected RTL mirroring behavior. Retain the ellipsis assertion and add
coverage for the relevant icon rendering/accessibility contract without relying
only on the static class.
🪄 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 Plus

Run ID: 25c28503-c3ca-4345-bb21-1f3097844dfd

📥 Commits

Reviewing files that changed from the base of the PR and between d82d799 and e5aded6.

📒 Files selected for processing (1)
  • test/components/Pagination.spec.ts

Comment on lines +59 to +76
it('mirrors default control icons in RTL', async () => {
const wrapper = await mountSuspended(Pagination, {
props: {
total: 100,
page: 5,
showEdges: true,
siblingCount: 1
}
})

for (const control of ['first', 'prev', 'next', 'last']) {
const icon = wrapper.find(`[data-slot="${control}"] [data-slot="leadingIcon"]`)
expect(icon.classes(), `${control} icon`).toContain('rtl:-scale-x-100')
}

const ellipsisIcon = wrapper.find('[data-slot="ellipsis"] [data-slot="leadingIcon"]')
expect(ellipsisIcon.classes(), 'ellipsis icon').not.toContain('rtl:-scale-x-100')
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make this a real RTL regression test.

The test never mounts Pagination in an RTL context; it only checks the static rtl:-scale-x-100 class, which is applied regardless of direction. Add dir="rtl" to the mount context and cover explicit firstIcon, prevIcon, nextIcon, and lastIcon props, since custom icons are also part of the PR contract.

As per coding guidelines, component tests should cover relevant props, slots, and accessibility behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/components/Pagination.spec.ts` around lines 59 - 76, Update the “mirrors
default control icons in RTL” test to mount Pagination with an RTL direction
context, then provide explicit firstIcon, prevIcon, nextIcon, and lastIcon props
and verify those custom controls receive the expected RTL mirroring behavior.
Retain the ellipsis assertion and add coverage for the relevant icon
rendering/accessibility contract without relying only on the static class.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v4 #4488

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upagination arrows in RTL are not in correct order

1 participant