Skip to content

feat: Improve accessibility (keyboard navigation, ARIA semantics, translations)#972

Open
Pareder wants to merge 2 commits into
react-component:masterfrom
Pareder:feat/improve-accessibility
Open

feat: Improve accessibility (keyboard navigation, ARIA semantics, translations)#972
Pareder wants to merge 2 commits into
react-component:masterfrom
Pareder:feat/improve-accessibility

Conversation

@Pareder
Copy link
Copy Markdown

@Pareder Pareder commented Jun 3, 2026

Overview

This PR makes the picker fully operable by keyboard and screen readers. It adds in‑panel keyboard navigation, a proper focus model between the input and the popup, ARIA roles/labels throughout the panels, and the localized strings those labels need (added across all built‑in locales).
It also includes a few breaking changes to the public component API, the footer DOM/CSS, and the Locale type — see Breaking changes.

Motivation

The picker previously could only be driven with a mouse: panel cells weren't focusable, the popup wasn't announced as a dialog, header controls were removed from the tab order (tabIndex={-1}), and time columns had no keyboard affordance. This made the component unusable for keyboard and assistive‑technology users, WCAG Success criterions are 2.1.1, 2.1.3.

What's changed

Keyboard navigation

  • Date/month/year/etc. grids: arrow keys move between cells using a roving tabindex (the active cell is the only one with tabindex="0"); Enter/Space selects the focused cell.
  • Time columns: ArrowUp/ArrowDown move between options, Enter/Space selects; options use role="option" inside a role="listbox".
  • Tab into the popup: pressing Tab while the popup is open moves focus into the panel's active cell instead of leaving the widget; Tab/Shift+Tab then cycle through the popup's focusable elements (header nav buttons, cells, footer buttons).
  • Header navigation buttons are now reachable by keyboard (the tabIndex={-1} that hid them was removed).
  • Escape closes the popup and returns focus to the trigger input.
  • Focus return on close: selecting a date that closes the popup (single picker) or completing a range (range picker), as well as Escape, returns focus to the trigger input. The return is deferred a frame so the range picker's transient close→reopen during a start→end field switch doesn't steal focus from the next field.
  • New internal usePopupFocus hook centralizes the input↔panel focus handoff; the popup container is now role="dialog".

ARIA semantics

  • Inputs expose aria-haspopup="dialog" and aria-expanded.
  • Grid cells use role="gridcell" with aria-selected, aria-disabled, and aria-current="date"; time options use role="option"/aria-selected.
  • Header navigation buttons have aria-labels, with a new per‑panel labels prop (superPrev/prev/next/superNext) so each panel can override them.

Translations

  • Added new accessibility/label keys to the Locale type and provided values for all built‑in locales: hours, minutes, seconds, milliseconds, hourSelect, minuteSelect, secondSelect, millisecondSelect, meridiemSelect.
  • Cleaned up existing nav strings to drop hard‑coded keyboard hints (e.g. "Previous month (PageUp)""Previous month"), since shortcuts are now conveyed via semantics rather than baked into labels.

Components refactor

  • The "Now/Today" control is now a real <button class="rc-picker-now"> (previously <a class="rc-picker-now-btn">), and the OK control a <button class="rc-picker-ok">.
  • The presets/ranges container is now a flex <div class="rc-picker-ranges"> instead of <ul>/<li>.

Breaking changes

  1. components.button split into components.nowButton and components.okButton.
    - <Picker components={{ button: MyButton }} />
    + <Picker components={{ nowButton: MyButton, okButton: MyButton }} />
    nowButton renders the Now/Today action; okButton renders the confirm action.

  2. Footer DOM / class changes. Custom CSS targeting the old structure must be updated:

    • .rc-picker-now-btn → removed; style .rc-picker-now (now applied directly to the <button>).
    • .rc-picker-ranges > li / ul.rc-picker-ranges.rc-picker-ranges is now a
      (flex column); the <li> wrappers are gone.
    • The Now/Today control changed from <a> to <button>.
  3. Locale type now requires additional keys. Projects that pass a custom object typed as Locale must add: hours, minutes, seconds, milliseconds, hourSelect, minuteSelect, secondSelect, millisecondSelect, meridiemSelect. (All bundled locales are already updated.)

  4. Locale string content changed. Nav labels no longer include parenthetical keyboard hints (previousMonth, nextMonth, previousYear, nextYear, previousDecade, previousCentury). Snapshot tests or assertions on the exact strings will need updating.

  5. Rendered DOM/ARIA changed. Header nav buttons are now in the tab order; inputs and cells gain aria-*/role/tabindex attributes.

Migration

  • Rename components.buttoncomponents.nowButton / components.okButton.
  • Update any CSS overrides for .rc-picker-now-btn, .rc-picker-now a, or .rc-picker-ranges li.
  • If you supply a custom Locale, add the new required keys (copy from src/locale/en_US.ts).

Testing

  • Added keyboard‑interaction tests in tests/keyboard.spec.tsx (Tab into panel, Shift+Tab, Enter‑on‑cell focus return, Escape focus return) and range tests in tests/range.spec.tsx (Tab into panel, completing a range returns focus).
  • Updated affected snapshots (panel, picker, range) to reflect the new roles/labels/DOM.

Related issues

Summary by CodeRabbit

发布说明

  • 新增功能

    • 增强键盘导航:支持Tab键在日期面板内循环切换焦点、Escape键关闭弹层
    • 改进时间选择界面:时间面板支持方向键导航和Enter/Space快捷操作
    • 扩展按钮自定义选项:支持分别自定义"现在"和"确认"按钮
    • 完善无障碍支持:为日期表格、时间列表添加ARIA标签和属性标识
  • 样式调整

    • 重构预设和页脚布局:改用Flexbox实现灵活排列
    • 优化时间单位显示:细化多语言本地化文案,覆盖时小时/分钟/秒等单位
  • 测试更新

    • 更新测试用例以适配新的DOM结构和交互方式

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 3, 2026

@Pareder 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
Contributor

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

整体说明

本次提交针对 DatePicker 和 TimePicker 组件的无障碍性进行了全面增强,重点实现了 Tab 键盘导航、焦点管理和 ARIA 属性支持。

走查指南

应按以下顺序审阅

  1. 弹窗容器键盘处理 — 理解 Tab 循环和 Escape 关闭的实现
  2. 焦点抑制 Hook — 掌握程序化聚焦期间的事件抑制机制
  3. 面板网格聚焦 — 审查 roving tabindex 和方向键导航逻辑
  4. 选择器集成 — 查看 Picker 组件如何协调弹窗、面板和焦点状态
  5. 按钮重构 — 理解 nowButton/okButton 的分离及其传播
  6. 无障碍属性 — 验证 ARIA 标签和表格角色的正确性
  7. 测试覆盖 — 检查键盘导航和焦点相关的测试用例

预估审查工作量

🎯 4 (复杂) | ⏱️ ~60 分钟

该 PR 在多个组件层级引入了复杂的焦点管理逻辑、添加了大量 ARIA 属性、重构了按钮组件接口,并补充了 60+ 个语言包的文案。虽然大部分语言包更新是重复性工作,但核心的焦点管理和键盘导航实现涉及较高的逻辑密度和多层级的状态协调。

建议审阅人员

  • zombieJ — 熟悉 Picker 核心设计和聚焦管理
  • thinkasany — 了解无障碍和键盘交互
  • afc163 — 覆盖宽度和集成验证

🐰 键盘在网格间舞蹈,
Tab 循环无限,焦点如梦想起航,
ARIA 低语述说故事,
千语万言化作一键闭合。✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 enhances the accessibility and keyboard navigation of the date and time picker components by introducing a custom focus-management hook (usePopupFocus), implementing roving tabIndex and arrow-key navigation, and adding appropriate ARIA roles and labels. The code reviewer identified several critical issues and opportunities for improvement: potential runtime reference errors due to missing imports of isSameDecade and isSameYear in their respective panels; a bug in the Shift+Tab handling within the popup container that skips the last focusable element; accessibility issues in TimeColumn when no value is selected, which can be resolved by computing a fallback tabIndexValue; and the omission of type="button" on several button components, which could lead to accidental form submissions.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +233 to +237
const idx = focusable.indexOf(document.activeElement as HTMLElement);
const next = e.shiftKey
? (idx - 1 + focusable.length) % focusable.length
: (idx + 1) % focusable.length;
focusable[next].focus();
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.

high

When document.activeElement is not in the focusable list (e.g., when focus is on the container itself), idx is -1. In this case, if the user presses Shift+Tab, the formula (idx - 1 + focusable.length) % focusable.length evaluates to focusable.length - 2 (for focusable.length > 1), which focuses the second-to-last element instead of the last one. This skips the last focusable element. We should explicitly handle idx === -1 to focus the last element on Shift+Tab and the first element on Tab.

      const idx = focusable.indexOf(document.activeElement as HTMLElement);
      const next =
        idx === -1
          ? e.shiftKey
            ? focusable.length - 1
            : 0
          : e.shiftKey
          ? (idx - 1 + focusable.length) % focusable.length
          : (idx + 1) % focusable.length;
      focusable[next].focus();

};

const getCellAttributes = (date: DateType): React.TdHTMLAttributes<HTMLTableCellElement> => {
if (isSameDecade(generateConfig, date, generateConfig.getNow())) {
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.

high

The helper function isSameDecade is used here but it does not appear to be imported at the top of the file. This will cause a runtime ReferenceError when the DecadePanel is rendered. Please ensure isSameDecade is imported from ../../utils/dateUtil.

};

const getCellAttributes = (date: DateType): React.TdHTMLAttributes<HTMLTableCellElement> => {
if (isSameYear(generateConfig, date, generateConfig.getNow())) {
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.

high

The helper function isSameYear is used here but it does not appear to be imported at the top of the file. This will cause a runtime ReferenceError when the YearPanel is rendered. Please ensure isSameYear is imported from ../../utils/dateUtil.

setFocusedValue(null);
}, [value]);

const tabFocusValue = focusedValue ?? activeValue;
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.

medium

If value and optionalValue are both undefined (e.g., when the picker is empty), tabFocusValue will be undefined. Since no unit's value matches undefined, all items will receive tabIndex={-1}, making the column completely unreachable via keyboard Tab navigation. We should compute a fallback tabIndexValue that defaults to the first enabled unit when no value is selected, ensuring the column is always focusable.

Suggested change
const tabFocusValue = focusedValue ?? activeValue;
const tabFocusValue = focusedValue ?? activeValue;
const hasTabFocus = units.some((u) => u.value === tabFocusValue);
const tabIndexValue = hasTabFocus
? tabFocusValue
: (units.find((u) => !u.disabled)?.value ?? units[0]?.value);

Comment on lines +164 to +185
const onCellKeyDown = (e: React.KeyboardEvent<HTMLLIElement>) => {
const enabledUnits = units.filter((u) => !u.disabled);
const currentIdx = enabledUnits.findIndex((u) => u.value === tabFocusValue);

if (e.key === 'ArrowDown') {
e.preventDefault();
pendingFocusRef.current = true;
const next = currentIdx < enabledUnits.length - 1 ? currentIdx + 1 : 0;
setFocusedValue(enabledUnits[next]?.value);
} else if (e.key === 'ArrowUp') {
e.preventDefault();
pendingFocusRef.current = true;
const prev = currentIdx > 0 ? currentIdx - 1 : enabledUnits.length - 1;
setFocusedValue(enabledUnits[prev]?.value);
} else if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
const target = enabledUnits.find((u) => u.value === tabFocusValue);
if (target) {
onChange(target.value);
}
}
};
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.

medium

Update onCellKeyDown to use tabIndexValue instead of tabFocusValue so that keyboard navigation starts from the fallback focusable item when no value is selected. Also, add a defensive guard to prevent errors if all units are disabled.

  const onCellKeyDown = (e: React.KeyboardEvent<HTMLLIElement>) => {
    const enabledUnits = units.filter((u) => !u.disabled);
    if (!enabledUnits.length) {
      return;
    }
    const currentIdx = enabledUnits.findIndex((u) => u.value === tabIndexValue);

    if (e.key === 'ArrowDown') {
      e.preventDefault();
      pendingFocusRef.current = true;
      const next = currentIdx < enabledUnits.length - 1 ? currentIdx + 1 : 0;
      setFocusedValue(enabledUnits[next]?.value);
    } else if (e.key === 'ArrowUp') {
      e.preventDefault();
      pendingFocusRef.current = true;
      const prev = currentIdx > 0 ? currentIdx - 1 : enabledUnits.length - 1;
      setFocusedValue(enabledUnits[prev]?.value);
    } else if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      const target = enabledUnits.find((u) => u.value === tabIndexValue);
      if (target) {
        onChange(target.value);
      }
    }
  };

Comment on lines +209 to +211
ref={tabFocusValue === unitValue ? registerFocusedLi : undefined}
aria-label={getListItemLabel(type, unitValue, locale)}
tabIndex={tabFocusValue === unitValue ? 0 : -1}
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.

medium

Use tabIndexValue instead of tabFocusValue to ensure that exactly one item in the column always has tabIndex={0} and receives the ref.

Suggested change
ref={tabFocusValue === unitValue ? registerFocusedLi : undefined}
aria-label={getListItemLabel(type, unitValue, locale)}
tabIndex={tabFocusValue === unitValue ? 0 : -1}
ref={tabIndexValue === unitValue ? registerFocusedLi : undefined}
aria-label={getListItemLabel(type, unitValue, locale)}
tabIndex={tabIndexValue === unitValue ? 0 : -1}

Comment on lines +75 to +77
<NowButton className={`${prefixCls}-now`} disabled={nowDisabled} onClick={onInternalNow}>
{internalMode === 'date' ? locale.today : locale.now}
</NowButton>
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.

medium

Add type="button" to the NowButton to prevent accidental form submissions when the picker is placed inside an HTML <form>.

Suggested change
<NowButton className={`${prefixCls}-now`} disabled={nowDisabled} onClick={onInternalNow}>
{internalMode === 'date' ? locale.today : locale.now}
</NowButton>
<NowButton type="button" className="${prefixCls}-now" disabled={nowDisabled} onClick={onInternalNow}>
{internalMode === 'date' ? locale.today : locale.now}
</NowButton>

Comment on lines +82 to +84
<OkButton disabled={invalid} className={`${prefixCls}-ok`} onClick={onSubmit}>
{locale.ok}
</OkButton>
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.

medium

Add type="button" to the OkButton to prevent accidental form submissions when the picker is placed inside an HTML <form>.

Suggested change
<OkButton disabled={invalid} className={`${prefixCls}-ok`} onClick={onSubmit}>
{locale.ok}
</OkButton>
<OkButton type="button" disabled={invalid} className="${prefixCls}-ok" onClick={onSubmit}>
{locale.ok}
</OkButton>

Comment on lines +27 to +30
<button
key={index}
onClick={() => {
onClick(executeValue(value));
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.

medium

Add type="button" to the preset <button> to prevent accidental form submissions when the picker is placed inside an HTML <form>.

Suggested change
<button
key={index}
onClick={() => {
onClick(executeValue(value));
<button
key={index}
type="button"
onClick={() => {

Copy link
Copy Markdown
Contributor

@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: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (16)
src/locale/ca_ES.ts (2)

32-32: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

修正 nextYear 的文案。

Line 32 现在还是 Mes següent,读出来是“下个月”,但这个 key 绑定的是“下一年”按钮。这样 Catalan 用户会听到错误的操作名称。

🤖 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/locale/ca_ES.ts` at line 32, The value for the locale key nextYear is
incorrect ("Mes següent" = next month); update the nextYear entry in
src/locale/ca_ES.ts (the nextYear string) to the correct Catalan phrasing for
"next year" (e.g., "Any següent (Control + right)" or "Any vinent (Control +
right)") so the label matches the button action.

29-32: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

去掉导航文案里的快捷键提示。

previousMonth/nextMonth/previousYear/nextYear 这里还带着 (PageUp)(Control + left) 之类后缀,但这批文案现在会直接进入头部按钮的可访问名称。这样读屏会把过时/误导性的按键提示一起读出来,也和本次“移除内嵌键盘提示”的 locale 契约不一致。这个问题在本批次其余几个已修改的 locale 文件里也还存在,建议一起清掉。

🤖 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/locale/ca_ES.ts` around lines 29 - 32, Remove the inline keyboard
shortcut hints from the locale strings so the accessible names don't include
outdated/misleading key tips: update the values for previousMonth, nextMonth,
previousYear, and nextYear in ca_ES.ts to only the plain labels (e.g., "Mes
anterior", "Mes següent", "Any anterior", "Any següent")—strip any "(PageUp)",
"(PageDown)", "(Control + left)", "(Control + right)" suffixes and trim
whitespace; apply the same removal pattern to the other locale files that still
contain parenthetical shortcut hints.
src/locale/ne_NP.ts (1)

31-34: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

移除导航按钮文案里的快捷键提示。

这些字段在这次改动后不再只是“帮助说明”,而是会成为表头按钮的可访问名称。把 पृष्ठ माथिControl + left 一类按键提示放在名称里,会让读屏输出变长且语义不准。建议只保留“上个月 / 下个月 / 上一年 / 下一年”的按钮名称。

🤖 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/locale/ne_NP.ts` around lines 31 - 34, The localization strings
previousMonth, nextMonth, previousYear, and nextYear include keyboard hint text
and should be simplified to plain button names; remove the shortcut/help
fragments like " (पृष्ठ माथि)", " (पृष्ठ तल)", " (Control + left)", " (Control +
right)" and replace them with concise Nepali labels such as "अघिल्लो महिना",
"अर्को महिना", "गत वर्ष", and "आउने वर्ष" respectively so the accessible button
names remain short and semantically correct.
src/locale/da_DK.ts (1)

30-33: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

移除导航按钮文案里的快捷键提示。

这些字符串在本 PR 里会作为表头翻页按钮的 aria-label 使用;把 Page UpCtrl-venstre pil 这类快捷键写进控件名称里,会让屏幕阅读器读出冗余且可能过时的说明。这里应只保留“上一月 / 下一月 / 上一年 / 下一年”这类名称。

🤖 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/locale/da_DK.ts` around lines 30 - 33, Update the locale entries
previousMonth, nextMonth, previousYear, and nextYear to remove keyboard shortcut
hints; replace strings like "Forrige måned (Page Up)" and "Forrige år
(Ctrl-venstre pil)" with plain labels such as "Forrige måned", "Næste måned",
"Forrige år", and "Næste år" so the aria-labels used for header navigation
buttons contain only the concise control names.
src/locale/pl_PL.ts (1)

30-33: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

移除导航按钮文案里的快捷键提示。

这些值在当前实现里会被当作导航按钮的名称读取;把 PageUpCtrl + left 之类的提示保留在字符串中,会导致 aria-label 冗长且误导。建议删掉括号里的按键说明,只保留导航动作本身。

🤖 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/locale/pl_PL.ts` around lines 30 - 33, Remove the shortcut hints in the
navigation label strings so ARIA labels are concise: update the constants
previousMonth, nextMonth, previousYear, and nextYear to omit text in parentheses
(e.g., remove " (PageUp)", " (PageDown)", " (Ctrl + left)", " (Ctrl + right)")
and leave only the Polish action phrases such as "Poprzedni miesiąc", "Następny
miesiąc", "Ostatni rok", and "Następny rok".
src/locale/pt_BR.ts (1)

30-33: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

移除导航按钮文案里的快捷键提示。

这些导航文案现在会作为按钮的可访问名称暴露出去;把 PageUpControl + esquerda 这类快捷键写进去,会让读屏把“名称”和“操作提示”混在一起。建议这里仅保留“上个月 / 下个月 / 上一年 / 下一年”的标签文本。

🤖 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/locale/pt_BR.ts` around lines 30 - 33, Remove the keyboard shortcut hints
from the localized button labels: update the string values for previousMonth,
nextMonth, previousYear, and nextYear so they contain only the plain labels
("Mês anterior", "Próximo mês", "Ano anterior", "Próximo ano") without any
"PageUp" or "Control + esquerda/direita" hints, since these strings are used as
accessible names for buttons.
src/locale/nl_BE.ts (1)

30-33: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

移除导航按钮文案里的快捷键提示。

这些导航字符串现在会直接进入按钮的 aria-labelPageUpControl + left 这种快捷键说明不应该成为控件名称的一部分。建议这里删掉括号内提示,只保留纯粹的导航文案。

🤖 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/locale/nl_BE.ts` around lines 30 - 33, Remove the keyboard shortcut hints
from the navigation strings used for control labels: update the locale keys
previousMonth, nextMonth, previousYear, and nextYear so their values are just
the plain navigation text (e.g., change "Vorige maand (PageUp)" → "Vorige
maand", "Volgende maand (PageDown)" → "Volgende maand", "Vorig jaar (Control +
left)" → "Vorig jaar", "Volgend jaar (Control + right)" → "Volgend jaar") so
aria-labels no longer include shortcut descriptions.
src/locale/my_MM.ts (1)

31-34: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

移除导航按钮文案里的快捷键提示。

这些文案现在会直接作为导航按钮的可访问名称;把 PageUpControl + left 之类的按键提示留在名称里,会让读屏结果变得冗长,而且和新的焦点/键盘模型不一致。建议这里只保留按钮语义,不要把操作提示混进标签里。

🤖 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/locale/my_MM.ts` around lines 31 - 34, Update the localized labels for
the calendar navigation keys to remove keyboard shortcut hints: change the
values for previousMonth, nextMonth, previousYear, and nextYear in the my_MM
locale so they contain only the semantic button text (e.g. 'ယခင်လ', 'နောက်လ',
'ယခင်နှစ်', 'နောက်နှစ်') and do not include any "PageUp", "Control + left" or
similar shortcut hints.
src/locale/nl_NL.ts (1)

30-33: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

移除导航按钮文案里的快捷键提示。

本 PR 已经把这些文案提升为实际可聚焦按钮的标签;继续保留 PageUpControl + left 等按键提示,会让可访问名称混入操作说明。这里应只翻译按钮名称本身,不要包含快捷键。

🤖 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/locale/nl_NL.ts` around lines 30 - 33, The translations for the calendar
navigation labels (previousMonth, nextMonth, previousYear, nextYear) include
keyboard shortcut hints; remove those hints so the values contain only the
button names (e.g., change "Vorige maand (PageUp)" to "Vorige maand", "Volgende
maand (PageDown)" to "Volgende maand", "Vorig jaar (Control + left)" to "Vorig
jaar", and "Volgend jaar (Control + right)" to "Volgend jaar") so the accessible
labels are free of operational instructions.
src/locale/nb_NO.ts (1)

33-36: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

移除导航按钮文案里的快捷键提示。

这里的 previousMonth / nextMonth / previousYear / nextYear 现在会被读成按钮名称;继续保留 PageUpControl + venstre 这类提示,会把说明文本错误地并入 aria-label。建议删掉括号里的快捷键信息,仅保留导航名称。

🤖 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/locale/nb_NO.ts` around lines 33 - 36, Update the localization strings
for previousMonth, nextMonth, previousYear, and nextYear to remove the shortcut
hints in parentheses so the values contain only the navigation labels (e.g.,
change "Forrige måned (PageUp)" to "Forrige måned", "Neste måned (PageDown)" to
"Neste måned", "Forrige år (Control + venstre)" to "Forrige år", and "Neste år
(Control + høyre)" to "Neste år") so these keys no longer include keyboard
shortcut text that could be read into aria-labels.
src/locale/el_GR.ts (1)

30-37: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

跨语言包不一致:未移除导航标签中的键盘快捷键提示

en_GB 和 en_US 语言包已移除了导航标签中的键盘提示(如 "PageUp"、"Control + left"),但希腊语言包仍保留这些提示。这会导致不同语言用户看到不一致的界面文本。

建议与英语语言包保持一致,移除所有键盘快捷键注释,例如:

  • previousMonth: 'Προηγούμενος μήνας'(而非 'Προηγούμενος μήνας (PageUp)'
  • nextMonth: 'Επόμενος μήνας'
  • previousYear: 'Προηγούμενο έτος'
  • nextYear: 'Επόμενο έτος'
🤖 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/locale/el_GR.ts` around lines 30 - 37, The Greek locale entries still
include keyboard shortcut hints; update the locale values for the keys
previousMonth, nextMonth, previousYear, nextYear (and optionally verify
previousDecade, nextDecade, previousCentury, nextCentury) to remove any
parenthesized keyboard annotations so the strings match the English packs—for
example change "Προηγούμενος μήνας (PageUp)" → "Προηγούμενος μήνας", "Επόμενος
μήνας (PageDown)" → "Επόμενος μήνας", "Προηγούμενο έτος (Control + αριστερά)" →
"Προηγούμενο έτος", and "Επόμενο έτος (Control + δεξιά)" → "Επόμενο έτος".
src/locale/et_EE.ts (1)

30-37: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

跨语言包不一致:未移除导航标签中的键盘快捷键提示

en_GB 和 en_US 语言包已移除了导航标签中的键盘提示(如 "PageUp"、"Control + left"),但爱沙尼亚语言包仍保留这些提示。这会导致不同语言用户看到不一致的界面文本。

建议与英语语言包保持一致,移除所有键盘快捷键注释,例如:

  • previousMonth: 'Eelmine kuu'(而非 'Eelmine kuu (PageUp)'
  • nextMonth: 'Järgmine kuu'
  • previousYear: 'Eelmine aasta'
  • nextYear: 'Järgmine aasta'
🤖 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/locale/et_EE.ts` around lines 30 - 37, Remove the inline keyboard
shortcut hints from the Estonian locale string values so they match en_GB/en_US;
locate the keys previousMonth, nextMonth, previousYear, nextYear (and optionally
previousDecade, nextDecade, previousCentury, nextCentury) in src/locale/et_EE.ts
and update their values to the same plain translations without parenthetical
shortcuts (e.g., change "Eelmine kuu (PageUp)" to "Eelmine kuu", "Järgmine kuu
(PageDown)" to "Järgmine kuu", "Eelmine aasta (Control + left)" to "Eelmine
aasta", etc.), ensuring no other text is altered.
src/locale/es_ES.ts (1)

30-37: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

跨语言包不一致:未移除导航标签中的键盘快捷键提示

en_GB 和 en_US 语言包已移除了导航标签中的键盘提示(如 "PageUp"、"Control + left"),但西班牙语(西班牙)语言包仍保留这些提示。这会导致不同语言用户看到不一致的界面文本。

建议与英语语言包保持一致,移除所有键盘快捷键注释,例如:

  • previousMonth: 'Mes anterior'(而非 'Mes anterior (PageUp)'
  • nextMonth: 'Mes siguiente'
  • previousYear: 'Año anterior'
  • nextYear: 'Año siguiente'
🤖 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/locale/es_ES.ts` around lines 30 - 37, The Spanish locale still includes
keyboard shortcut hints in the calendar navigation strings; update the keys
previousMonth, nextMonth, previousYear, nextYear, previousDecade, nextDecade,
previousCentury, and nextCentury to match the English packs by removing any
parenthetical keyboard hints (e.g., change "Mes anterior (PageUp)" to "Mes
anterior", etc.), ensuring the localized values are plain labels without
shortcut annotations.
src/locale/eu_ES.ts (1)

31-38: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

跨语言包不一致:未移除导航标签中的键盘快捷键提示

en_GB 和 en_US 语言包已移除了导航标签中的键盘提示(如 "PageUp"、"Control + left"),但巴斯克语言包仍保留这些提示(如 "RePag"、"Control + ezkerra")。这会导致不同语言用户看到不一致的界面文本。

建议与英语语言包保持一致,移除所有键盘快捷键注释,例如:

  • previousMonth: 'Aurreko hilabetea'(而非 'Aurreko hilabetea (RePag)'
  • nextMonth: 'Urrengo hilabetea'
  • previousYear: 'Aurreko urtea'
  • nextYear: 'Urrento urtea'
🤖 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/locale/eu_ES.ts` around lines 31 - 38, The Basque locale keeps keyboard
shortcut hints in navigation labels causing inconsistency; update the locale
keys (previousMonth, nextMonth, previousYear, nextYear, previousDecade,
nextDecade, previousCentury, nextCentury) in eu_ES.ts to remove any
parenthetical keyboard hints so they match the English packs (e.g., change
"Aurreko hilabetea (RePag)" to "Aurreko hilabetea", "Urrengo hilabetea (AvPag)"
to "Urrengo hilabetea", and similarly drop "(Control + ...)" from year labels).
src/locale/es_MX.ts (1)

31-38: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

跨语言包不一致:未移除导航标签中的键盘快捷键提示

en_GB 和 en_US 语言包已移除了导航标签中的键盘提示(如 "PageUp"、"Control + Left"),但西班牙语(墨西哥)语言包仍保留这些提示。这会导致不同语言用户看到不一致的界面文本。

建议与英语语言包保持一致,移除所有键盘快捷键注释,例如:

  • previousMonth: 'Mes anterior'(而非 'Mes anterior (PageUp)'
  • nextMonth: 'Mes siguiente'
  • previousYear: 'Año anterior'
  • nextYear: 'Año siguiente'
🤖 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/locale/es_MX.ts` around lines 31 - 38, Remove the keyboard shortcut
annotations from the Spanish (Mexico) locale strings so they match en_GB/en_US;
update the locale keys previousMonth, nextMonth, previousYear, nextYear (and
optionally previousDecade, nextDecade, previousCentury, nextCentury) to plain
labels like "Mes anterior", "Mes siguiente", "Año anterior", "Año siguiente"
without any "(PageUp)" or "(Control + ...)" suffixes.
src/PickerPanel/DatePanel/index.tsx (1)

190-190: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

表格 aria-label 也需要遵守本地化的年月顺序。

这里已经用 locale.monthBeforeYear 控制了可见标题顺序,但 tableLabel 仍固定为“月 年”。在年在前的语言里,读屏结果会和界面标题不一致。

💡 建议修改
   const monthYearNodes = locale.monthBeforeYear ? [monthNode, yearNode] : [yearNode, monthNode];
+  const tableLabel = locale.monthBeforeYear
+    ? `${monthLabel} ${yearLabel}`
+    : `${yearLabel} ${monthLabel}`;
@@
-          tableLabel={`${monthLabel} ${yearLabel}`}
+          tableLabel={tableLabel}

Also applies to: 234-234

🤖 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/PickerPanel/DatePanel/index.tsx` at line 190, The aria-label string for
the month/year table (tableLabel) is currently hardcoded as "月 年" and does not
follow the visible title order controlled by locale.monthBeforeYear; update the
logic that builds tableLabel (the same area that computes monthYearNodes) to
conditionally assemble the label in the same order as monthYearNodes using
locale.monthBeforeYear so screen reader output matches the displayed header
(apply the same change where tableLabel is created around the monthYearNodes
usage at both occurrences).
🧹 Nitpick comments (6)
tests/components.spec.tsx (1)

28-30: ⚡ Quick win

补一条 nowButton 迁移用例。

这里现在只覆盖了 components.okButton。这次破坏性变更是把 components.button 拆成 nowButtonokButton 两个入口,如果 nowButton 的渲染链路回归,当前测试层不会报错。建议再补一个 showNow/时间面板场景,显式断言自定义 nowButton 会渲染。

🤖 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/components.spec.tsx` around lines 28 - 30, Add a test case covering the
new components.nowButton migration: when passing components={{ okButton: Button,
nowButton: Button }} (in addition to the existing components.okButton test),
render the picker with showNow enabled (or open the time panel) to trigger the
now-button render path and assert the custom nowButton is rendered (e.g.,
getByText/getByRole or querySelector for the custom label). This ensures the
nowButton render chain is covered and will fail if nowButton regresses.
tests/keyboard.spec.tsx (1)

99-184: ⚡ Quick win

把 ARIA 契约也锁进这组新增键盘用例。

这几条用例只验证了焦点流转,还没有显式断言输入框的 aria-expanded / aria-haspopup="dialog",或弹层的 role="dialog" / 活动单元格语义。这个 PR 的公共变更里,ARIA 和键盘行为是同一层契约;只靠快照兜底的话,后续回归会比较难定位。

🤖 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/keyboard.spec.tsx` around lines 99 - 184, Add explicit ARIA assertions
to the keyboard tests so they validate both focus and accessibility attributes:
in the "tab into open popup" tests (using DayPicker, openPicker, isOpen,
container) assert the input has aria-haspopup="dialog" and the correct
aria-expanded value before/after tabbing; assert the popup element has
role="dialog" when open; in the "enter on a date cell" and "escape from inside
the panel" tests, after moving focus into the panel (use
document.querySelector('td[tabindex="0"]') as activeCell) assert the active cell
has the appropriate semantic attributes (e.g., role="gridcell" or role expected,
and aria-selected or aria-current if applicable) and after confirm/escape assert
input's aria-expanded flips back to "false" and focus returns to
container.querySelector('input'); keep assertions adjacent to existing focus
checks and use the same helper variables (container, activeCell, isOpen) so they
are easy to locate.
tests/range.spec.tsx (1)

1392-1433: ⚡ Quick win

补一个 RangePicker 的 Escape 关闭路径。

这里已经覆盖了 Tab 进弹层和选完整段后的焦点返回,但 RangePicker 这次还有“延后一帧归还焦点”的专门逻辑。单选里的 Escape 用例覆盖不到这个分支,建议再补一条:先把焦点移到活动单元格,再按 Escape,断言弹层关闭且焦点回到当前输入框。

🤖 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/range.spec.tsx` around lines 1392 - 1433, Add a test in the "tab into
open popup" suite that covers the RangePicker's Escape close path: render
DayRangePicker, openPicker(container, 0), move focus into an active cell (e.g.
query and focus the 'td[tabindex="0"]' or use selectCell to ensure a focused
cell), use jest.useFakeTimers(), fire a keyDown with key 'Escape' on the focused
cell, run timers via act(() => jest.runAllTimers()), then assert isOpen() is
false and document.activeElement is the corresponding input
(container.querySelectorAll('input')[0] or [1] depending on which field was
active); restore timers with jest.useRealTimers().
src/locale/is_IS.ts (1)

28-28: 💤 Low value

考虑由母语者验证此翻译。

"Veldu hálf dags" 字面意思是"选择半天",用于 meridiem(上午/下午)选择器可能不够自然。建议请冰岛语母语者确认此翻译是否符合当地习惯用法。

🤖 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/locale/is_IS.ts` at line 28, The meridiemSelect translation (key
meridiemSelect in src/locale/is_IS.ts) may be unnatural—ask a native Icelandic
speaker to verify and, if needed, replace "Veldu hálf dags" with a more
idiomatic phrase for selecting AM/PM (or meridiem), updating the meridiemSelect
value accordingly to match local usage and tone.
src/locale/es_ES.ts (1)

28-28: ⚡ Quick win

建议使用更地道的西班牙语表达

"Seleccionar meridiem" 中的 "meridiem" 在西班牙语中不够常用。建议使用更自然的表达,例如:

  • meridiemSelect: 'Seleccionar AM/PM'
  • meridiemSelect: 'Seleccionar periodo del día'
🤖 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/locale/es_ES.ts` at line 28, Replace the literal value for the
meridiemSelect key to a more natural Spanish phrase; locate meridiemSelect in
the locale object and change its string from "Seleccionar meridiem" to a clearer
option such as "Seleccionar AM/PM" or "Seleccionar periodo del día" depending on
desired tone.
src/locale/es_MX.ts (1)

29-29: ⚡ Quick win

建议使用更地道的西班牙语表达

"Seleccionar meridiem" 中的 "meridiem" 在西班牙语中不够常用。建议使用更自然的表达,例如:

  • meridiemSelect: 'Seleccionar AM/PM'
  • meridiemSelect: 'Seleccionar periodo del día'
🤖 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/locale/es_MX.ts` at line 29, The current localized string meridiemSelect
in es_MX.ts uses the English term "meridiem", which is unnatural for Spanish;
update the value of meridiemSelect to a more idiomatic Spanish phrase such as
'Seleccionar AM/PM' or 'Seleccionar periodo del día' so the label reads
naturally for Spanish (Mexico) users.
🤖 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/locale/te_IN.ts`:
- Around line 31-38: The te_IN locale strings for navigation (previousMonth,
nextMonth, previousYear, nextYear, previousDecade, nextDecade, previousCentury,
nextCentury) lack the PageUp/PageDown keyboard hints and are thus inconsistent
with most other locales; restore the keyboard hint text in each of these keys in
src/locale/te_IN.ts to match the pattern used in the other language files (e.g.,
append the same PageUp/PageDown parenthetical hint used elsewhere), ensuring the
exact keys named above are updated with the localized hint wording.

In `@src/locale/zh_CN.ts`:
- Around line 22-23: The locale strings previousMonth and nextMonth in zh_CN.ts
include embedded keyboard hints like "(翻页上键)" which should be removed; update
previousMonth: '上个月' and nextMonth: '下个月' and similarly remove any inline
key-tip text from other navigation-related keys in this file (e.g., the
analogous entries around the same block) so the strings only contain the action
labels used for buttons/ARIA.

In `@src/PickerInput/Popup/Footer.tsx`:
- Around line 75-84: The NowButton and OkButton are rendered as native buttons
without a type, so when placed inside a form clicking them can trigger form
submission; update the JSX for NowButton (used with onInternalNow, className
`${prefixCls}-now`) and OkButton (rendered when needConfirm is true, disabled
based on invalid, with onClick onSubmit and className `${prefixCls}-ok`) to
include type="button" to prevent accidental form submits.

In `@src/PickerInput/Popup/index.tsx`:
- Around line 221-228: The Tab-focus collection in onContainerKeyDown currently
queries only 'button', 'a', 'td[tabindex="0"]', 'li[tabindex="0"]' so custom
slot content (e.g., components.nowButton/components.okButton or panelRender
outputs) gets skipped; update the selector used in container.querySelectorAll
inside onContainerKeyDown to a generic focusable set (e.g., include input,
select, textarea, [href], and [tabindex]:not([tabindex="-1"]) ), then keep the
existing filtering step but extend it to exclude elements that are disabled,
have aria-disabled="true", or are not visible via getComputedStyle; ensure the
rest of the function (focus wrap logic) uses that new focusable list.

In `@src/PickerInput/Popup/PresetPanel.tsx`:
- Around line 27-40: The preset buttons in PresetPanel are missing an explicit
type and currently default to type="submit", causing outer forms to submit;
update the <button> elements rendered in the PresetPanel component to include
type="button" so clicks only trigger onClick/onMouseEnter/onMouseLeave handlers
(preserve executeValue, onClick, onHover usage and label rendering).

In `@src/PickerPanel/DatePanel/index.tsx`:
- Around line 78-85: The aria-label for the week cell currently hardcodes an
English prefix ("Week") which breaks localization; change the aria-label
construction in the DatePanel week cell to use the localized prefix from the
component locale (e.g., use locale.week or the appropriate field on the locale
object) when composing the label (where
generateConfig.locale.getWeek(locale.locale, date) produces label), so
aria-label becomes something like combining locale.week with the computed label
instead of the literal "Week".

---

Outside diff comments:
In `@src/locale/ca_ES.ts`:
- Line 32: The value for the locale key nextYear is incorrect ("Mes següent" =
next month); update the nextYear entry in src/locale/ca_ES.ts (the nextYear
string) to the correct Catalan phrasing for "next year" (e.g., "Any següent
(Control + right)" or "Any vinent (Control + right)") so the label matches the
button action.
- Around line 29-32: Remove the inline keyboard shortcut hints from the locale
strings so the accessible names don't include outdated/misleading key tips:
update the values for previousMonth, nextMonth, previousYear, and nextYear in
ca_ES.ts to only the plain labels (e.g., "Mes anterior", "Mes següent", "Any
anterior", "Any següent")—strip any "(PageUp)", "(PageDown)", "(Control +
left)", "(Control + right)" suffixes and trim whitespace; apply the same removal
pattern to the other locale files that still contain parenthetical shortcut
hints.

In `@src/locale/da_DK.ts`:
- Around line 30-33: Update the locale entries previousMonth, nextMonth,
previousYear, and nextYear to remove keyboard shortcut hints; replace strings
like "Forrige måned (Page Up)" and "Forrige år (Ctrl-venstre pil)" with plain
labels such as "Forrige måned", "Næste måned", "Forrige år", and "Næste år" so
the aria-labels used for header navigation buttons contain only the concise
control names.

In `@src/locale/el_GR.ts`:
- Around line 30-37: The Greek locale entries still include keyboard shortcut
hints; update the locale values for the keys previousMonth, nextMonth,
previousYear, nextYear (and optionally verify previousDecade, nextDecade,
previousCentury, nextCentury) to remove any parenthesized keyboard annotations
so the strings match the English packs—for example change "Προηγούμενος μήνας
(PageUp)" → "Προηγούμενος μήνας", "Επόμενος μήνας (PageDown)" → "Επόμενος
μήνας", "Προηγούμενο έτος (Control + αριστερά)" → "Προηγούμενο έτος", and
"Επόμενο έτος (Control + δεξιά)" → "Επόμενο έτος".

In `@src/locale/es_ES.ts`:
- Around line 30-37: The Spanish locale still includes keyboard shortcut hints
in the calendar navigation strings; update the keys previousMonth, nextMonth,
previousYear, nextYear, previousDecade, nextDecade, previousCentury, and
nextCentury to match the English packs by removing any parenthetical keyboard
hints (e.g., change "Mes anterior (PageUp)" to "Mes anterior", etc.), ensuring
the localized values are plain labels without shortcut annotations.

In `@src/locale/es_MX.ts`:
- Around line 31-38: Remove the keyboard shortcut annotations from the Spanish
(Mexico) locale strings so they match en_GB/en_US; update the locale keys
previousMonth, nextMonth, previousYear, nextYear (and optionally previousDecade,
nextDecade, previousCentury, nextCentury) to plain labels like "Mes anterior",
"Mes siguiente", "Año anterior", "Año siguiente" without any "(PageUp)" or
"(Control + ...)" suffixes.

In `@src/locale/et_EE.ts`:
- Around line 30-37: Remove the inline keyboard shortcut hints from the Estonian
locale string values so they match en_GB/en_US; locate the keys previousMonth,
nextMonth, previousYear, nextYear (and optionally previousDecade, nextDecade,
previousCentury, nextCentury) in src/locale/et_EE.ts and update their values to
the same plain translations without parenthetical shortcuts (e.g., change
"Eelmine kuu (PageUp)" to "Eelmine kuu", "Järgmine kuu (PageDown)" to "Järgmine
kuu", "Eelmine aasta (Control + left)" to "Eelmine aasta", etc.), ensuring no
other text is altered.

In `@src/locale/eu_ES.ts`:
- Around line 31-38: The Basque locale keeps keyboard shortcut hints in
navigation labels causing inconsistency; update the locale keys (previousMonth,
nextMonth, previousYear, nextYear, previousDecade, nextDecade, previousCentury,
nextCentury) in eu_ES.ts to remove any parenthetical keyboard hints so they
match the English packs (e.g., change "Aurreko hilabetea (RePag)" to "Aurreko
hilabetea", "Urrengo hilabetea (AvPag)" to "Urrengo hilabetea", and similarly
drop "(Control + ...)" from year labels).

In `@src/locale/my_MM.ts`:
- Around line 31-34: Update the localized labels for the calendar navigation
keys to remove keyboard shortcut hints: change the values for previousMonth,
nextMonth, previousYear, and nextYear in the my_MM locale so they contain only
the semantic button text (e.g. 'ယခင်လ', 'နောက်လ', 'ယခင်နှစ်', 'နောက်နှစ်') and
do not include any "PageUp", "Control + left" or similar shortcut hints.

In `@src/locale/nb_NO.ts`:
- Around line 33-36: Update the localization strings for previousMonth,
nextMonth, previousYear, and nextYear to remove the shortcut hints in
parentheses so the values contain only the navigation labels (e.g., change
"Forrige måned (PageUp)" to "Forrige måned", "Neste måned (PageDown)" to "Neste
måned", "Forrige år (Control + venstre)" to "Forrige år", and "Neste år (Control
+ høyre)" to "Neste år") so these keys no longer include keyboard shortcut text
that could be read into aria-labels.

In `@src/locale/ne_NP.ts`:
- Around line 31-34: The localization strings previousMonth, nextMonth,
previousYear, and nextYear include keyboard hint text and should be simplified
to plain button names; remove the shortcut/help fragments like " (पृष्ठ माथि)",
" (पृष्ठ तल)", " (Control + left)", " (Control + right)" and replace them with
concise Nepali labels such as "अघिल्लो महिना", "अर्को महिना", "गत वर्ष", and
"आउने वर्ष" respectively so the accessible button names remain short and
semantically correct.

In `@src/locale/nl_BE.ts`:
- Around line 30-33: Remove the keyboard shortcut hints from the navigation
strings used for control labels: update the locale keys previousMonth,
nextMonth, previousYear, and nextYear so their values are just the plain
navigation text (e.g., change "Vorige maand (PageUp)" → "Vorige maand",
"Volgende maand (PageDown)" → "Volgende maand", "Vorig jaar (Control + left)" →
"Vorig jaar", "Volgend jaar (Control + right)" → "Volgend jaar") so aria-labels
no longer include shortcut descriptions.

In `@src/locale/nl_NL.ts`:
- Around line 30-33: The translations for the calendar navigation labels
(previousMonth, nextMonth, previousYear, nextYear) include keyboard shortcut
hints; remove those hints so the values contain only the button names (e.g.,
change "Vorige maand (PageUp)" to "Vorige maand", "Volgende maand (PageDown)" to
"Volgende maand", "Vorig jaar (Control + left)" to "Vorig jaar", and "Volgend
jaar (Control + right)" to "Volgend jaar") so the accessible labels are free of
operational instructions.

In `@src/locale/pl_PL.ts`:
- Around line 30-33: Remove the shortcut hints in the navigation label strings
so ARIA labels are concise: update the constants previousMonth, nextMonth,
previousYear, and nextYear to omit text in parentheses (e.g., remove "
(PageUp)", " (PageDown)", " (Ctrl + left)", " (Ctrl + right)") and leave only
the Polish action phrases such as "Poprzedni miesiąc", "Następny miesiąc",
"Ostatni rok", and "Następny rok".

In `@src/locale/pt_BR.ts`:
- Around line 30-33: Remove the keyboard shortcut hints from the localized
button labels: update the string values for previousMonth, nextMonth,
previousYear, and nextYear so they contain only the plain labels ("Mês
anterior", "Próximo mês", "Ano anterior", "Próximo ano") without any "PageUp" or
"Control + esquerda/direita" hints, since these strings are used as accessible
names for buttons.

In `@src/PickerPanel/DatePanel/index.tsx`:
- Line 190: The aria-label string for the month/year table (tableLabel) is
currently hardcoded as "月 年" and does not follow the visible title order
controlled by locale.monthBeforeYear; update the logic that builds tableLabel
(the same area that computes monthYearNodes) to conditionally assemble the label
in the same order as monthYearNodes using locale.monthBeforeYear so screen
reader output matches the displayed header (apply the same change where
tableLabel is created around the monthYearNodes usage at both occurrences).

---

Nitpick comments:
In `@src/locale/es_ES.ts`:
- Line 28: Replace the literal value for the meridiemSelect key to a more
natural Spanish phrase; locate meridiemSelect in the locale object and change
its string from "Seleccionar meridiem" to a clearer option such as "Seleccionar
AM/PM" or "Seleccionar periodo del día" depending on desired tone.

In `@src/locale/es_MX.ts`:
- Line 29: The current localized string meridiemSelect in es_MX.ts uses the
English term "meridiem", which is unnatural for Spanish; update the value of
meridiemSelect to a more idiomatic Spanish phrase such as 'Seleccionar AM/PM' or
'Seleccionar periodo del día' so the label reads naturally for Spanish (Mexico)
users.

In `@src/locale/is_IS.ts`:
- Line 28: The meridiemSelect translation (key meridiemSelect in
src/locale/is_IS.ts) may be unnatural—ask a native Icelandic speaker to verify
and, if needed, replace "Veldu hálf dags" with a more idiomatic phrase for
selecting AM/PM (or meridiem), updating the meridiemSelect value accordingly to
match local usage and tone.

In `@tests/components.spec.tsx`:
- Around line 28-30: Add a test case covering the new components.nowButton
migration: when passing components={{ okButton: Button, nowButton: Button }} (in
addition to the existing components.okButton test), render the picker with
showNow enabled (or open the time panel) to trigger the now-button render path
and assert the custom nowButton is rendered (e.g., getByText/getByRole or
querySelector for the custom label). This ensures the nowButton render chain is
covered and will fail if nowButton regresses.

In `@tests/keyboard.spec.tsx`:
- Around line 99-184: Add explicit ARIA assertions to the keyboard tests so they
validate both focus and accessibility attributes: in the "tab into open popup"
tests (using DayPicker, openPicker, isOpen, container) assert the input has
aria-haspopup="dialog" and the correct aria-expanded value before/after tabbing;
assert the popup element has role="dialog" when open; in the "enter on a date
cell" and "escape from inside the panel" tests, after moving focus into the
panel (use document.querySelector('td[tabindex="0"]') as activeCell) assert the
active cell has the appropriate semantic attributes (e.g., role="gridcell" or
role expected, and aria-selected or aria-current if applicable) and after
confirm/escape assert input's aria-expanded flips back to "false" and focus
returns to container.querySelector('input'); keep assertions adjacent to
existing focus checks and use the same helper variables (container, activeCell,
isOpen) so they are easy to locate.

In `@tests/range.spec.tsx`:
- Around line 1392-1433: Add a test in the "tab into open popup" suite that
covers the RangePicker's Escape close path: render DayRangePicker,
openPicker(container, 0), move focus into an active cell (e.g. query and focus
the 'td[tabindex="0"]' or use selectCell to ensure a focused cell), use
jest.useFakeTimers(), fire a keyDown with key 'Escape' on the focused cell, run
timers via act(() => jest.runAllTimers()), then assert isOpen() is false and
document.activeElement is the corresponding input
(container.querySelectorAll('input')[0] or [1] depending on which field was
active); restore timers with jest.useRealTimers().
🪄 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: 8d1ea2d7-7f9d-4cec-b993-cde046481155

📥 Commits

Reviewing files that changed from the base of the PR and between 0087213 and 2776fdd.

⛔ Files ignored due to path filters (3)
  • tests/__snapshots__/panel.spec.tsx.snap is excluded by !**/*.snap
  • tests/__snapshots__/picker.spec.tsx.snap is excluded by !**/*.snap
  • tests/__snapshots__/range.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (103)
  • assets/index.less
  • src/PickerInput/Popup/Footer.tsx
  • src/PickerInput/Popup/PresetPanel.tsx
  • src/PickerInput/Popup/index.tsx
  • src/PickerInput/RangePicker.tsx
  • src/PickerInput/Selector/Input.tsx
  • src/PickerInput/Selector/hooks/useInputProps.ts
  • src/PickerInput/SinglePicker.tsx
  • src/PickerInput/context.tsx
  • src/PickerInput/hooks/usePopupFocus.ts
  • src/PickerPanel/DatePanel/index.tsx
  • src/PickerPanel/DecadePanel/index.tsx
  • src/PickerPanel/MonthPanel/index.tsx
  • src/PickerPanel/PanelBody.tsx
  • src/PickerPanel/PanelHeader.tsx
  • src/PickerPanel/QuarterPanel/index.tsx
  • src/PickerPanel/TimePanel/TimePanelBody/TimeColumn.tsx
  • src/PickerPanel/TimePanel/TimePanelBody/index.tsx
  • src/PickerPanel/YearPanel/index.tsx
  • src/PickerPanel/context.ts
  • src/PickerPanel/index.tsx
  • src/interface.tsx
  • src/locale/am_ET.ts
  • src/locale/ar_EG.ts
  • src/locale/az_AZ.ts
  • src/locale/bg_BG.ts
  • src/locale/bn_BD.ts
  • src/locale/by_BY.ts
  • src/locale/ca_ES.ts
  • src/locale/cs_CZ.ts
  • src/locale/da_DK.ts
  • src/locale/de_DE.ts
  • src/locale/el_GR.ts
  • src/locale/en_GB.ts
  • src/locale/en_US.ts
  • src/locale/es_ES.ts
  • src/locale/es_MX.ts
  • src/locale/et_EE.ts
  • src/locale/eu_ES.ts
  • src/locale/fa_IR.ts
  • src/locale/fi_FI.ts
  • src/locale/fr_BE.ts
  • src/locale/fr_CA.ts
  • src/locale/fr_FR.ts
  • src/locale/ga_IE.ts
  • src/locale/gl_ES.ts
  • src/locale/he_IL.ts
  • src/locale/hi_IN.ts
  • src/locale/hr_HR.ts
  • src/locale/hu_HU.ts
  • src/locale/id_ID.ts
  • src/locale/is_IS.ts
  • src/locale/it_IT.ts
  • src/locale/ja_JP.ts
  • src/locale/ka_GE.ts
  • src/locale/kk_KZ.ts
  • src/locale/km_KH.ts
  • src/locale/kmr_IQ.ts
  • src/locale/kn_IN.ts
  • src/locale/ko_KR.ts
  • src/locale/lt_LT.ts
  • src/locale/lv_LV.ts
  • src/locale/mk_MK.ts
  • src/locale/ml_IN.ts
  • src/locale/mn_MN.ts
  • src/locale/mr_IN.ts
  • src/locale/ms_MY.ts
  • src/locale/my_MM.ts
  • src/locale/nb_NO.ts
  • src/locale/ne_NP.ts
  • src/locale/nl_BE.ts
  • src/locale/nl_NL.ts
  • src/locale/pl_PL.ts
  • src/locale/pt_BR.ts
  • src/locale/pt_PT.ts
  • src/locale/ro_RO.ts
  • src/locale/ru_RU.ts
  • src/locale/si_LK.ts
  • src/locale/sk_SK.ts
  • src/locale/sl_SI.ts
  • src/locale/sr_Cyrl_RS.ts
  • src/locale/sr_RS.ts
  • src/locale/sv_SE.ts
  • src/locale/ta_IN.ts
  • src/locale/te_IN.ts
  • src/locale/th_TH.ts
  • src/locale/tk_TK.ts
  • src/locale/tl_PH.ts
  • src/locale/tr_TR.ts
  • src/locale/ug_CN.ts
  • src/locale/uk_UA.ts
  • src/locale/ur_PK.ts
  • src/locale/uz_UZ.ts
  • src/locale/vi_VN.ts
  • src/locale/zh_CN.ts
  • src/locale/zh_TW.ts
  • tests/components.spec.tsx
  • tests/keyboard.spec.tsx
  • tests/multiple.spec.tsx
  • tests/new-range.spec.tsx
  • tests/picker.spec.tsx
  • tests/range.spec.tsx
  • tests/util/commonUtil.tsx

Comment thread src/locale/te_IN.ts
Comment on lines +31 to +38
previousMonth: 'మునుపటి నెల',
nextMonth: 'వచ్చే నెల',
previousYear: 'మునుపటి సంవత్సరం',
nextYear: 'తదుపరి సంవత్సరం',
previousDecade: 'మునుపటి దశాబ్దం',
nextDecade: 'తదుపరి దశాబ్దం',
previousCentury: 'మునుపటి శతాబ్దం',
nextCentury: 'తదుపరి శతాబ్దం',
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 描述:检查所有语言包的导航字符串是否包含键盘提示

echo "=== 检查包含键盘提示的语言包 ==="
rg -n "previousMonth.*\(PageUp\)|nextMonth.*\(PageDown\)" src/locale/

echo -e "\n=== 检查不包含键盘提示的语言包 ==="
rg -n "previousMonth:" src/locale/ | rg -v "PageUp"

echo -e "\n=== 统计 ==="
echo "包含 PageUp 提示的文件数:"
rg -l "PageUp" src/locale/ | wc -l
echo "总语言包文件数:"
fd -e ts . src/locale/ | wc -l

Repository: react-component/picker

Length of output: 8674


修正 te_IN 导航字符串与重大变更 #4 的键盘提示不一致

src/locale/te_IN.ts 的导航字段(如 previousMonth/nextMonth)已移除 PageUp/PageDown 提示,但全量语言包里仍有大量文件保留该提示(包含 PageUp/PageDown 的语言包文件数为 58/75),因此与“导航标签不再包含键盘提示”这一重大变更项 #4 不一致。

  • 要么为 te_IN 恢复键盘提示以匹配当前其它语言包的状态
  • 要么将所有仍含 PageUp/PageDown 的语言包统一移除提示,以匹配 te_IN
🤖 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/locale/te_IN.ts` around lines 31 - 38, The te_IN locale strings for
navigation (previousMonth, nextMonth, previousYear, nextYear, previousDecade,
nextDecade, previousCentury, nextCentury) lack the PageUp/PageDown keyboard
hints and are thus inconsistent with most other locales; restore the keyboard
hint text in each of these keys in src/locale/te_IN.ts to match the pattern used
in the other language files (e.g., append the same PageUp/PageDown parenthetical
hint used elsewhere), ensuring the exact keys named above are updated with the
localized hint wording.

Comment thread src/locale/zh_CN.ts
Comment on lines 22 to 23
previousMonth: '上个月 (翻页上键)',
nextMonth: '下个月 (翻页下键)',
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

导航文案里不要继续保留按键提示。

这些字符串现在会直接承担按钮/ARIA 文案,(翻页上键)(Control键加左方向键) 会被读屏读出来,也和这次“清理内嵌键盘提示”的变更目标不一致。建议保留纯动作文案,并同步清理其余 locale 更新。

建议修改
-  previousMonth: '上个月 (翻页上键)',
-  nextMonth: '下个月 (翻页下键)',
+  previousMonth: '上个月',
+  nextMonth: '下个月',
@@
-  previousYear: '上一年 (Control键加左方向键)',
-  nextYear: '下一年 (Control键加右方向键)',
+  previousYear: '上一年',
+  nextYear: '下一年',

Also applies to: 33-34

🤖 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/locale/zh_CN.ts` around lines 22 - 23, The locale strings previousMonth
and nextMonth in zh_CN.ts include embedded keyboard hints like "(翻页上键)" which
should be removed; update previousMonth: '上个月' and nextMonth: '下个月' and
similarly remove any inline key-tip text from other navigation-related keys in
this file (e.g., the analogous entries around the same block) so the strings
only contain the action labels used for buttons/ARIA.

Comment on lines +75 to +84
<NowButton className={`${prefixCls}-now`} disabled={nowDisabled} onClick={onInternalNow}>
{internalMode === 'date' ? locale.today : locale.now}
</NowButton>
);

// >>> OK
const okNode = needConfirm && (
<li className={`${prefixCls}-ok`}>
<Button disabled={invalid} onClick={onSubmit}>
{locale.ok}
</Button>
</li>
<OkButton disabled={invalid} className={`${prefixCls}-ok`} onClick={onSubmit}>
{locale.ok}
</OkButton>
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

给默认按钮补上 type="button"

NowButton / OkButton 默认回退为原生 <button>,这里没传 type,放进 <form> 里点击会触发表单提交,直接打断选择流程。

建议修改
-    <NowButton className={`${prefixCls}-now`} disabled={nowDisabled} onClick={onInternalNow}>
+    <NowButton
+      type="button"
+      className={`${prefixCls}-now`}
+      disabled={nowDisabled}
+      onClick={onInternalNow}
+    >
       {internalMode === 'date' ? locale.today : locale.now}
     </NowButton>
@@
-    <OkButton disabled={invalid} className={`${prefixCls}-ok`} onClick={onSubmit}>
+    <OkButton type="button" disabled={invalid} className={`${prefixCls}-ok`} onClick={onSubmit}>
       {locale.ok}
     </OkButton>
📝 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
<NowButton className={`${prefixCls}-now`} disabled={nowDisabled} onClick={onInternalNow}>
{internalMode === 'date' ? locale.today : locale.now}
</NowButton>
);
// >>> OK
const okNode = needConfirm && (
<li className={`${prefixCls}-ok`}>
<Button disabled={invalid} onClick={onSubmit}>
{locale.ok}
</Button>
</li>
<OkButton disabled={invalid} className={`${prefixCls}-ok`} onClick={onSubmit}>
{locale.ok}
</OkButton>
<NowButton
type="button"
className={`${prefixCls}-now`}
disabled={nowDisabled}
onClick={onInternalNow}
>
{internalMode === 'date' ? locale.today : locale.now}
</NowButton>
);
// >>> OK
const okNode = needConfirm && (
<OkButton type="button" disabled={invalid} className={`${prefixCls}-ok`} onClick={onSubmit}>
{locale.ok}
</OkButton>
🤖 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/PickerInput/Popup/Footer.tsx` around lines 75 - 84, The NowButton and
OkButton are rendered as native buttons without a type, so when placed inside a
form clicking them can trigger form submission; update the JSX for NowButton
(used with onInternalNow, className `${prefixCls}-now`) and OkButton (rendered
when needConfirm is true, disabled based on invalid, with onClick onSubmit and
className `${prefixCls}-ok`) to include type="button" to prevent accidental form
submits.

Comment on lines +221 to +228
const onContainerKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (e) => {
if (e.key === 'Tab') {
const container = e.currentTarget;
const focusable = Array.from(
container.querySelectorAll<HTMLElement>(
'button:not([disabled]), a:not([aria-disabled="true"]), td[tabindex="0"], li[tabindex="0"]',
),
).filter((el) => window.getComputedStyle(el).visibility !== 'hidden');
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

焦点循环的选择器写死了内置 DOM,定制内容会被跳过。

这里现在只会收集 button / a / td[tabindex="0"] / li[tabindex="0"]。但这个弹窗同时支持 panelRender,并且这次 PR 还把 components.nowButton / components.okButton 暴露成公开插槽;这些扩展点完全可能渲染成 inputselecttextarea 或任意带 tabIndex 的自定义节点。结果就是 Tab 循环会直接越过这些可聚焦控件,键盘导航在自定义场景下仍然是不完整的。

建议把选择器改成通用的 focusable 集合(表单控件、[href][tabindex]:not([tabindex="-1"]) 等),再统一过滤 disabled / aria-disabled / 不可见节点。

可参考的修正方向
-      const focusable = Array.from(
-        container.querySelectorAll<HTMLElement>(
-          'button:not([disabled]), a:not([aria-disabled="true"]), td[tabindex="0"], li[tabindex="0"]',
-        ),
-      ).filter((el) => window.getComputedStyle(el).visibility !== 'hidden');
+      const focusable = Array.from(
+        container.querySelectorAll<HTMLElement>(
+          [
+            'button',
+            'a[href]',
+            'input',
+            'select',
+            'textarea',
+            '[tabindex]:not([tabindex="-1"])',
+          ].join(', '),
+        ),
+      ).filter((el) => {
+        const style = window.getComputedStyle(el);
+        return (
+          !el.hasAttribute('disabled') &&
+          el.getAttribute('aria-disabled') !== 'true' &&
+          style.display !== 'none' &&
+          style.visibility !== 'hidden'
+        );
+      });
🤖 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/PickerInput/Popup/index.tsx` around lines 221 - 228, The Tab-focus
collection in onContainerKeyDown currently queries only 'button', 'a',
'td[tabindex="0"]', 'li[tabindex="0"]' so custom slot content (e.g.,
components.nowButton/components.okButton or panelRender outputs) gets skipped;
update the selector used in container.querySelectorAll inside onContainerKeyDown
to a generic focusable set (e.g., include input, select, textarea, [href], and
[tabindex]:not([tabindex="-1"]) ), then keep the existing filtering step but
extend it to exclude elements that are disabled, have aria-disabled="true", or
are not visible via getComputedStyle; ensure the rest of the function (focus
wrap logic) uses that new focusable list.

Comment on lines +27 to +40
<button
key={index}
onClick={() => {
onClick(executeValue(value));
}}
onMouseEnter={() => {
onHover(executeValue(value));
}}
onMouseLeave={() => {
onHover(null);
}}
>
{label}
</button>
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preset 按钮也需要显式声明 type="button"

现在这些 preset 项已经变成原生 <button>,未设置 type 时会默认提交外层表单,和“仅回填日期”的预期不符。

建议修改
         <button
           key={index}
+          type="button"
           onClick={() => {
             onClick(executeValue(value));
           }}
📝 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
<button
key={index}
onClick={() => {
onClick(executeValue(value));
}}
onMouseEnter={() => {
onHover(executeValue(value));
}}
onMouseLeave={() => {
onHover(null);
}}
>
{label}
</button>
<button
key={index}
type="button"
onClick={() => {
onClick(executeValue(value));
}}
onMouseEnter={() => {
onHover(executeValue(value));
}}
onMouseLeave={() => {
onHover(null);
}}
>
{label}
</button>
🤖 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/PickerInput/Popup/PresetPanel.tsx` around lines 27 - 40, The preset
buttons in PresetPanel are missing an explicit type and currently default to
type="submit", causing outer forms to submit; update the <button> elements
rendered in the PresetPanel component to include type="button" so clicks only
trigger onClick/onMouseEnter/onMouseLeave handlers (preserve executeValue,
onClick, onHover usage and label rendering).

Comment on lines +78 to 85
const label = generateConfig.locale.getWeek(locale.locale, date);

return (
<td
key="week"
role="rowheader"
aria-label={`Week ${label}`}
className={clsx(cellPrefixCls, `${cellPrefixCls}-week`, {
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

避免把周序号的读屏标签写死成英文。

这里的 aria-label={Week ${label}} 会让所有非英语 locale 都播报英文前缀,和这次补齐本地化无障碍文案的目标不一致。直接复用现有的 locale.week 就能避免混合语言输出。

💡 建议修改
-            aria-label={`Week ${label}`}
+            aria-label={`${locale.week} ${label}`}
📝 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
const label = generateConfig.locale.getWeek(locale.locale, date);
return (
<td
key="week"
role="rowheader"
aria-label={`Week ${label}`}
className={clsx(cellPrefixCls, `${cellPrefixCls}-week`, {
const label = generateConfig.locale.getWeek(locale.locale, date);
return (
<td
key="week"
role="rowheader"
aria-label={`${locale.week} ${label}`}
className={clsx(cellPrefixCls, `${cellPrefixCls}-week`, {
🤖 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/PickerPanel/DatePanel/index.tsx` around lines 78 - 85, The aria-label for
the week cell currently hardcodes an English prefix ("Week") which breaks
localization; change the aria-label construction in the DatePanel week cell to
use the localized prefix from the component locale (e.g., use locale.week or the
appropriate field on the locale object) when composing the label (where
generateConfig.locale.getWeek(locale.locale, date) produces label), so
aria-label becomes something like combining locale.week with the computed label
instead of the literal "Week".

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.

DatePicker, TimePicker: Improve accessibility

1 participant