Skip to content

feat: 日历组件无障碍#3437

Merged
xiaoyatong merged 5 commits into
jdf2e:feat_v3.xfrom
m186:feat_v3.x
Apr 26, 2026
Merged

feat: 日历组件无障碍#3437
xiaoyatong merged 5 commits into
jdf2e:feat_v3.xfrom
m186:feat_v3.x

Conversation

@m186
Copy link
Copy Markdown
Contributor

@m186 m186 commented Apr 25, 2026

🤔 这个变动的性质是?

  • 新特性提交
  • 日常 bug 修复
  • 站点、文档改进
  • 演示代码改进
  • 组件样式/交互改进
  • TypeScript 定义更新
  • 包体积优化
  • 性能优化
  • 功能增强
  • 国际化改进
  • 重构
  • 代码风格优化
  • 测试用例
  • 分支合并
  • 其他改动(是关于什么的改动?)

🔗 相关 Issue

💡 需求背景和解决方案

☑️ 请求合并前的自查清单

⚠️ 请自检并全部勾选全部选项⚠️

  • 文档已补充或无须补充
  • 代码演示已提供或无须提供
  • TypeScript 定义已补充或无须补充
  • fork仓库代码是否为最新避免文件冲突
  • Files changed 没有 package.json lock 等无关文件

Summary by CodeRabbit

发布说明

  • 新功能

    • 日历卡片新增可选 weekdays 配置项,支持自定义工作日标题
    • 添加演示示例 Demo13,展示自定义标题与翻页交互
  • 可访问性改进

    • 为每个日期单元格提供更明确的 aria 标签与语义角色,区分“今天/禁用/选中”状态,改善屏幕阅读器体验
  • 类型更新

    • 日历卡片接口新增可选 weekdays 字段

@github-actions github-actions Bot added 3.x Target branch 3.x action:review This PR needs more reviews (less than 2 approvals) labels Apr 25, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

CalendarCard 新增可选 weekdays 属性并将周标题构建改为基于依赖的 useMemo,为每个日格生成包含今日/已选/禁用状态的 ariaLabel,暴露 ariaRole="button",内部渲染容器设为 ariaHidden(并有 TS 忽略)。

Changes

Cohort / File(s) Summary
核心组件变更
src/packages/calendarcard/calendarcard.taro.tsx
新增可选 weekdays prop(defaultProps.weekdays: []);使用 useMemo 根据 weekdaysfirstDayOfWeek 和 locale 计算周标题;为每个日格生成并暴露 ariaLabel,设置 ariaRole="button",内部渲染容器加 ariaHidden(含 TS 忽略)。
演示页更新
src/packages/calendarcard/demo.taro.tsx
在示例列表中新增 Demo13 展示区块并添加对应本地化字符串键 customWeekdays,渲染新的示例标题段落。
新增示例组件
src/packages/calendarcard/demos/taro/demo13.tsx
新增默认导出 Demo13 组件:设置 defaultValue2025-01-01,维护月份状态并在 onPageChange 中更新,示例传入自定义 weekdaysfirstDayOfWeek
类型定义
src/types/spec/calendarcard/base.ts
BaseCalendarCard 接口中新增可选属性 weekdays?: string[]

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • xiaoyatong
  • oasis-cloud
  • Alex-huxiyang

Poem

🐰 新周名自定,格中声更亲,
今日标一记,朗读不纷纷,
小兔点点头,日历更清新 ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning PR描述仅包含空白的贡献模板,所有必填项(变动性质、相关Issue、需求背景和解决方案)均未填写,自查清单项目也全部未勾选。 请填写变动性质(应选择'功能增强'或'新特性提交'),补充相关Issue链接,详细说明无障碍改动的具体问题和解决方案,并勾选完成的自查清单项目。
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 标题准确反映了PR的主要变动,即添加日历组件的无障碍功能支持(包括ariaLabel、ariaRole等)。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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

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

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

Caution

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

⚠️ Outside diff range comments (1)
src/packages/calendarcard/calendarcard.taro.tsx (1)

23-28: ⚠️ Potential issue | 🟡 Minor

weekdays 属性仅添加到 Taro 版本,与 H5 版本存在 API 不对称。

根据 src/packages/calendarcard/calendarcard.tsx:22-26defaultProps,H5 版本并未支持 weekdays 属性,仍直接使用 locale.calendaritem.weekdays。两端公共 API 行为不一致会让用户在跨端使用时感到困惑(同样的代码在 H5 端无效),且类型 TaroCalendarCardPropsCalendarCardProps 也会出现差异。建议同步在 H5 版本添加 weekdays 属性,或在文档中明确说明该属性仅 Taro 端支持。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/calendarcard.taro.tsx` around lines 23 - 28, The
Taro build adds a weekdays prop in defaultProps while the H5 CalendarCard lacks
it, causing asymmetric API and diverging types (TaroCalendarCardProps vs
CalendarCardProps); add weekdays support to the H5 implementation to match
behavior: update the H5 CalendarCard defaultProps to include weekdays (default
[]), thread the prop through the CalendarCard render/logic where
locale.calendaritem.weekdays is used, and update the shared prop types
(CalendarCardProps and TaroCalendarCardProps) to include weekdays so both builds
expose the same API, or alternatively document that weekdays is Taro-only if you
choose not to change H5.
🧹 Nitpick comments (1)
src/packages/calendarcard/calendarcard.taro.tsx (1)

471-481: ariaHidden 需要 @ts-ignore 绕过类型检查,建议补全类型或采用受支持的写法。

@tarojs/componentsView 类型定义中缺失 ariaHidden 属性,导致在此处(及项目其他组件如 radio.taro.tsxcheckbox.taro.tsx)需要使用 @ts-ignore。同一 JSX 中的 ariaLabelariaRole 都有支持,唯独 ariaHidden 需要绕过检查。建议:

  • 优先升级 @tarojs/components 或补全其类型声明,移除 @ts-ignore;或
  • 用受支持的写法避免类型冲突,例如改用其他兼容的无障碍方案。

重复的 @ts-ignore 会掩盖真正的类型错误,维护成本较高。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/calendarcard.taro.tsx` around lines 471 - 481, The
code is using `@ts-ignore` to bypass TypeScript errors for the View prop
ariaHidden in calendarcard.taro.tsx (occurring on the View elements that
renderDayTop/renderDay/renderDayBottom), which hides real typing issues; fix by
adding proper typings or using a supported prop: extend or augment the
`@tarojs/components` View props to include ariaHidden (declare module and add
ariaHidden?: boolean) or replace ariaHidden with a supported accessibility prop
(e.g., aria-hidden via a string index signature or using ariaHidden as a data-
attribute or the supported ariaLabel/ariaRole patterns) and remove the
`@ts-ignore` lines around the View elements (the unique symbols to locate are the
JSX <View className={`${prefixCls}-day-top`} ariaHidden>, <View
className={`${prefixCls}-day-inner`} ariaHidden>, and <View
className={`${prefixCls}-day-bottom`} ariaHidden>).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/packages/calendarcard/calendarcard.taro.tsx`:
- Around line 250-262: getAriaLabel currently only reads day.date which causes
identical labels for same numeric days from prev/next months; update
getAriaLabel (used with days array and predicates isActive/isDisable) to
distinguish non-current-month cells by appending month info (e.g. "上月30号"/"下月2号"
or full month name) when day.type !== 'current', or alternatively mark those
cells as aria-hidden and remove them from tab order (tabIndex=-1) to match
handleDayClick's filtering of non-current clicks; ensure isActive/isDisable
logic still applies and labels remain localized and consistent with existing
strings.
- Around line 250-262: getAriaLabel currently hardcodes Chinese strings and
breaks i18n; change it to use locale entries (e.g.,
locale.calendaritem.selected, .today, .day, .disabled) instead of literal
"已选定"/"今日"/"号"/"按钮变暗", and build the label by composing these localized tokens
together when computing getAriaLabel(day) (still using isActive, isDisable,
isToday to pick which tokens to combine); also update the surrounding comment to
remove the misleading "按钮" text (ariaRole="button" is set on the parent so the
role need not be repeated in the label).
- Around line 426-439: The current weekHeader is created with useState lazy
initializer, so it won't update when props like weekdays, firstDayOfWeek or
locale.calendaritem.weekdays change; replace the useState(() => { ... }) with a
useMemo that returns the same computed weekdaysData array and rotated slice, and
set its dependency array to [weekdays, firstDayOfWeek,
locale?.calendaritem?.weekdays] (or the exact locale weekdays value used) so
weekHeader recomputes when those inputs change; keep the mapping that produces {
name, key } and the slice/concatenate logic identical.

---

Outside diff comments:
In `@src/packages/calendarcard/calendarcard.taro.tsx`:
- Around line 23-28: The Taro build adds a weekdays prop in defaultProps while
the H5 CalendarCard lacks it, causing asymmetric API and diverging types
(TaroCalendarCardProps vs CalendarCardProps); add weekdays support to the H5
implementation to match behavior: update the H5 CalendarCard defaultProps to
include weekdays (default []), thread the prop through the CalendarCard
render/logic where locale.calendaritem.weekdays is used, and update the shared
prop types (CalendarCardProps and TaroCalendarCardProps) to include weekdays so
both builds expose the same API, or alternatively document that weekdays is
Taro-only if you choose not to change H5.

---

Nitpick comments:
In `@src/packages/calendarcard/calendarcard.taro.tsx`:
- Around line 471-481: The code is using `@ts-ignore` to bypass TypeScript errors
for the View prop ariaHidden in calendarcard.taro.tsx (occurring on the View
elements that renderDayTop/renderDay/renderDayBottom), which hides real typing
issues; fix by adding proper typings or using a supported prop: extend or
augment the `@tarojs/components` View props to include ariaHidden (declare module
and add ariaHidden?: boolean) or replace ariaHidden with a supported
accessibility prop (e.g., aria-hidden via a string index signature or using
ariaHidden as a data- attribute or the supported ariaLabel/ariaRole patterns)
and remove the `@ts-ignore` lines around the View elements (the unique symbols to
locate are the JSX <View className={`${prefixCls}-day-top`} ariaHidden>, <View
className={`${prefixCls}-day-inner`} ariaHidden>, and <View
className={`${prefixCls}-day-bottom`} ariaHidden>).
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3bf088cb-2733-4ee8-b36a-03e9545c0c80

📥 Commits

Reviewing files that changed from the base of the PR and between e409673 and 560fc19.

📒 Files selected for processing (1)
  • src/packages/calendarcard/calendarcard.taro.tsx

Comment on lines +250 to +262
const getAriaLabel = (day: CalendarCardDay) => {
const today = isToday(day)
// 日期选定时,朗读="已选定 1号 按钮"
if (isActive(day)) {
return today ? `已选定今日${day.date}号` : `已选定${day.date}号`
}
// 若不可选中,朗读=“3号 按钮 变暗”
if (isDisable(day)) {
return today ? `${day.date}号今日按钮变暗` : `${day.date}号按钮变暗`
}
// 未选定时,朗读=“2号 按钮”
return today ? `${day.date}号今日` : `${day.date}号`
}
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 | 🟡 Minor

未区分 prev/next 月份的日期,可能导致同一数字在网格中被读三次。

days 数组同时包含上月、本月、下月的日期。当前实现只读 day.date,例如月初网格里会出现 30号31号 等上月日期,与下月开头的日期混在一起,盲人用户会听到 "30号"、"30号"——无法分辨这是哪个月的 30 号。建议对 day.type !== 'current' 的单元格附加月份信息(或将其设为 ariaHidden / 不参与 tab 序),与 handleDayClick 中已经过滤非当前月点击的逻辑保持一致。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/calendarcard.taro.tsx` around lines 250 - 262,
getAriaLabel currently only reads day.date which causes identical labels for
same numeric days from prev/next months; update getAriaLabel (used with days
array and predicates isActive/isDisable) to distinguish non-current-month cells
by appending month info (e.g. "上月30号"/"下月2号" or full month name) when day.type
!== 'current', or alternatively mark those cells as aria-hidden and remove them
from tab order (tabIndex=-1) to match handleDayClick's filtering of non-current
clicks; ensure isActive/isDisable logic still applies and labels remain
localized and consistent with existing strings.

⚠️ Potential issue | 🟠 Major

aria 文案硬编码为中文,破坏国际化能力。

该组件其它文案(如 monthTitleweekdays)均通过 locale 提供本地化,但 getAriaLabel 直接拼接了 "已选定"、"今日"、"号"、"按钮变暗" 等中文字符串。非中文 locale 下屏幕阅读器仍会朗读中文,对盲人用户造成严重的可访问性退化。建议将这些文案抽到 locale.calendaritem 中(例如 selectedtodaydaydisabled 等键),由调用方按 locale 翻译。

另外,注释中提到 "已选定 1号 按钮"、"3号 按钮 变暗" 等期望朗读结果都包含 "按钮",但实际返回值中并没有 "按钮"。由于 ariaRole="button" 已在父级设置,多数读屏会自动朗读 role,因此 label 中不需重复,但建议同步更新注释以避免歧义。

🌐 建议改造方向(示意)
-  // 日期无障碍朗读
-  const getAriaLabel = (day: CalendarCardDay) => {
-    const today = isToday(day)
-    // 日期选定时,朗读="已选定 1号 按钮"
-    if (isActive(day)) {
-      return today ? `已选定今日${day.date}号` : `已选定${day.date}号`
-    }
-    // 若不可选中,朗读=“3号 按钮 变暗”
-    if (isDisable(day)) {
-      return today ? `${day.date}号今日按钮变暗` : `${day.date}号按钮变暗`
-    }
-    // 未选定时,朗读=“2号 按钮”
-    return today ? `${day.date}号今日` : `${day.date}号`
-  }
+  // 日期无障碍朗读(文案由 locale 提供,避免硬编码语言)
+  const getAriaLabel = (day: CalendarCardDay) => {
+    const a11y = locale.calendaritem.a11y // 需在 locale 中补充
+    const today = isToday(day)
+    const base = today ? a11y.today(day.date) : a11y.day(day.date)
+    if (isActive(day)) return a11y.selected(base)
+    if (isDisable(day)) return a11y.disabled(base)
+    return base
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/calendarcard.taro.tsx` around lines 250 - 262,
getAriaLabel currently hardcodes Chinese strings and breaks i18n; change it to
use locale entries (e.g., locale.calendaritem.selected, .today, .day, .disabled)
instead of literal "已选定"/"今日"/"号"/"按钮变暗", and build the label by composing these
localized tokens together when computing getAriaLabel(day) (still using
isActive, isDisable, isToday to pick which tokens to combine); also update the
surrounding comment to remove the misleading "按钮" text (ariaRole="button" is set
on the parent so the role need not be repeated in the label).

Comment thread src/packages/calendarcard/calendarcard.taro.tsx Outdated
</View>
<View className={`${prefixCls}-day-bottom`}>
{/* @ts-ignore */}
<View className={`${prefixCls}-day-bottom`} ariaHidden>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这个会有有效信息,被忽略~ 不需要处理 ariahidden

>
<View className={`${prefixCls}-day-top`}>
{/* @ts-ignore */}
<View className={`${prefixCls}-day-top`} ariaHidden>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

这个会有有效信息,被忽略~ 不需要处理 ariahidden

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: 4

🧹 Nitpick comments (2)
src/packages/calendarcard/demos/taro/demo13.tsx (2)

13-13: 局部变量 CalendarCardRef 与导入的同名类型重名,易混淆。

第 2 行从 @nutui/nutui-react-taro 导入了 CalendarCardRef 类型;第 13 行又以同名命名 useRef 返回值,使得后续 useRef<CalendarCardRef>(null) 在阅读上会与运行时变量产生歧义。建议将变量改为驼峰小写(如 calendarCardRefcalendarRef)。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/demos/taro/demo13.tsx` at line 13, The local ref
variable is named CalendarCardRef which conflicts with the imported type
CalendarCardRef; rename the runtime variable to a camelCase identifier (e.g.,
calendarCardRef or calendarRef) and update its declaration
useRef<CalendarCardRef>(null) and all references to that variable in this file
(e.g., event handlers, JSX refs) so the imported type CalendarCardRef remains
distinct from the runtime ref variable.

20-21: weekdays 起始项与 firstDayOfWeek 的对应关系容易让用户误解。

此处传入的 weekdays 以 "周日" 起始(索引 0=周日),同时 firstDayOfWeek={1}。组件内部会按 firstDayOfWeek 旋转数组,因此实际渲染顺序为 周一…周六, 周日,符合预期。但调用方很可能误以为数组的第 0 项就是首列,从而传入以 "周一" 开头的数组,结果反而错位。建议在文档/示例注释中明确:weekdays 必须以"周日"为索引 0 传入完整 7 项(与 locale.calendaritem.weekdays 的约定一致)。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/demos/taro/demo13.tsx` around lines 20 - 21,
Summary: The demo may confuse users because weekdays array index 0 must be
Sunday while firstDayOfWeek rotates display; explicitly state this requirement.
Fix: In the demo (around the weekdays and firstDayOfWeek props) add a clear
inline comment and/or example note that weekdays must be a full 7-item array
starting with "周日" (index 0 = Sunday) and that firstDayOfWeek only rotates the
display order; reference the props weekdays and firstDayOfWeek and mention the
convention matches locale.calendaritem.weekdays so callers do not supply a
weekday array starting at Monday.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/packages/calendarcard/calendarcard.taro.tsx`:
- Around line 480-481: Remove the unnecessary ariaHidden prop and the
accompanying `@ts-ignore` on the inner day container so screen readers can access
custom rendered content; edit the <View className={`${prefixCls}-day-inner`}
ariaHidden> (inside renderDay / calendar day cell) to simply be <View
className={`${prefixCls}-day-inner`}> and drop the `@ts-ignore`; if you intended
to hide non-essential decorative elements, explicitly apply aria-hidden only to
those specific sub-elements rather than the entire `${prefixCls}-day-inner`
container.

In `@src/packages/calendarcard/demo.taro.tsx`:
- Around line 99-102: The two examples Demo12 and Demo13 both use the same
translated.title, causing duplicate headings; add a new translation key (e.g.,
"a11y" or "weekdaysTitle") in the useTranslate hook and update the demo jsx to
use that new key for Demo13's title (replace the second {translated.title} with
{translated.a11y} or the chosen key) so each demo (Demo12 and Demo13) has a
distinct, descriptive heading.

In `@src/packages/calendarcard/demos/taro/demo13.tsx`:
- Line 7: The React component and default export are incorrectly named Demo1 in
demo13.tsx causing a naming collision; rename the component and default export
from Demo1 to Demo13 (update the component declaration and the export default)
so the component symbol Demo13 is used consistently within this file and avoids
conflict with demos/taro/demo1.tsx.
- Around line 8-12: 变量命名和类型不一致:把 dateStr 重命名为 month 或 currentMonth(并把 setDate
重命名为 setMonth)以反映它实际存储的是月份数字,且在初始化时用 date.getMonth() + 1 保持与 CalendarCard 的 1-12
约定一致;将 onPageChange 的参数从 any 改为已导出的类型 CalendarCardMonth(确保导入该类型)并在回调中使用
setMonth(val.month) 来更新月份,从而移除 any 并保证类型安全。

---

Nitpick comments:
In `@src/packages/calendarcard/demos/taro/demo13.tsx`:
- Line 13: The local ref variable is named CalendarCardRef which conflicts with
the imported type CalendarCardRef; rename the runtime variable to a camelCase
identifier (e.g., calendarCardRef or calendarRef) and update its declaration
useRef<CalendarCardRef>(null) and all references to that variable in this file
(e.g., event handlers, JSX refs) so the imported type CalendarCardRef remains
distinct from the runtime ref variable.
- Around line 20-21: Summary: The demo may confuse users because weekdays array
index 0 must be Sunday while firstDayOfWeek rotates display; explicitly state
this requirement. Fix: In the demo (around the weekdays and firstDayOfWeek
props) add a clear inline comment and/or example note that weekdays must be a
full 7-item array starting with "周日" (index 0 = Sunday) and that firstDayOfWeek
only rotates the display order; reference the props weekdays and firstDayOfWeek
and mention the convention matches locale.calendaritem.weekdays so callers do
not supply a weekday array starting at Monday.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 66a339c5-0450-4fc9-b7c7-70818c1f8f04

📥 Commits

Reviewing files that changed from the base of the PR and between 560fc19 and 0dd2b34.

📒 Files selected for processing (3)
  • src/packages/calendarcard/calendarcard.taro.tsx
  • src/packages/calendarcard/demo.taro.tsx
  • src/packages/calendarcard/demos/taro/demo13.tsx

Comment on lines +480 to +481
{/* @ts-ignore */}
<View className={`${prefixCls}-day-inner`} ariaHidden>
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

与维护者意图相悖:内层 ariaHidden 会丢失有效信息,建议移除。

维护者在前次评审中已明确表示 "这个会有有效信息,被忽略~ 不需要处理 ariahidden"。当前代码仍在 ${prefixCls}-day-inner 上设置了 ariaHidden 并以 @ts-ignore 屏蔽类型检查。这会让 renderDay 自定义内容(角标、农历、节日等业务关键信息)对屏幕阅读器不可见,且 @ts-ignore 还会掩盖该属性在 Taro View 类型上是否存在的真实问题。

♻️ 建议移除
-              {/* `@ts-ignore` */}
-              <View className={`${prefixCls}-day-inner`} ariaHidden>
+              <View className={`${prefixCls}-day-inner`}>
                 {renderDay ? renderDay(day) : day.date}
               </View>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/calendarcard.taro.tsx` around lines 480 - 481,
Remove the unnecessary ariaHidden prop and the accompanying `@ts-ignore` on the
inner day container so screen readers can access custom rendered content; edit
the <View className={`${prefixCls}-day-inner`} ariaHidden> (inside renderDay /
calendar day cell) to simply be <View className={`${prefixCls}-day-inner`}> and
drop the `@ts-ignore`; if you intended to hide non-essential decorative elements,
explicitly apply aria-hidden only to those specific sub-elements rather than the
entire `${prefixCls}-day-inner` container.

Comment thread src/packages/calendarcard/demo.taro.tsx
Comment thread src/packages/calendarcard/demos/taro/demo13.tsx Outdated
Comment on lines +8 to +12
const [dateStr, setDate] = useState(date.getMonth())
const onPageChange = (val: any) => {
console.log('onPageChange', val)
setDate(val.month)
}
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 | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's find and examine the demo file
fd -e tsx "demo13" src/packages/calendarcard/demos/

Repository: jdf2e/nutui-react

Length of output: 109


🏁 Script executed:

# Search for CalendarCardMonth type in the codebase
rg "CalendarCardMonth" src/packages/calendarcard/ --type ts --type tsx

Repository: jdf2e/nutui-react

Length of output: 89


🏁 Script executed:

# Check the CalendarCard component implementation, particularly around the month range
fd -e tsx "calendarcard.taro" src/packages/calendarcard/

Repository: jdf2e/nutui-react

Length of output: 109


🏁 Script executed:

# Look for the index/export files to see what's exported
fd -e ts "index" src/packages/calendarcard/ | head -20

Repository: jdf2e/nutui-react

Length of output: 136


🏁 Script executed:

# Read the demo13.tsx file
cat -n src/packages/calendarcard/demos/taro/demo13.tsx

Repository: jdf2e/nutui-react

Length of output: 1092


🏁 Script executed:

# Check the CalendarCardMonth type - search more broadly
rg "CalendarCardMonth" src/packages/calendarcard/

Repository: jdf2e/nutui-react

Length of output: 693


🏁 Script executed:

# Read the exports from the main index file
cat -n src/packages/calendarcard/index.taro.ts

Repository: jdf2e/nutui-react

Length of output: 367


🏁 Script executed:

# Read the taro component implementation to understand month handling
cat -n src/packages/calendarcard/calendarcard.taro.tsx | head -100

Repository: jdf2e/nutui-react

Length of output: 3275


🏁 Script executed:

# Final verification - check the type definition of CalendarCardMonth
rg "type CalendarCardMonth" src/ -A 5

Repository: jdf2e/nutui-react

Length of output: 43


🏁 Script executed:

# Verify the props type for onPageChange callback
rg "onPageChange" src/packages/calendarcard/calendarcard.taro.tsx -B 2 -A 2

Repository: jdf2e/nutui-react

Length of output: 524


变量命名误导和类型缺失

  • dateStr 实际存放的是 getMonth() 返回的数字(0-11),命名容易让人误以为是字符串。建议重命名为 monthcurrentMonth
  • onPageChange 形参 val: any 可改为已导出的 CalendarCardMonth 类型,避免 any 并提升对 val.month 字段的类型保护。
♻️ 建议修改
-import { CalendarCard, CalendarCardRef } from '@nutui/nutui-react-taro'
+import {
+  CalendarCard,
+  CalendarCardRef,
+  CalendarCardMonth,
+} from '@nutui/nutui-react-taro'
...
-  const [dateStr, setDate] = useState(date.getMonth())
-  const onPageChange = (val: any) => {
+  const [month, setMonth] = useState(date.getMonth() + 1)
+  const onPageChange = (val: CalendarCardMonth) => {
     console.log('onPageChange', val)
-    setDate(val.month)
+    setMonth(val.month)
   }

注:CalendarCard 内部的 month 取值范围为 1-12(参见 calendarcard.taro.tsx 第 70 行 date.getMonth() + 1),而 Date.prototype.getMonth() 返回 0-11,因此初始化时也应 +1 以保持一致,否则首次渲染前显示的值会比 onPageChange 回调后的值少 1。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/demos/taro/demo13.tsx` around lines 8 - 12,
变量命名和类型不一致:把 dateStr 重命名为 month 或 currentMonth(并把 setDate 重命名为
setMonth)以反映它实际存储的是月份数字,且在初始化时用 date.getMonth() + 1 保持与 CalendarCard 的 1-12
约定一致;将 onPageChange 的参数从 any 改为已导出的类型 CalendarCardMonth(确保导入该类型)并在回调中使用
setMonth(val.month) 来更新月份,从而移除 any 并保证类型安全。

@m186
Copy link
Copy Markdown
Contributor Author

m186 commented Apr 25, 2026

日历无障碍 & 星期自定义

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

♻️ Duplicate comments (2)
src/packages/calendarcard/calendarcard.taro.tsx (2)

480-481: ⚠️ Potential issue | 🟠 Major

与维护者反馈相左:内层 ariaHidden + @ts-ignore 仍未移除。

维护者在前次评审中明确表示 "这个会有有效信息,被忽略~ 不需要处理 ariahidden"。当前代码仍保留 ariaHidden@ts-ignore,会让 renderDay 自定义内容(角标、农历、节日等)对屏幕阅读器不可见,并掩盖 Taro View 类型上该属性是否有效的真实问题。建议直接去掉。

♻️ 建议修复
-              {/* `@ts-ignore` */}
-              <View className={`${prefixCls}-day-inner`} ariaHidden>
+              <View className={`${prefixCls}-day-inner`}>
                 {renderDay ? renderDay(day) : day.date}
               </View>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/calendarcard.taro.tsx` around lines 480 - 481, The
inner day View currently includes an unnecessary ariaHidden and a disabling
`@ts-ignore` which hides accessibility content and masks the underlying type
issue; remove the ariaHidden attribute and the preceding "@ts-ignore" from the
JSX element that renders the inner day (the View with className
`${prefixCls}-day-inner`) so custom renderDay content becomes visible to screen
readers and any TypeScript type errors surface for proper fixing (if TS flags
show the prop is invalid, update the component's props/type definitions instead
of suppressing the error).

250-268: ⚠️ Potential issue | 🟠 Major

aria 文案仍为硬编码中文,i18n 退化未修复。

此处将 "已选定"、"今日"、"号"、"按钮变暗" 等中文字面量直接拼接到 ariaLabel 中,非中文 locale 下屏幕阅读器仍会朗读中文,与组件其它通过 locale.calendaritem 提供本地化的文案不一致。建议把这些 token 抽到 locale.calendaritem 中(如 selected / today / day / disabled),由调用方按 locale 翻译。同时 ariaRole="button" 已在父级声明,标签里再带 "按钮" 会被读屏重复朗读,注释里的示例也建议同步更新。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/calendarcard.taro.tsx` around lines 250 - 268,
getAriaLabel currently builds Chinese-only aria strings by concatenating
literals like "已选定"/"今日"/"号"/"按钮变暗" and even repeats "按钮" despite
ariaRole="button" on the parent; replace these hardcoded tokens with
locale-driven tokens (e.g. use locale.calendaritem.selected, .today, .day,
.disabled) inside getAriaLabel so callers can supply translations, and remove
the explicit "按钮" wording from the strings to avoid duplicate reads; ensure
isActive/isDisable/isToday branches compose the final aria label by joining the
locale tokens in the same order (selected + today + month + day + dayToken,
disabled + month + day + disabledToken, or today + month + day etc.) using the
CalendarCardDay values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/packages/calendarcard/calendarcard.taro.tsx`:
- Around line 432-445: The useMemo call returning the weekdays array is
incorrectly destructured as const [weekHeader] = useMemo(...), which grabs only
the first weekday object instead of the full array; change this to directly
assign the memo result (e.g., const weekHeader = useMemo(...)) inside
src/packages/calendarcard/calendarcard.taro.tsx and any other similar
occurrences in that file (search for patterns like const [something] =
useMemo(...)/useMemo(() => arr) to ensure other H5 versions are fixed), so
weekHeader is the full array and weekHeader.map(...) works as expected.

---

Duplicate comments:
In `@src/packages/calendarcard/calendarcard.taro.tsx`:
- Around line 480-481: The inner day View currently includes an unnecessary
ariaHidden and a disabling `@ts-ignore` which hides accessibility content and
masks the underlying type issue; remove the ariaHidden attribute and the
preceding "@ts-ignore" from the JSX element that renders the inner day (the View
with className `${prefixCls}-day-inner`) so custom renderDay content becomes
visible to screen readers and any TypeScript type errors surface for proper
fixing (if TS flags show the prop is invalid, update the component's props/type
definitions instead of suppressing the error).
- Around line 250-268: getAriaLabel currently builds Chinese-only aria strings
by concatenating literals like "已选定"/"今日"/"号"/"按钮变暗" and even repeats "按钮"
despite ariaRole="button" on the parent; replace these hardcoded tokens with
locale-driven tokens (e.g. use locale.calendaritem.selected, .today, .day,
.disabled) inside getAriaLabel so callers can supply translations, and remove
the explicit "按钮" wording from the strings to avoid duplicate reads; ensure
isActive/isDisable/isToday branches compose the final aria label by joining the
locale tokens in the same order (selected + today + month + day + dayToken,
disabled + month + day + disabledToken, or today + month + day etc.) using the
CalendarCardDay values.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2dfa500e-7d5d-4451-a019-08398f27dc77

📥 Commits

Reviewing files that changed from the base of the PR and between 8a08fb8 and ecbf64a.

📒 Files selected for processing (1)
  • src/packages/calendarcard/calendarcard.taro.tsx

Comment thread src/packages/calendarcard/calendarcard.taro.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.

♻️ Duplicate comments (1)
src/packages/calendarcard/calendarcard.taro.tsx (1)

249-268: ⚠️ Potential issue | 🟠 Major

aria 文案仍硬编码为中文,i18n 仍未修复。

getAriaLabel 直接拼接 "已选定"、"今日"、"号"、"按钮变暗" 等中文字符串,与组件其余文案(monthTitleweekdays)走 locale 的做法不一致。在非中文 locale 下,屏幕阅读器仍会朗读中文,导致严重的可访问性回退。建议将这些片段抽到 locale.calendaritem 中(如 selected / today / day / disabled),由 locale 决定语言。

另外,行内注释("按钮"、"按钮 变暗")与实际返回值已经不一致——ariaRole="button" 由父级提供,label 中无需重复,建议同步更新注释以免误导后续维护者。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/calendarcard.taro.tsx` around lines 249 - 268,
getAriaLabel currently returns hard-coded Chinese fragments; extract all text
fragments into the locale map (e.g., add locale.calendaritem keys like selected,
today, daySuffix or dayLabel, disabled) and build the aria string using those
locale values inside getAriaLabel (use isToday, isActive, isDisable to pick
fragments). Remove redundant "按钮" wording from the label (ariaRole="button" is
provided elsewhere) and update comments to reflect that the label should not
include the word "button". Ensure monthTitle/weekdays locale pattern is followed
so ARIA strings are fully localized.
🧹 Nitpick comments (1)
src/packages/calendarcard/calendarcard.taro.tsx (1)

480-481: 改用 @ts-expect-error 取代 @ts-ignore 来处理 ariaHidden 的类型问题。

当前使用 @ts-ignore 会屏蔽该位置的所有类型错误。改用 @ts-expect-error 可以在类型问题解决后自动提醒,确保错误抑制不会遗留。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/packages/calendarcard/calendarcard.taro.tsx` around lines 480 - 481,
Replace the "// `@ts-ignore`" suppression above the JSX element that renders View
with className `${prefixCls}-day-inner` and the ariaHidden prop by using "//
`@ts-expect-error`" instead; locate the comment immediately before the JSX node in
calendarcard.taro.tsx (the View with ariaHidden) and change the directive so
TypeScript will fail the build once the prop's typing is fixed rather than
permanently silencing all type errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/packages/calendarcard/calendarcard.taro.tsx`:
- Around line 249-268: getAriaLabel currently returns hard-coded Chinese
fragments; extract all text fragments into the locale map (e.g., add
locale.calendaritem keys like selected, today, daySuffix or dayLabel, disabled)
and build the aria string using those locale values inside getAriaLabel (use
isToday, isActive, isDisable to pick fragments). Remove redundant "按钮" wording
from the label (ariaRole="button" is provided elsewhere) and update comments to
reflect that the label should not include the word "button". Ensure
monthTitle/weekdays locale pattern is followed so ARIA strings are fully
localized.

---

Nitpick comments:
In `@src/packages/calendarcard/calendarcard.taro.tsx`:
- Around line 480-481: Replace the "// `@ts-ignore`" suppression above the JSX
element that renders View with className `${prefixCls}-day-inner` and the
ariaHidden prop by using "// `@ts-expect-error`" instead; locate the comment
immediately before the JSX node in calendarcard.taro.tsx (the View with
ariaHidden) and change the directive so TypeScript will fail the build once the
prop's typing is fixed rather than permanently silencing all type errors.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 53d62dab-7efd-463d-b979-12e3247fb0e4

📥 Commits

Reviewing files that changed from the base of the PR and between ecbf64a and 0bf2c87.

📒 Files selected for processing (1)
  • src/packages/calendarcard/calendarcard.taro.tsx

@xiaoyatong xiaoyatong merged commit cb508df into jdf2e:feat_v3.x Apr 26, 2026
2 checks passed
xiaoyatong added a commit that referenced this pull request Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3.x Target branch 3.x action:review This PR needs more reviews (less than 2 approvals) size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants