跳到主要内容

月/年下拉打开时停在 1976 而非当前年份(WEB-1295)

版本: 0.9.0 · 类型: 🐛 Bug Fix

WEB-1295

问题

打开日历(DatePicker)顶部的月份 / 年份下拉时,列表总是停在最顶部。对年份下拉而言,意味着每次打开都展示1976(最早的年份),即便当前选中年份是2026——用户得一路往下滚才能找到当前年。月份下拉存在同样的潜在问题。

根本原因

CalendarMonthCaption 用 Radix DropdownMenu 渲染月/年下拉。年份列表范围是当前年 ±50(START_YEAR = CURRENT_YEAR - 50END_YEAR = CURRENT_YEAR + 50),共 101 项,装在 max-h-[280px] 的滚动容器里。Radix 打开时默认把焦点落在列表首项并将其滚入可视区,因此容器停在顶部的 1976,当前选中年份被滚出视野。组件此前没有「打开时把选中项滚入可视区」的逻辑。

改动文件

  • packages/design/src/components/Calendar/CalendarMonthCaption.tsx
  • packages/design/src/components/Calendar/__tests__/Calendar.test.tsx

改动内容

  1. 给「当前月 / 当前年」对应的 DropdownMenuItemEntry 追加 itemProps: { 'data-current': 'true' } 标记(月份按 i === currentMonth,年份按 year === currentYear);monthItemsuseMemo 依赖补上 currentMonth
  2. 两个下拉的 contentClassName 前置标记类 pd-calendar__scroll-menu(滚动容器即带 max-h-[280px] overflow-y-auto 的 content 外框)。
  3. 新增 useEffect(依赖 [monthOpen, yearOpen]):任一下拉打开时,在一个 requestAnimationFrame 后(等 Radix 完成首项 autofocus 与布局)遍历 .pd-calendar__scroll-menu,先对 [data-current]focus({ preventScroll: true })(把键盘焦点从首项移到当前项),再用 getBoundingClientRect 相对位移把它在滚动容器内居中(仅调整 scrollTop,不触发页面滚动)。cleanup 取消该帧。
  4. 新增 2 条回归单测:打开年份下拉断言存在 [role="menuitem"][data-current="true"] 且文案含 2026;打开月份下拉断言当前项含 Jun——锁定标记契约(happy-dom 无法验真实滚动,getBoundingClientRect 恒返回 0)。

影响面

所有使用 Calendar / DatePicker(经 CalendarMonthCaption)的场景。下拉未打开时视觉与行为不变;仅在打开月/年下拉时把当前选中项居中展示。web4 经 workspace:* 直接引用 @plaud/design 源码,改动无需发版即生效。