跳到主要内容

修复下拉自动滚动时顶部首项被裁切(WEB-1194)

版本: 0.8.0 · 类型: 🐛 Bug Fix

WEB-1194

问题

Select(Radix Select 分支:组合式用法与非 searchable 的声明式 options)展开后,若选中项位于列表靠后位置,下拉会自动滚动以显示它——此时顶部仍可见的第一项被裁切,紧贴面板顶边。该问题在「显示语言」设置上复现:中文用户的取值为「中文(简体)」(index 8),点开列表后列表下滚,顶部的「Español」被切掉一部分。

根因在于垂直内边距的落点。Radix SelectPrimitive.Viewport 自带 inline overflow: hidden autoflex: 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.ts
  • packages/design/src/components/Select/Select.tsx
  • packages/design/src/components/Select/__tests__/Select.test.tsx

改动内容

  1. SELECT_VIEWPORT_TOKEN_CLASSmergeClass('pd-select__viewport', 'py-(--Spacing_8)', 'overflow-y-auto') 精简为仅保留语义标识 'pd-select__viewport':移除滚动区内的 py-(--Spacing_8)(迁至 content 外框)及冗余的 overflow-y-auto(Radix inline overflow: hidden auto 已负责滚动)。
  2. SelectContent 的 content className 上追加 py-(--Spacing_8)。Radix 给 popper content 元素施加 display:flex; flex-direction:column,该 padding 落在不滚动的 flex 外框上恒定显示。
  3. SELECT_DROPDOWN_MAX_HEIGHTmax-h-[268px] 修正为 max-h-[270px]。content 带 1px border,Tailwind preflight 下 box-sizing: border-boxmax-height 含 border。268px 时 viewport(flex: 1)实际只有 268 − 2(border) − 16(padding) = 250px(< 7 × 36 = 252px),选中项靠后触发滚动时首项仍被裁切约 2px;计入上下 2px border 后 viewport 恰为 252px,正好 7 × 36px,滚动按整项对齐,首项完整显示。
  4. 未改动共享的 SELECT_CONTENT_TOKEN_CLASS——它被 searchable Popover(SELECT_POPOVER_CONTENT_CLASS)与 MultiSelectMULTI_SELECT_CONTENT_CLASS)复用,二者已各自处理内边距;把改动限定在 SelectContent 可避免它们出现重复内边距。
  5. 新增回归测试:断言垂直内边距落在 listbox(content 外框)而非 viewport 上,且 listbox 为 max-h-[270px]

未滚动的面板视觉不变(面板边框与首项之间仍为 8px 间距),仅修正滚动裁切问题。searchable / MultiSelect 分支不受影响。