Skip to content

fix: improve pagination aria labels and semantics#690

Open
ZQDesigned wants to merge 1 commit into
react-component:masterfrom
ZQDesigned:fix/a11y-aria-labels
Open

fix: improve pagination aria labels and semantics#690
ZQDesigned wants to merge 1 commit into
react-component:masterfrom
ZQDesigned:fix/a11y-aria-labels

Conversation

@ZQDesigned
Copy link
Copy Markdown

@ZQDesigned ZQDesigned commented Jun 1, 2026

Summary

Improve accessibility semantics for pagination controls and quick-jumper inputs.

Changes

  • Add safe fallback aria labels for page and page-size controls when locale strings are missing
  • Add role="button" and explicit aria-label to interactive pagination li items (prev, next, jump-prev, jump-next, and page items)
  • Add aria-current="page" on the active page item
  • Support Space key activation in keyboard handlers (in addition to Enter)
  • Keep compatibility with custom itemRender output
  • Update tests and snapshots to cover the new semantics

Motivation

This follows the a11y request discussed in ant-design/ant-design#58072, where some pagination controls lacked effective labels/semantics in screen readers.

Verification

  • npm test -- tests/index.test.tsx tests/itemRender.test.tsx tests/options.test.tsx tests/simple.test.tsx tests/demo.test.tsx -u
  • npm test -- tests/jumper.test.tsx tests/sizer.test.tsx tests/data-aria.test.tsx

Summary by CodeRabbit

发布说明

  • 可访问性改进

    • 增强了键盘导航支持,分页控件现已响应 Enter 与 Space 键触发
    • 优化了屏幕阅读器兼容性,补充 ARIA 属性标记(role、aria-label、aria-current)
    • 改进了分页项标签和导航按钮的无障碍文本呈现
  • 测试

    • 完善了无障碍属性的自动化测试覆盖

Copilot AI review requested due to automatic review settings June 1, 2026 11:21
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

@ZQDesigned is attempting to deploy a commit to the React Component Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

Walkthrough

通过为分页组件各项添加语义属性(role、aria-label、aria-current)并扩展键盘触发支持空格键,增强无障碍可访问性。页码项由 pageLabel 契约驱动动态生成文案;导航与跳转项统一配置语义属性;测试补充验证。

Changes

分页组件无障碍与交互增强

Layer / File(s) Summary
单页码项的契约与无障碍属性
src/Pager.tsx
PagerProps 新增可选 pageLabel 字段;页码项 <li> 添加 role="button"aria-label={pagerLabel}(由 pageLabel 或默认值 'Page' 与页号拼接)、根据活跃状态设置 aria-current;链接 <a> 补充 tabIndex={-1}aria-hidden="true"
键盘触发扩展至空格键
src/Pagination.tsx (lines 252–310)
引入 runIfEnterOrSpace 处理器,同时识别 Enter 与空格键(event.key === ' ' 或对应 keyCode/charCode),用于前后导航与跳转项的键盘激活。
Pagination 页码标签计算与传入 Pager
src/Pagination.tsx (lines 119–127, 352–355, 412)
getItemIcon 新增可选 title 参数供导航图标显示;pagerProps 添加 pageLabel: locale.page 传给下游 Pager;简单模式快速跳转输入框 aria-labellocale.jump_to 改为 locale.page
前后导航与跳转项的语义属性
src/Pagination.tsx (lines 454–497, 553–565, 584–596)
前后导航 <li> 移除 title 属性,改为设置 role="button"aria-label={locale.prev_page/next_page};跳转项 <li> 添加 role="button"aria-labeltitle 改为传入的标题文案(受 showTitle 控制);getItemIcon 按 title 参数构建按钮属性。
无障碍属性测试验证
tests/index.test.tsx
增强现有测试断言当前页项具有 aria-current="page";新增测试用例验证前后导航按钮与当前页项的 role="button"aria-label(仅前后导航)、aria-current="page"(仅当前页)语义完整性。

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • react-component/pagination#634: 主要 PR 的 src/Pagination.tsx 无障碍变更同样修改了简单模式"跳转页码"输入框的 aria-label(切换其值),与该 PR 添加相同输入框的 aria-label 直接重叠。
  • react-component/pagination#642: 两份 PR 都在 src/Pagination.tsx 中修改了前后导航对应的渲染 <li>:一个侧重补充/调整 rolearia-* 与键盘触发逻辑,另一个侧重给这些 <li> 注入自定义 className/inline style,因此是相关变更。

Suggested reviewers

  • yoyo837
  • zombieJ

Poem

🐰 分页也须无碍路,

语义标签铺康庄。

空格回车齐拥抱,

屏幕阅读不迷茫。

测试守关共安康!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR标题'fix: improve pagination aria labels and semantics'准确概括了主要变更:改进分页组件的无障碍属性和语义化标记,这与所有文件的核心改动一致。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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.

src/Pager.tsx

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

src/Pagination.tsx

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

tests/index.test.tsx

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.


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 and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR improves Pagination accessibility by adding ARIA attributes, keyboard activation support, and updating related tests/snapshots.

Changes:

  • Add aria-current, aria-label, and role attributes to pagination controls/items.
  • Update keyboard handling to activate controls via Space/Enter.
  • Refresh tests and snapshots to assert/access the new accessibility attributes.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/index.test.tsx Adds assertions for aria-current, roles, and labels on pagination items.
tests/snapshots/simple.test.tsx.snap Updates snapshots to reflect new ARIA attributes and title placement.
tests/snapshots/demo.test.tsx.snap Updates demo snapshots for new roles/labels and aria-current.
src/Pagination.tsx Introduces ARIA/title behavior changes, keyboard handling updates, and locale fallbacks.
src/Pager.tsx Adds aria-label, aria-current, and role to page items and accepts pageLabel.
src/Options.tsx Adds non-empty-string fallback for aria-label values in page size / quick jumper.
Comments suppressed due to low confidence (2)

src/Pager.tsx:1

  • role="button" (plus keyboard handlers) is being applied to the <li> while pager is rendered from itemRender(...) and is typically an interactive descendant (e.g. an <a>). This creates nested interactive controls and confusing semantics (multiple focus targets / conflicting roles). Prefer making the actual interactive element the focusable control and keep the <li> presentational (e.g., move tabIndex, key handlers, and ARIA attributes onto the rendered <a>/<button>, or render a <button>/<a> as the direct child and remove role/handlers from <li>).
/* eslint react/prop-types: 0 */

src/Pagination.tsx:1

  • Similar to Pager, adding role="button"/tabIndex/keyboard handling to the <li> while it contains an actual <button> rendered by getItemIcon(...) results in nested interactive elements and extra tab stops. This is an accessibility anti-pattern and can regress keyboard/screen reader behavior. Prefer moving click/key handling (and ARIA) onto the inner <button> (or render a single <button> as the clickable control) and keep the <li> as a non-interactive list container.
import { clsx } from 'clsx';

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Pagination.tsx Outdated
Comment thread src/Pagination.tsx Outdated
Comment thread tests/index.test.tsx
Comment thread src/Pagination.tsx
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request improves the accessibility of the pagination component by adding appropriate ARIA roles, labels, and keyboard interaction support. The feedback highlights two critical areas of improvement: first, preventing potential runtime crashes in the getNonEmptyString helper when non-string locale values (such as React elements) are passed; second, resolving accessibility violations caused by nesting interactive elements (like <a> and <button>) inside parent elements that have been assigned role="button".

Comment thread src/Options.tsx Outdated
Comment thread src/Pagination.tsx Outdated
Comment thread src/Pager.tsx Outdated
Comment thread src/Pagination.tsx
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/Pagination.tsx (1)

264-269: 💤 Low value

空格键支持的向后兼容性可以进一步增强

当前实现已正确支持现代浏览器的空格键激活(event.key === ' 'event.key === 'Spacebar'),但在第 266-267 行的 charCodekeyCode 回退检查中仅检查了 KeyCode.ENTER。对于不支持 event.key 的极老浏览器,空格键(keyCode 32)不会触发回调。

虽然这些极老浏览器已非常罕见,且主要的无障碍改进在现代浏览器中已生效,但如果需要完整的向后兼容性,可以考虑在回退检查中也包含 KeyCode.SPACE

💡 可选的增强方案
  function runIfEnter(
    event: React.KeyboardEvent<HTMLLIElement>,
    callback: (...args: any[]) => void,
    ...restParams: any[]
  ) {
    if (
      event.key === 'Enter' ||
      event.key === ' ' ||
      event.key === 'Spacebar' ||
      event.charCode === KeyCode.ENTER ||
-      event.keyCode === KeyCode.ENTER
+      event.keyCode === KeyCode.ENTER ||
+      event.keyCode === 32  // KeyCode.SPACE
    ) {
      event.preventDefault();
      callback(...restParams);
    }
  }
🤖 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/Pagination.tsx` around lines 264 - 269, The keyboard handler currently
checks event.key for space but falls back to only KeyCode.ENTER for
event.charCode/event.keyCode; update the fallback in the pagination keyboard
handler (the conditional around event.key === ' ' / 'Spacebar' and
event.charCode/event.keyCode) to also accept KeyCode.SPACE (numeric 32) so
legacy browsers that only expose charCode/keyCode will treat the space key the
same as Enter; modify the condition that references KeyCode.ENTER to include
KeyCode.SPACE for both event.charCode and event.keyCode checks.
tests/index.test.tsx (2)

100-110: ⚡ Quick win

建议添加空格键激活的测试用例。

根据 PR 目标,"支持空格键激活以及回车键激活"是此次改进的一部分。当前测试用例以及现有的键盘支持测试(第 214-221 行和第 593-654 行)仅验证了回车键(Enter)的行为,缺少对空格键(Space)激活的测试覆盖。

🧪 建议添加空格键测试

可以在现有键盘支持测试部分(第 593 行开始的 "keyboard support" describe 块)中添加空格键测试:

it('should work with Space key for prev page', () => {
  const prevButton = $('li.rc-pagination-prev');
  fireEvent.keyDown(prevButton, { key: ' ', keyCode: 32, which: 32 });
  expect(onChange).toHaveBeenLastCalledWith(49, 10);
});

it('should work with Space key for next page', () => {
  const nextButton = $('li.rc-pagination-next');
  fireEvent.keyDown(nextButton, { key: ' ', keyCode: 32, which: 32 });
  expect(onChange).toHaveBeenLastCalledWith(51, 10);
});

it('should work with Space key for page items', () => {
  const pagers = wrapper.container.querySelectorAll('.rc-pagination-item');
  fireEvent.keyDown(pagers[0], { key: ' ', keyCode: 32, which: 32 });
  expect(onChange).toHaveBeenCalled();
});
🤖 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 `@tests/index.test.tsx` around lines 100 - 110, Add tests that assert Space key
activation alongside Enter in the existing "keyboard support" describe block in
tests/index.test.tsx: locate the block where fireEvent.keyDown and onChange are
used (symbols: fireEvent, onChange, wrapper, $ helper) and add cases that fire
keyDown with { key: ' ', keyCode: 32, which: 32 } on the prev button
('li.rc-pagination-prev'), next button ('li.rc-pagination-next'), and a page
item ('.rc-pagination-item'), then assert onChange was called with the expected
arguments (matching the existing Enter-key expectations) to ensure Space
triggers the same navigation behavior.

105-107: ⚡ Quick win

建议验证 aria-label 的值非空。

当前断言仅检查 aria-label 属性是否存在,但即使值为空字符串断言也会通过。根据 PR 目标,已添加了安全回退机制以防止空标签。建议验证标签实际包含有意义的内容,以确保回退逻辑正常工作。

💡 建议的增强断言
-    expect(prevButton).toHaveAttribute('aria-label');
+    expect(prevButton).toHaveAttribute('aria-label');
+    expect(prevButton.getAttribute('aria-label')).toBeTruthy();
     expect(nextButton).toHaveAttribute('role', 'button');
-    expect(nextButton).toHaveAttribute('aria-label');
+    expect(nextButton).toHaveAttribute('aria-label');
+    expect(nextButton.getAttribute('aria-label')).toBeTruthy();
🤖 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 `@tests/index.test.tsx` around lines 105 - 107, The tests currently only assert
the presence of the aria-label attribute on prevButton and nextButton; update
those assertions to ensure the attribute value is non-empty so the fallback
logic is exercised. Locate the assertions referencing prevButton and nextButton
in the test (the lines using toHaveAttribute('aria-label')) and replace/augment
them with checks that the aria-label value is a non-empty string (e.g., retrieve
the attribute and assert it's truthy or not equal to an empty string) for both
prevButton and nextButton to guarantee meaningful labels are present.
🤖 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 `@src/Options.tsx`:
- Around line 34-36: Extract the duplicated getNonEmptyString function into a
shared utility module and import it from both components: create a new exported
function getNonEmptyString in src/utils.ts (or your utilities module), remove
the local definitions of getNonEmptyString from Options.tsx and Pagination.tsx,
and replace them with an import of the shared getNonEmptyString; ensure the
function signature and behavior remain identical so calls in Options.tsx and
Pagination.tsx continue to work without further changes.

---

Nitpick comments:
In `@src/Pagination.tsx`:
- Around line 264-269: The keyboard handler currently checks event.key for space
but falls back to only KeyCode.ENTER for event.charCode/event.keyCode; update
the fallback in the pagination keyboard handler (the conditional around
event.key === ' ' / 'Spacebar' and event.charCode/event.keyCode) to also accept
KeyCode.SPACE (numeric 32) so legacy browsers that only expose charCode/keyCode
will treat the space key the same as Enter; modify the condition that references
KeyCode.ENTER to include KeyCode.SPACE for both event.charCode and event.keyCode
checks.

In `@tests/index.test.tsx`:
- Around line 100-110: Add tests that assert Space key activation alongside
Enter in the existing "keyboard support" describe block in tests/index.test.tsx:
locate the block where fireEvent.keyDown and onChange are used (symbols:
fireEvent, onChange, wrapper, $ helper) and add cases that fire keyDown with {
key: ' ', keyCode: 32, which: 32 } on the prev button ('li.rc-pagination-prev'),
next button ('li.rc-pagination-next'), and a page item ('.rc-pagination-item'),
then assert onChange was called with the expected arguments (matching the
existing Enter-key expectations) to ensure Space triggers the same navigation
behavior.
- Around line 105-107: The tests currently only assert the presence of the
aria-label attribute on prevButton and nextButton; update those assertions to
ensure the attribute value is non-empty so the fallback logic is exercised.
Locate the assertions referencing prevButton and nextButton in the test (the
lines using toHaveAttribute('aria-label')) and replace/augment them with checks
that the aria-label value is a non-empty string (e.g., retrieve the attribute
and assert it's truthy or not equal to an empty string) for both prevButton and
nextButton to guarantee meaningful labels are present.
🪄 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: d67d4cf3-cfe7-45f1-9ce5-f3df08803dd4

📥 Commits

Reviewing files that changed from the base of the PR and between 65040ce and d52f9af.

⛔ Files ignored due to path filters (2)
  • tests/__snapshots__/demo.test.tsx.snap is excluded by !**/*.snap
  • tests/__snapshots__/simple.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • src/Options.tsx
  • src/Pager.tsx
  • src/Pagination.tsx
  • tests/index.test.tsx

Comment thread src/Options.tsx Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Options.tsx (1)

122-137: ⚡ Quick win

SizeChangerRenderaria-label 类型不安全(strictNullChecks 时可能触发 TS2322)

  • src/Options.tsx'aria-label' 期望为必填 string,但 getNonEmptyString(...) 返回 string | undefined(内部使用了 ?.trim())。
  • 若启用 strictNullChecks,这会触发 TS2322;建议在此处兜底/做非空断言以保证传入类型恒为 string
🛠️ 可选修复
-      'aria-label': getNonEmptyString(locale.page_size, 'Page Size'),
+      'aria-label': getNonEmptyString(locale.page_size, 'Page Size') as string,
🤖 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/Options.tsx` around lines 122 - 137, The 'aria-label' passed into the
size changer render can be undefined (getNonEmptyString returns string |
undefined) and will fail under strictNullChecks; update the call site inside the
showSizeChanger && sizeChangerRender block to ensure a definitive string is
provided to the 'aria-label' prop (e.g., use a fallback with nullish coalescing
or a non-null assertion on getNonEmptyString(locale.page_size, 'Page Size')), so
that the value passed to sizeChangerRender is always a string; modify the
expression where 'aria-label' is set (referencing getNonEmptyString and the
sizeChangerRender call) to produce a string unconditionally.
🤖 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 `@src/utils/getNonEmptyString.ts`:
- Around line 1-5: The predicate passed to Array.prototype.find in
getNonEmptyString currently returns unknown | undefined so the subsequent
?.trim() can be called on unknown and triggers TS18046; change the predicate to
a TypeScript type guard that narrows the element to string (for example make the
callback signature (v): v is string and return typeof v === 'string' && v.trim()
!== ''), so .find(...) will be typed as string | undefined and calling ?.trim()
is safe—update the predicate in getNonEmptyString accordingly.

---

Nitpick comments:
In `@src/Options.tsx`:
- Around line 122-137: The 'aria-label' passed into the size changer render can
be undefined (getNonEmptyString returns string | undefined) and will fail under
strictNullChecks; update the call site inside the showSizeChanger &&
sizeChangerRender block to ensure a definitive string is provided to the
'aria-label' prop (e.g., use a fallback with nullish coalescing or a non-null
assertion on getNonEmptyString(locale.page_size, 'Page Size')), so that the
value passed to sizeChangerRender is always a string; modify the expression
where 'aria-label' is set (referencing getNonEmptyString and the
sizeChangerRender call) to produce a string unconditionally.
🪄 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: 9098cfbe-8bab-4b1d-992e-7aa152e9dbaa

📥 Commits

Reviewing files that changed from the base of the PR and between d52f9af and 0614c2f.

⛔ Files ignored due to path filters (2)
  • tests/__snapshots__/demo.test.tsx.snap is excluded by !**/*.snap
  • tests/__snapshots__/simple.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (5)
  • src/Options.tsx
  • src/Pager.tsx
  • src/Pagination.tsx
  • src/utils/getNonEmptyString.ts
  • tests/index.test.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Pager.tsx
  • tests/index.test.tsx

Comment thread src/utils/getNonEmptyString.ts Outdated
@ZQDesigned ZQDesigned force-pushed the fix/a11y-aria-labels branch from 86fc95a to 0614c2f Compare June 1, 2026 11:49
@ZQDesigned ZQDesigned force-pushed the fix/a11y-aria-labels branch from 0614c2f to c559371 Compare June 1, 2026 11:54
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@src/Pagination.tsx`:
- Around line 410-413: The quick-jumper input in Pagination.tsx currently uses
locale.page directly for aria-label which can be missing or empty; update the
aria-label to fall back to a default 'Page' string (matching the Pager.tsx
fallback) so the input always has an accessible name—locate the input element
that uses value={internalInputVal} and change aria-label to use locale.page ||
'Page' (or a shared fallback constant) to ensure consistent accessibility.
- Around line 252-265: The runIfEnterOrSpace handler only checks event.key for
space but misses numeric fallbacks; update the function runIfEnterOrSpace to
include checks for event.charCode === KeyCode.SPACE (32) and event.keyCode ===
KeyCode.SPACE (32) alongside the existing ENTER checks so space activation works
in environments that only provide keyCode/charCode; then add/extend unit tests
for the Pagination component (covering previous/next and jump controls) to
simulate keyboard events with event.key = ' ' and 'Spacebar' and with
keyCode/charCode = 32 to assert the callbacks fire.
🪄 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: 80a6d822-a9f9-44d9-aab5-980e14f9b4b3

📥 Commits

Reviewing files that changed from the base of the PR and between 86fc95a and c559371.

⛔ Files ignored due to path filters (2)
  • tests/__snapshots__/demo.test.tsx.snap is excluded by !**/*.snap
  • tests/__snapshots__/simple.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (3)
  • src/Pager.tsx
  • src/Pagination.tsx
  • tests/index.test.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/index.test.tsx
  • src/Pager.tsx

Comment thread src/Pagination.tsx
Comment on lines +252 to 265
function runIfEnterOrSpace(
event: React.KeyboardEvent<HTMLLIElement>,
callback: (...args: any[]) => void,
...restParams: any[]
) {
if (
event.key === 'Enter' ||
event.key === ' ' ||
event.key === 'Spacebar' ||
event.charCode === KeyCode.ENTER ||
event.keyCode === KeyCode.ENTER
) {
event.preventDefault();
callback(...restParams);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 验证实现和测试是否覆盖了 Space 触发路径
rg -n -C2 "runIfEnterOrSpace|keyCode:\s*32|charCode:\s*32|key:\s*' '" src/Pagination.tsx tests

Repository: react-component/pagination

Length of output: 1431


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n --hidden --no-ignore -S "Space|spacebar|keyCode:\s*32|charCode:\s*32|key:\s*' '\s*|event\.key\s*===\s*' '" tests src/Pagination.tsx

Repository: react-component/pagination

Length of output: 556


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 只看 Pagination.tsx 里键码/字符码判断的实际分支
sed -n '230,290p' src/Pagination.tsx | nl -ba

Repository: react-component/pagination

Length of output: 113


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 定位 KeyCode 定义,确认 ENTER/Space 是否有统一常量
rg -n "enum KeyCode|KeyCode\." src -S

Repository: react-component/pagination

Length of output: 608


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n "KeyCode\s*=\s*|enum\s+KeyCode|const\s+KeyCode|export\s+const\s+KeyCode|KeyCode\." src

Repository: react-component/pagination

Length of output: 608


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 直接输出 Pagination.tsx 中该函数的完整判断块,避免依赖 nl
sed -n '240,280p' src/Pagination.tsx

Repository: react-component/pagination

Length of output: 1050


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 看看是否已有测试覆盖 Space/Spacebar/空格 keyCode
rg -n "Spacebar|keyCode:\s*32|charCode:\s*32|key:\s*['\"]\s*['\"]" tests src -S

Repository: react-component/pagination

Length of output: 127


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 查看 Pagination.tsx 顶部:KeyCode 从哪里来、有没有 SPACE 常量
sed -n '1,80p' src/Pagination.tsx

Repository: react-component/pagination

Length of output: 1935


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 查找是否存在 KeyCode.SPACE 或类似常量
rg -n "KeyCode\.SPACE|SPACEBAR|keyCode\s*===\s*32|charCode\s*===\s*32|event\.key\s*===\s*' '\s*\|" src -S

Repository: react-component/pagination

Length of output: 120


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 目录里看下是否存在测试文件
ls -la
fd -t f -a "Pagination" -e ts -e tsx -e js -e jsx . | head -n 50
fd -t f -a "pagination" -e ts -e tsx -e js -e jsx tests . | head -n 50

Repository: react-component/pagination

Length of output: 1967


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 兜底:直接搜索测试中是否出现 Space/Spacebar/32
rg -n "Spacebar|event\.key\s*===\s*' '\s*|keyCode:\s*32|charCode:\s*32|Space" tests src -S

Repository: react-component/pagination

Length of output: 556


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 1) 抓 Pagination.tsx 里 runIfEnterOrSpace 的完整实现(含 onKeyPress/调用点)
sed -n '240,370p' src/Pagination.tsx

Repository: react-component/pagination

Length of output: 3576


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 2) 检查 simple 模式 input 的 aria-label / locale.page 使用情况
rg -n "simple|aria-label|locale\.page|pageLabel" src/Pagination.tsx

Repository: react-component/pagination

Length of output: 701


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 3) 搜索测试里是否覆盖 Space/Spacebar(以及用 key 还是 keyCode/charCode)
rg -n "Spacebar|key:\s*' '\s*|event\.key|keyCode:\s*32|charCode:\s*32|keyCode:\s*|charCode:" tests -S

Repository: react-component/pagination

Length of output: 2003


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 4) 列出测试文件中与键盘交互相关的用例(缩小输出)
rg -n "fireEvent|keyDown|keyPress|keyUp|keydown|keypress|space|Enter|onKeyPress" tests -S

Repository: react-component/pagination

Length of output: 6889


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 1) 读取 simple 模式下 aria-label={locale.page} 附近实现
sed -n '380,430p' src/Pagination.tsx

Repository: react-component/pagination

Length of output: 1338


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 2) 找 locale.page 的类型定义/接口约束(PaginationProps 相关)
rg -n "interface .*Locale|type .*Locale|locale:\s*|page\s*:" src/interface* src -S

Repository: react-component/pagination

Length of output: 25331


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# 3) 看 locale zh_CN / 默认 locale 文件里 page 是否必填
rg -n "export default|page(\s*:|,)" src/locale -S

Repository: react-component/pagination

Length of output: 17994


补齐 Space 的 keyCode/charCode 分支(src/Pagination.tsx:252-265)并补回归测试

runIfEnterOrSpace 目前空格只通过 event.key' '/'Spacebar')触发;但缺少像 Enter 一样对 event.keyCode/event.charCode === 32 的兜底判断,因此在仅携带 keyCode: 32/charCode: 32 的环境里,上一页/下一页和 jump 控件的空格激活可能失效。现有测试用例也未见 Space/Spacebar 的键盘触发覆盖。

🔧 建议修改
  function runIfEnterOrSpace(
    event: React.KeyboardEvent<HTMLLIElement>,
    callback: (...args: any[]) => void,
    ...restParams: any[]
  ) {
    if (
      event.key === 'Enter' ||
      event.key === ' ' ||
      event.key === 'Spacebar' ||
+      event.charCode === 32 ||
      event.charCode === KeyCode.ENTER ||
+      event.keyCode === 32 ||
      event.keyCode === KeyCode.ENTER
    ) {
      event.preventDefault();
      callback(...restParams);
    }
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function runIfEnterOrSpace(
event: React.KeyboardEvent<HTMLLIElement>,
callback: (...args: any[]) => void,
...restParams: any[]
) {
if (
event.key === 'Enter' ||
event.key === ' ' ||
event.key === 'Spacebar' ||
event.charCode === KeyCode.ENTER ||
event.keyCode === KeyCode.ENTER
) {
event.preventDefault();
callback(...restParams);
function runIfEnterOrSpace(
event: React.KeyboardEvent<HTMLLIElement>,
callback: (...args: any[]) => void,
...restParams: any[]
) {
if (
event.key === 'Enter' ||
event.key === ' ' ||
event.key === 'Spacebar' ||
event.charCode === 32 ||
event.charCode === KeyCode.ENTER ||
event.keyCode === 32 ||
event.keyCode === KeyCode.ENTER
) {
event.preventDefault();
callback(...restParams);
}
}
🤖 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/Pagination.tsx` around lines 252 - 265, The runIfEnterOrSpace handler
only checks event.key for space but misses numeric fallbacks; update the
function runIfEnterOrSpace to include checks for event.charCode ===
KeyCode.SPACE (32) and event.keyCode === KeyCode.SPACE (32) alongside the
existing ENTER checks so space activation works in environments that only
provide keyCode/charCode; then add/extend unit tests for the Pagination
component (covering previous/next and jump controls) to simulate keyboard events
with event.key = ' ' and 'Spacebar' and with keyCode/charCode = 32 to assert the
callbacks fire.

Comment thread src/Pagination.tsx
Comment on lines 410 to 413
<input
type="text"
aria-label={locale.jump_to}
aria-label={locale.page}
value={internalInputVal}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

简单模式输入框也要保留页码文案兜底。

Line 412 这里直接使用 locale.page 作为 aria-label,自定义 locale 缺少该字段或传空字符串时,quick-jumper input 会失去可访问名称。src/Pager.tsx 已经对页码项做了 'Page' 兜底,这里最好保持一致。

🔧 建议修改
-            aria-label={locale.page}
+            aria-label={locale.page?.trim() || 'Page'}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<input
type="text"
aria-label={locale.jump_to}
aria-label={locale.page}
value={internalInputVal}
<input
type="text"
aria-label={locale.page?.trim() || 'Page'}
value={internalInputVal}
🤖 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/Pagination.tsx` around lines 410 - 413, The quick-jumper input in
Pagination.tsx currently uses locale.page directly for aria-label which can be
missing or empty; update the aria-label to fall back to a default 'Page' string
(matching the Pager.tsx fallback) so the input always has an accessible
name—locate the input element that uses value={internalInputVal} and change
aria-label to use locale.page || 'Page' (or a shared fallback constant) to
ensure consistent accessibility.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants