月/年下拉打开时停在 1976 而非当前年份(WEB-1295)
版本: 0.9.0 · 类型: 🐛 Bug Fix
问题
打开日历(DatePicker)顶部的月份 / 年份下拉时,列表总是停在最顶部。对年份下拉而言,意味着每次打开都展示1976(最早的年份),即便当前选中年份是2026——用户得一路往下滚才能找到当前年。月份下拉存在同样的潜在问题。
根本原因
CalendarMonthCaption 用 Radix DropdownMenu 渲染月/年下拉。年份列表范围是当前年 ±50(START_YEAR = CURRENT_YEAR - 50 … END_YEAR = CURRENT_YEAR + 50),共 101 项,装在 max-h-[280px] 的滚动容器里。Radix 打开时默认把焦点落在列表首项并将其滚入可视区,因此容器停在顶部的 1976,当前选中年份被滚出视野。组件此前没有「打开时把选中项滚入可视区」的逻辑。
改动文件
packages/design/src/components/Calendar/CalendarMonthCaption.tsxpackages/design/src/components/Calendar/__tests__/Calendar.test.tsx
改动内容
- 给「当前月 / 当前年」对应的
DropdownMenuItemEntry追加itemProps: { 'data-current': 'true' }标记(月份按i === currentMonth,年份按year === currentYear);monthItems的useMemo依赖补上currentMonth。 - 两个下拉的
contentClassName前置标记类pd-calendar__scroll-menu(滚动容器即带max-h-[280px] overflow-y-auto的 content 外框)。 - 新增
useEffect(依赖[monthOpen, yearOpen]):任一下拉打开时,在一个requestAnimationFrame后(等 Radix 完成首项 autofocus 与布局)遍历.pd-calendar__scroll-menu,先对[data-current]项focus({ preventScroll: true })(把键盘焦点从首项移到当前项),再用getBoundingClientRect相对位移把它在滚动容器内居中(仅调整scrollTop,不触发页面滚动)。cleanup 取消该帧。 - 新增 2 条回归单测:打开年份下拉断言存在
[role="menuitem"][data-current="true"]且文案含2026;打开月份下拉断言当前项含Jun——锁定标记契约(happy-dom 无法验真实滚动,getBoundingClientRect恒返回 0)。
影响面
所有使用 Calendar / DatePicker(经 CalendarMonthCaption)的场景。下拉未打开时视觉与行为不变;仅在打开月/年下拉时把当前选中项居中展示。web4 经 workspace:* 直接引用 @plaud/design 源码,改动无需发版即生效。