Table 使用手册
v2.7.1 · @snowui-design-system/components
许可阅读:首次阅读组件文档、源码或 npm 使用流程,先读完整 LICENSE;同任务同版本去重。公开 API 配置与内部实现修改分别按许可处理;全部组件使用统一运行包,源码权益以许可为准。
组件介绍
以语义化表格展示结构化数据,支持自适应列宽、局部横向滚动与加载状态,可自由组合表头和单元格。
使用选择
用于纯展示结构化数据,并组合 TableHeader、TableBody、TableRow、TableHead、TableCell。出现搜索、排序、勾选、操作列或分页时由 DataTable 协调,不在普通 Table 外复制数据管理行为。
通过 TableHeader / TableBody / TableRow 等保持合法表格层级。
columnWidths 保存列宽,columnId 对齐同一列;数据查询、选择、分页交给 DataTable。
快速开始
以下示例展示推荐的基本组合。更多场景与组合限制见后文。
API
未重新声明的继承能力请查所属基础组件文档;本表只列本组件源码具名公开属性。
使用边界与详细说明
列标题通过 TableHead 的 children 插槽传入,支持文字、图标及非交互组件组合。纯图标标题需提供可访问名称;可排序列不要在标题内嵌套交互控件。详见 TableHead 图标与组件标题。
Table 与 DataTable 的边界
普通 Table 是纯数据展示组件:只负责以原生表格语义渲染表头和数据行。普通表格不提供加载更多、checkbox 选择列、按钮操作列、排序、筛选、分页或搜索。
出现上述任一数据管理或操作能力时,使用 DataTable:
首次加载 Skeleton 与已有数据加载 Spinner 是 Table 的加载展示协议,不包含请求、加载更多、分页或其他数据管理逻辑;这些状态由调用方显式传入,或由 DataTable 协调。
布局模型
主布局模型:复合管理布局。
结构:
Root Frame(表格边界与 overlay scrollbar host)
Horizontal viewport(可聚焦的局部滚动区)
Native table(原生表格排版)
TableHeader / TableBody(
thead/tbody)TableRow(
tr)TableHead / TableCell(
th/td)
局部布局来源:Root Frame 不声明 row / column,不启用通用槽位排列;table 及各语义子项显式关闭 Auto Layout,保持浏览器原生表格布局。TableHead 内部的排序按钮和 Indicator、TableCell 的可选内容 row 属于各子组件的局部布局。
padding 归属:Table 根层和原生 table 不制造 padding;表头与数据单元格分别由 TableHead / TableCell 负责 padding。普通、selection 与 actions 单元格的左右 padding 按 Table 自身可用宽度与内容需求在 4px → 12px 之间流动:窄容器优先收敛到每侧 4px,使相邻列的最小视觉间距为 8px;宽容器恢复每侧 12px;表格外缘与角色浮层的左右留白至少 8px。上下 padding 保持 8px;已登记的 Head/Cell padding override 仍可整体接管。
gap 归属:原生表格列之间无通用 gap,视觉间距来自 Cell padding;TableCell 复合内容的 gap 由 TableCell 自身控制。
固有最小宽度:未声明 columnWidths / minWidth 时,原生 table-layout:auto 以各列内容的 min-content 宽度自动形成整表最小宽度,并至少填满宿主。普通可换行单元格以“最长不可断单词 / 片段 + 单元格左右 padding”为列的自动下限,不会逐字拆分标识符。lines={1} / nowrap 内容的整行是不可断片段,因而会产生更保守的列下限。任一显式 columnWidths、拖动列宽或固定宽度都属于调用方主动覆盖,该列改按 TableCell / TableHead 的截断规则处理。
普通 Table 不提供 checkbox 选择列或按钮操作列。TableHead/TableCell as="selection|actions" 只有位于 DataTable Context 中才激活;选择状态、角色布局与批量操作均由 DataTable 持有。
普通 Table 的 TableHead 默认不允许拖动修改列宽;需要时显式传入 resizable。DataTable 的普通列保持默认可拖动,显式 resizable={false} 可关闭。该默认能力只负责列宽,不会让普通 Table 自动拥有数据排序规则。
DataTable selection 角色中,TableHead 的全选 Checkbox 与 TableCell 的行 Checkbox 默认使用 calc(var(--size-4) + 0.0625rem),即 17×17px。额外的 0.0625rem 是 StyleSpec.md §2.2.2(源码参考:specs/maintainers/StyleSpec.md) 登记的 Table 视觉居中特例,不借用任何边框 Token,也不改变 Checkbox 组件自身的 16px 默认值;可通过 --snowui-table-selection-checkbox-size-override 覆盖。
首次加载列协议:TableHead 通过 Table Context 显式注册列结构;TableBody 在 loading 生效时按该结构生成真实 tr / td Skeleton rows。首次加载只消费同一语义表格内部的列注册;响应式布局另由 Table 私有控制器测量所拥有的原生表格网格。DataTable 可通过继承的同一 Context 提供“首次加载且 rows 为空”状态与规范化后的 pageSize;独立 Table 也可由 TableBody 显式启用;已知数据数量时传入 rowCount,未知时按外部容器可见高度估算,详见 TableBody 文档。
已有数据加载协议:loading 或 refreshing 生效且当前存在可见数据行时,TableBody 保留业务行并在末尾追加一个真实 tr / td 加载行;单元格通过 colspan 跨越已注册表头列,内部复用 SnowUI 通用 <Spinner size={16} /> 并在 40px 行内水平、垂直居中。表格加载 Spinner 默认 16×16px,可通过 Table 的 loadingSpinnerSize 统一设置。
Spinner 本体由 TableBody 内部创建,不要求页面在 Demo 或业务模板中手写。页面提供真实请求函数,并选择手动按钮调用 DataTableRenderState.loadMore() 或声明 loadMoreMode="auto";DataTable 内部负责自动观察、请求节流、并发保护、逐条合并数据、hasMore、Spinner 时机与新增行渐显。
DataTable 的自动加载由其内部表尾哨兵负责。页面只需声明 loadMoreMode="auto" 和数据源;默认需让表格底部越过最近纵向滚动区域底部,再继续下滚 80px 才触发,连续请求至少间隔 500ms。Table / DataTable 仍不创建纵向滚动容器,也不改变外层 ScrollArea 或页面的纵向滚动归属。
DataTable 每收到一条数据就提交一条可见 row,并通过 Table Context 让对应行的普通 TableCell 进入 Frame Appear 状态,显式执行纯 opacity: 0 → 1 动效,不产生尺寸缩放。selection / actions 角色 Cell 不消费该内部动效,避免行级 opacity 与控件自身 hover opacity 相乘导致 Checkbox / actions 暂时不可见。第一条新行开始渐显时立即隐藏 Spinner;后续数据按 DataTable 内部配置的展示间隔逐条出现,各行动效彼此重叠。展示间隔为 0 时,同批本地数据在同一轮更新中提交。TableRow / TableCell 显式传入的 whileAppear 仍优先于内部动效。
增量加载首次开始时,Table 会在请求数据提交前测量当前表头普通数据列的自然宽度,并把尚未由 columnWidths 显式设置的列锁定到该宽度。后续新行中的更宽内容只在既有列宽内截断,不再让原生 table-layout:auto 重新分配全部列宽、带动已有行左右移动。自动锁定只执行一次并保持到当前 Table 销毁;外部 columnWidths 与用户拖动列宽始终优先。
角色列布局:默认 roleLayout="auto" 根据宽度决定常驻或浮层。显式 roleLayout="column" 时,selection/actions 作为普通窄列参与表格列宽;roleLayout="overlay" 时,角色单元格仍保留合法 table DOM,但自身宽度归零并 sticky 到表格左右边缘,内容以覆盖块浮在表格行之上。覆盖块使用左右方向相反的横向交叠 blur strip 柔化后方内容:selection 从左向右透明,actions 从右向左透明;blur layer 常驻,控件自身独立淡入淡出,避免 hover 时重建模糊层。
在 DataTable 中的选择与覆盖布局
本节描述 DataTable 协调下的组合行为。roleOverlayLayers、roleOverlayBlurMode、roleOverlayUniformFeather 与 selectedRowIds 传给外层 DataTable;roleLayout 与 horizontalScroll 可由 Table 显式覆盖。
roleLayout="overlay" 的数据行 selection 采用“合法 table 单元格 + fixed 覆盖块”的两层结构:
TableCell as="selection"仍然渲染真实<td>,该<td>在 overlay 模式下宽度、最小宽度和最大宽度都归零,并 sticky 到左侧,只作为合法 table DOM 和定位锚点存在。单元格内部的
.snowui-table-selection-control通过getBoundingClientRect()读取当前tr的屏幕位置,在 scroll / resize / row resize 时同步为position: fixed。selection 覆盖块固定到行左侧,宽度为--size-8(32px),高度等于当前行高度,z-index设为最高层,保证压在第一列真实内容之上。Checkbox 和
.snowui-table-role-blur-layer位于同一个.snowui-table-selection-control容器内。Checkbox 作为真实交互控件保留在最上层;blur layer 使用aria-hidden且pointer-events: none,只承担视觉效果,不参与点击命中。渐进式模糊复用
components/src/lib/progressive-blur.ts。selection 方向为 left-to-right:左侧强模糊,向右逐渐清晰;actions 方向相反。Table Demo 中的控制条通过--snowui-table-role-overlay-blur-override和--snowui-table-role-overlay-width-override修改最大 blur 半径和可见宽度。模糊层数与模糊模式由
roleOverlayLayers和roleOverlayBlurMode两个 DataTable 属性统一控制,并通过 Table context 下发给同一个表格内的 selection / actions 角色块(表头 TableHead 与数据单元格 TableCell 共用同一控制器,无需逐处传参)。roleOverlayLayers决定渐进式模糊叠加的层数(层数越多强度过渡越平滑);roleOverlayBlurMode="uniform"时改用createUniformBlurStyles渲染单层、固定强度的普通背景模糊,便于和渐进式模糊做 A/B 对比。uniform模式下可再用roleOverlayUniformFeather(0~1)给模糊块内侧边缘加渐变 mask,柔化硬边界。角色块模糊层底色固定为白色(
white/100%);其叠加强度(透明度)由 CSS 变量--snowui-table-role-overlay-tint-opacity-override(默认0%,即不可见)控制,可用于在uniform背景模糊上叠加一层可调透明度的白色磨砂质感。0%时层为全透明,仅有backdrop-filter模糊;100%时为不透明白块。DataTable 持有
selectedRowIds与清除选择能力,并通过 Context 共享,供内置 TableToolbar 自动显示批量操作;页面无需重复传递selectedCount/onClearSelection。.snowui-table-role-blur-layer默认隐藏,只在行 hover、focus-within 或已选中时显示。这样未交互状态不会额外绘制 blur,选中后 Checkbox 与模糊状态保持可见。不要把第一列内容通过 padding 推开;selection 必须覆盖在第一列之上。若使用方在单元格内容上额外提升
z-index,会导致第一列内容压过 Checkbox 和 blur,破坏 overlay 语义。
交互命中按优先级处理:
点击 checkbox 本体时,由 Checkbox 的
onCheckedChange更新当前行选中态,并阻止事件冒泡到 TableRow,避免双重切换。因为 overlay checkbox 与第一列内容视觉重叠,TableRow 会兜底判断行左侧
32px区域的点击;即使浏览器命中到底下的第一列链接,也会preventDefault()并切换当前行选中态。点击单元格内的真实交互内容(
a、button、input、label、select、textarea、[role="button"]、[role="checkbox"])不会触发行选择。点击行内非交互空白区域会切换当前行选中态;再次点击取消选中。
选择归属:DataTable 持有 selectedRowIds,TableRow 以 rowId 注册当前渲染行。表头全选只作用于当前已渲染的行(分页场景即当前页),跨页已选 id 会保留。
表头全选 Checkbox 在常驻 column 布局一直显示;overlay 的可见规则:仅在以下情况显示——①hover 任意数据行(.snowui-table-viewport:has(.snowui-table-body .snowui-table-row:hover),与行内 Checkbox 同步出现);②hover 紧邻 selection 覆盖块的首个数据列表头(overlay 下即 Date 列表头,.snowui-table-head[data-as="selection"] + .snowui-table-head:hover);③直接 hover / 键盘聚焦全选浮层自身(保证指针从数据行上移到全选框时其仍可见、可点击);④表格存在选中态(data-selected="true")。hover 其他表头列(Stores、Subscriber 等)不会显示全选框。overlay 下全选容器恒为 pointer-events:none,仅其中的 Checkbox 子元素在触发时 pointer-events:auto。
Overlay hover 边缘渐进式透明(内置能力)
roleLayout="overlay" 下,TableCell / TableHead 内置一套 hover 边缘渐进式透明:用 CSS mask-image 渐变直接作用于单元格内容,让 checkbox / 操作按钮覆盖块正下方的内容从靠控件一侧渐隐到清晰,从而保证浮在内容之上的控件清晰可读。该能力为表格固有行为,参数固定、无对外开关。
规则:
触发时机:数据行内容在该行 hover(
.snowui-table-row:hover)时渐隐;表头仅第一列标题(紧邻 selection 覆盖块的 Date 列)的渐隐与全选 Checkbox 的出现时机完全一致——即 hover 任意数据行、hover 该列表头、hover / 聚焦全选浮层自身、或存在选中态时才渐隐;全选 Checkbox 不出现时表头也不渐隐。其余表头列(含 actions 一侧)不渐隐。作用对象:
checkbox 一侧 = 紧邻 selection 覆盖块的那一个内容单元格(
[data-as="selection"] + .snowui-table-cell的.snowui-table-cell-content),方向to right。actions 一侧 = actions 覆盖块之前的普通内容单元格,方向
to left。所有内容以当前可见行右边缘为同一坐标原点,跨列保持连续渐隐;横向滚动后浮层仍限制在 Table 视口内。selection 与 actions 同时作用于一个内容块时,使用交集保留两侧遮罩。
参数(可分别覆盖,三套相互独立):每套 Fade start / Fade end 都暴露成 CSS 覆盖变量,默认值与下方一致;可在
<Table>或任意祖先容器的style上单独设置。表头第一列:
--snowui-table-head-fade-start-override(默认实际 Checkbox 右边缘)→--snowui-table-head-fade-end-override(默认右边缘 +--size-5),过渡不随列宽变化。checkbox 一侧:
--snowui-table-selection-fade-start-override(默认实际 Checkbox 右边缘)→--snowui-table-selection-fade-end-override(默认右边缘 +--size-5),过渡不随列宽变化。actions 一侧:完全透明区默认覆盖到最左侧按钮的实际左边缘(实测按钮组宽度含右侧内边距,coverage 默认
1)。从该边缘向左用--size-5(名义 20px)固定长度过渡到清晰,不随按钮组宽度、按钮数量或响应式 padding 变化;随全局 Token 缩放。--snowui-table-actions-fade-coverage-override仍可显式调整覆盖比例;--snowui-table-actions-fade-feather-override默认不设置,仅兼容旧调用方显式设置的倍数语义,此时过渡终点仍为透明区宽度乘该倍数。
三处渐隐的
mask-image均复用 基础共享能力edge-fade(源码参考:components/src/lib/edge-fade.md)(createEdgeFadeMaskImage)生成并存到 CSS 变量,TableCell / TableHead 的 hover 状态规则只mask-image: var(...)消费。selection / head 通过私有布局适配table-selection-fade.ts测量实际 Checkbox 右边缘并在内容节点生成遮罩;actions 遮罩依赖每行实测按钮宽度,因此由各普通内容 TableCell 在自身作用域生成,并减去该内容块右边缘距可见行右边缘的偏移,确保能够读取行级--snowui-table-role-overlay-content-width。上面这些*-override变量即该能力对表格暴露的可配置参数。「悬浮操作层」本身的定位(sticky / fixed + JS 测量)属于表格布局职责,不在通用能力范围内。
退出同步:hover 结束且没有展开的操作菜单时,actions 整个浮层立即隐藏,与内容遮罩撤销同步,避免淡出按钮或模糊层留下残影;进入渐显保持不变。
不影响点击:
mask只改变可见度,不改变命中测试;被渐隐内容里的链接、按钮等仍可正常点击。与 blur 的关系:边缘渐隐与
.snowui-table-role-blur-layer背景模糊是两套独立机制。需要只保留渐隐时,把--snowui-table-role-overlay-blur-override设为0rem关闭背景模糊即可。激活行:
<TableRow active>由使用方或外部条件持续写入,默认绘制--black-4背景。它不是 hover 或 selected,不会改变 Checkbox 的选中状态;真实 hover 到激活行时,连续 hover 移动层与激活背景叠加。静态 hover 预览:在某个
<TableRow>上加data-force-hover="true",可让该行在不实际 hover 的情况下恒定呈现 hover 态(背景 / 行 checkbox / 行动按钮 / 两侧渐隐 / 表头全选与表头渐隐均会按该行触发),用于文档截图与视觉走查;业务持久态应使用activeProp。
实现入口为 TableCell.svelte(源码参考:components/src/components/TableCell.svelte) 与 TableHead.svelte(源码参考:components/src/components/TableHead.svelte)。TableCell 在已激活行的现有定位批次中读取内容坐标,不为各内容列新建 Observer。对每个普通内容块,actions 遮罩的两个色标分别是 fade-width − edge-offset 与 fade-width + 固定过渡长度 − edge-offset;允许负色标,使远离操作区的列保持清晰。TableCell 将 selection 与 actions 两层 mask 以 mask-composite: intersect 合成,角色控件自身不参与内容遮罩。
滚动归属:Table 自己创建唯一的局部横向 viewport,并通过共享 useOverlayScrollbar 将同一条横向轨道 sticky 到当前页面视口底部。轨道只在表格固有最小宽度超过宿主时显示,表格离开视口或到达底端后收回表格边界。不把宽表宽度传播为页面最小宽度,不应再用外层 ScrollArea 包裹 Table,也不得创建第二条同步滚动条。minWidth 仍可进一步扩大表格的固有宽度。Table / DataTable 仍不创建纵向滚动容器。吸底轨道必须高于 table 内容层;即使 TableBody 默认连续 Hover 将 table 提升为内容层,轨道仍完整接收 hover、pointer down 与拖动,不得由其下方的数据行截获。连续 Hover 层由局部横向 viewport 承载,其背景只绘制在当前可见的表格范围内,不得把隐藏列对应的背景泄露到 viewport 外。
示例
TableCell 默认 lines={1},原始文字不需要再包一层 Text。行 hover 时首尾单元格会自动形成 12px 圆角。
Keyword
保持合法 table DOM 树,不使用 div 模拟网格。
排序状态由上层 DataTable 通过共享 context 提供。
列宽持久化属于页面层,Table 只发出变化。
响应式收缩与恢复
响应式收列停留恢复:宽度 1s 不再变化后,仍显示的列恢复其原有透明度(包括表头的默认弱化透明度),位移自然完成。再次缩窄从当前透明度接续,已经收起的列保持隐藏;DataTable 复用同一规则。
渐隐计算与 OverflowActions 共用 responsive-exit(源码参考:components/src/lib/responsive-exit.md),统一动效边界见 响应式项目收起(源码参考:specs/maintainers/MotionPresetSpec.md)。
Table 是 Table / DataTable 的唯一布局计算入口,依据自身容器可用宽度和实际列内容,不使用设备断点。
roleLayout="auto":全部内容和首选间距放得下时,Checkbox / actions 占据常驻列并一直显示;首先收为 hover / 键盘焦点浮层,不删除角色列。已选 Checkbox、已展开操作菜单继续可见。再压缩单元格左右 padding:默认每侧从
--padding-3(12px)收至--padding-1(4px),相邻列最小视觉间距 8px;最左/最右可见单元格及角色浮层的外侧 padding 不低于--padding-2(8px)。字号、图标、行高和单元格内部 gap 不跟着缩小。显式 padding override 保留。常驻操作列会为实际按钮内容预留宽度;显式columnWidths.__actions仍优先,自动测量不回写调用方列宽。horizontalScroll默认 true:空间仍不足时保留所有普通列,使用 Table 局部横向滚动。horizontalScroll={false}:普通列默认允许隐藏,按当前 DOM 顺序从右向左收起;TableHead responsiveHide={false}的列及第一普通列始终保留。角色列不参与隐藏。下一待隐藏列在阈值前--size-5(名义 20px)的容器宽度区间内线性渐隐,仅表头与单元格内容同步渐隐,背景与分隔线始终保持完整。跨过阈值后原生网格直接确定目标布局,内容层使用共享 resize preset(当前 250ms)过渡位置并逐步揭示扩大的内容区域,不缩放文字。背景、分隔线与圆角不参与插值,不临时切换 table-layout 或把末列压缩至零宽。连续拖动时内容按当前宽度渐显恢复;停留恢复规则见下文。位移动画仅在可见列集合改变时启动;同一集合内连续拖动不重启动画,不对换行产生的纵向位置插值。快速反向跨过收列阈值时从当前显示位置和裁切边界接管。第一列、保护列、角色列和合并单元格不参与渐隐;prefers-reduced-motion: reduce保留直接切换。收到最后一列仍放不下时,若是没有硬尺寸的普通文本列,则限制为容器宽度:
nowrap内容保持不换行并显示省略号,默认 Tooltip 提供全文(包括lines={false} nowrap);允许换行的内容折行,长连续字符串也可断行。原始文本和数据不变,变宽后恢复自然布局。显式tooltip={false}仍可关闭 Tooltip。 多个保护列、显式列宽 /minWidth、复杂合并网格或单列中的按钮、输入、图片等不可压缩控件仍使用横向滚动兜底,不截掉操作。容器窄至无法容纳两侧 8px 留白时也保留滚动。关闭横向滚动代表优先收列与文本适配,不强制隐藏不可避免的溢出。隐藏列的 Head / Cell 一起退出布局、键盘顺序和辅助技术读取,但数据、排序和选择状态不变。最后可见普通列接管右侧圆角;仅一列时同时拥有左右圆角。
多行或跨列表头、跨行数据单元格保持横向滚动,不猜测合并网格的列对应关系;普通表体的跨列 empty / Spinner 单元格跟随可见列数更新跨度。
变宽时先恢复数据列,再恢复 padding,最后角色列回到常驻;隐藏列恢复基于未隐藏的原始内容测量,避免振荡。动态数据、列宽调整、字体加载和 Token 缩放会重新计算。
DataTable 的配置由 Context 下发;显式 Table 配置优先。普通 Table 复用间距、隐藏和滚动规则,不新增 选择 / 操作状态。旧显式 roleLayout="column" / "overlay" 保留固定布局含义;column 现在常驻显示角色控件。
操作角色预算
DataTable操作列按本表局部viewport计算20%/14rem/显式及拖动列宽上限的最小预算,先收操作再执行角色列、padding和原有数据响应式规则。预算包含padding与浮层渐隐覆盖;More最小可用尺寸优先,极窄滚动兜底。菜单展开冻结布局、关闭后更新;统一观察器和字体/Token失效触发重测,不新增逐行ResizeObserver。
Table 样式覆盖
先阅读 完整 LICENSE;同任务、同版本、同范围去重。
优先用组件公开 Props 匹配合适样式,尽可能保留原有视觉。确需改写时按 样式选择与改写顺序 使用自己的 class(含项目已有 Tailwind)或实例 style。以下名称来自源码实际消费的公开 override;先核对目标作用域,不修改私有 DOM。采用 SnowUI Token 时选择正确类别,外部应用不被要求安装一方 utilities。
Table 类型与状态
必填属性:无具名必填属性。
可双向绑定:bind:columnWidths。
继承声明:Omit<FrameProps, "children">。继承能力以基类公开文档为准;Omit 中的字段已排除,不能按基类原样使用。
以下为公开属性实际引用的类型声明,来自源码;Svelte Snippet 表示内容片段,ComponentProps 表示对应组件的 Props。
TableRoleLayout
来源:components/src/lib/table-context.svelte.ts
ResourceSize
来源:components/src/context.ts