修复下拉自动滚动时顶部首项被裁切(WEB-1194)
版本: 0.8.0 · 类型: 🐛 Bug Fix
问题
Select(Radix Select 分支:组合式用法与非 searchable 的声明式 options)展开后,若选中项位于列表靠后位置,下拉会自动滚动以显示它——此时顶部仍可见的第一项被裁切,紧贴面板顶边。该问题在「显示语言」设置上复现:中文用户的取值为「中文(简体)」(index 8),点开列表后列表下滚,顶部的「Español」被切掉一部分。
根因在于垂直内边距的落点。Radix SelectPrimitive.Viewport 自带 inline overflow: hidden auto 与 flex: 1,使 viewport 自身成为滚动容器(flex: 1 覆盖了 h-(--radix-select-trigger-height) 类,把它撑满到 content 的 max-h-[268px])。下拉的上下 py-(--Spacing_8) 此前加在该 viewport 上——即位于滚动区之内。因此浏览器把选中项滚入可视区时,顶部 8px padding 随内容一起滚走,最上方可见项失去缓冲、紧贴边缘被裁切。
该问题在早前那次「移除 SelectScrollUpButton / SelectScrollDownButton、改用 content 原生 overflow-y-auto」的重构后暴露:滚动范式变了,但 padding 仍留在(此时已原生滚动的)viewport 内。
改动文件
packages/design/src/components/Select/styles.tspackages/design/src/components/Select/Select.tsxpackages/design/src/components/Select/__tests__/Select.test.tsx
改动内容
- 将
SELECT_VIEWPORT_TOKEN_CLASS从mergeClass('pd-select__viewport', 'py-(--Spacing_8)', 'overflow-y-auto')精简为仅保留语义标识'pd-select__viewport':移除滚动区内的py-(--Spacing_8)(迁至 content 外框)及冗余的overflow-y-auto(Radix inlineoverflow: hidden auto已负责滚动)。 - 在
SelectContent的 content className 上追加py-(--Spacing_8)。Radix 给 popper content 元素施加display:flex; flex-direction:column,该 padding 落在不滚动的 flex 外框上恒定显示。 - 将
SELECT_DROPDOWN_MAX_HEIGHT由max-h-[268px]修正为max-h-[270px]。content 带 1px border,Tailwind preflight 下box-sizing: border-box,max-height含 border。268px 时 viewport(flex: 1)实际只有 268 − 2(border) − 16(padding) = 250px(< 7 × 36 = 252px),选中项靠后触发滚动时首项仍被裁切约 2px;计入上下 2px border 后 viewport 恰为 252px,正好 7 × 36px,滚动按整项对齐,首项完整显示。 - 未改动共享的
SELECT_CONTENT_TOKEN_CLASS——它被 searchable Popover(SELECT_POPOVER_CONTENT_CLASS)与MultiSelect(MULTI_SELECT_CONTENT_CLASS)复用,二者已各自处理内边距;把改动限定在SelectContent可避免它们出现重复内边距。 - 新增回归测试:断言垂直内边距落在 listbox(content 外框)而非 viewport 上,且 listbox 为
max-h-[270px]。
未滚动的面板视觉不变(面板边框与首项之间仍为 8px 间距),仅修正滚动裁切问题。searchable / MultiSelect 分支不受影响。