生态产品多个设计器现已发布候选版本

查看生态总览
跳转到内容

GridList 网格列表 new ​

排列一组可选择、可执行主操作,并且每行还能放独立按钮的记录。它使用 ARIA grid/row/gridcell,而不是把按钮塞进 option;因此行选择与行内操作各有自己的焦点和事件。

用法 ​

点击行只改变选择,行内按钮执行自己的动作

项目
文档站
组件文档与示例
管理后台
运营与权限配置
移动端
现场工作台
已选:docs;尚未执行行内操作

组件结构 ​

加粗的是必需部件。

data-scope="grid-list":root · label · row · row-selection-indicator · row-content · row-text · row-description · row-actions · row-action · empty · loading

示例 ​

多选 ​

Space 切换当前行,Shift + 方向键、Shift + Space 与 Shift + 点击把锚点到那一行的一段并进选中,Ctrl 或 Cmd+A 选择或清空全部可用行

读取
写入
发布
权限:read

可拖动 ​

GridList 负责选择和行内按钮,Sortable 负责指针与键盘重排

需求梳理
交互设计
开发实现

Action List ​

不保留选择,Enter 或点击行触发主操作,行内按钮仍独立

打开项目
复制项目
归档项目
等待操作

设计指引 ​

何时使用 ​

  • 每行既能选中,又有编辑、预览、删除等独立操作。
  • 记录不需要按列对照,不值得升级为表格。
  • 需要与 Sortable 组合,用指针或键盘调整行顺序。

何时不用 ​

  • 只有选择,没有行内按钮:使用列表框。
  • 只有展示和按钮,没有选择或行主操作:使用列表。
  • 多个字段必须按列比较、排序或筛选:使用表格。

特性 ​

  • selectionMode 支持 none、single 与 multiple;none 是 Action List 模式。
  • 整组只有一个行级 Tab 停靠点;上下方向键、Home/End 与连打检索只在行焦点上工作。
  • Space 改变选择,Enter 触发行主操作;焦点在 row-action 时完全交给原生按钮。
  • 多选下 Shift 扩选:Shift + 方向键 / Home / End 移动焦点并把锚点到新焦点行那一段并进选中,Shift + Space 与 Shift + 点击扩到那一行。每一次扩选都从扩选开始前的选中集重算,往回扩即收回;禁用行占着位置但不被收进去。
  • row-actions 是独立 gridcell,按钮点击不会冒泡成行选择。
  • 在途分两种:还没有行时 loading 占位露面,一枚加载环排在文案之前;已有行时重新取数不换成占位,行保留上一帧淡下,取完再淡回。两种都由 root 报告 aria-busy。
  • 与 Sortable 组合即可获得指针拖动、键盘拖动、落点线和读屏播报;GridList 不复制拖拽协议。
  • collection 提供行标题、说明、禁用和语气的事实源;作者仍负责铺设各部件。

最佳实践 ​

  • 每行只保留一到两个高频按钮,更多操作收进 Menu。
  • 行主操作和行内按钮使用不同动词,不让同一点击产生两个结果。
  • 可排序时始终显示拖拽把手,不把整行点击与拖动混在同一命中区。

API 参考 ​

产物 ​

层值
自定义元素<xh-grid-list>
Vue 组件XhGridListEmpty XhGridListLabel XhGridListLoading XhGridListRoot XhGridListRow XhGridListRowAction XhGridListRowActions XhGridListRowContent XhGridListRowDescription XhGridListRowSelectionIndicator XhGridListRowText
组合式函数useGridList
状态机gridListMachine
皮肤@xihan-ui/styles/grid-list.css

Props ​

属性类型必填说明
labelledboolean作者渲染了 label 部件时置真,由适配器统计而不是判断标题文字是否有值。 为假时可聚焦部件不把 label 的 id 写进 aria-labelledby:指向未渲染的 id 是无效引用,作者写在控件上的 aria-label 也会被它压住。
collectionGridListNode[]
valuestring | string[]
defaultValuestring | string[]
selectionModeGridListSelectionModenone 只保留行主操作与行内按钮;single / multiple 开启选择。默认 single。
disabledboolean
readOnlyboolean
invalidboolean
loadingboolean取数在途:root 报告 aria-busy;还没有行时 loading 占位露面,已有行时行保留上一帧淡下、不接指针。
loopboolean
typeaheadboolean
dirDirection
variantControlVariant
toneTone
sizeSize
translationsPartial<GridListTranslations>
onValueChange(details: GridListValueChangeDetails) => void
onAction(details: GridListActionDetails) => voidEnter 或 selectionMode=none 时点击行触发;行内按钮保留自己的原生事件。

GridListNode ​

collection 的元素。

字段类型必填说明
valuestring是
labelstring
descriptionstring
disabledboolean
toneTone

事件 ​

自定义元素将载荷放在 detail;Vue 使用同名 emit。

事件载荷说明
value-changeGridListValueChangeDetails选择变化;detail 为
actionGridListActionDetails行主操作;detail 为

插槽 ​

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhGridListRootdefault—

React 适配器 props ​

只列各组件自己声明的那些:继承自 ComponentPropsWithRef 的 DOM 属性不在其中,根组件上与上面 Props 表同名的也不重复列。Vue 的对应物是上面的插槽表。

React 组件属性类型必填说明
XhGridListRootchildrenReactNode
XhGridListRowvaluestring是
XhGridListRowdisabledboolean

状态 ​

公开状态写入 data-state。

部件取值
row'checked' | 'unchecked'
row-selection-indicator'checked' | 'unchecked'
row-content'checked' | 'unchecked'
row-text'checked' | 'unchecked'
row-description'checked' | 'unchecked'
row-actions'checked' | 'unchecked'
row-action'checked' | 'unchecked'

以下名称仅用于内部状态机。

状态:idle

事件:VALUE.SET · ROW.SELECT · ROW.TOGGLE · ROW.EXTEND · ROW.ACTION · ROW.FOCUS · GRID.BLUR · PRESS.START · PRESS.END

判据:canPress

connect API ​

getXxxProps() 返回对应部件的宿主属性。

成员类型说明
valuestring[]
collectionreadonly GridListNodeMeta[]
selectionModeGridListSelectionMode
focusedValuestring | null
disabledboolean
readOnlyboolean
invalidboolean
loadingboolean
isSelected(value: string) => boolean
setValue(next: string[]) => void
select(value: string) => void
toggle(value: string) => void
action(value: string) => void
getRootProps() => T['element']
getLabelProps() => T['element']
getRowProps(props: GridListRowProps) => T['element']
getRowSelectionIndicatorProps(props: GridListRowProps) => T['element']
getRowContentProps(props: GridListRowProps) => T['element']
getRowTextProps(props: GridListRowProps) => T['element']
getRowDescriptionProps(props: GridListRowProps) => T['element']
getRowActionsProps(props: GridListRowProps) => T['element']
getRowActionProps(props: GridListRowProps) => T['button']
getEmptyProps() => T['element']
getLoadingProps() => T['element']

无障碍 ​

键盘 ​

规格出处:W3C APG

按键生效条件行为
Tab / Shift+Tabfocus outside grid list进入当前锚点行;行内按钮保持原生 Tab 次序
ArrowDownfocus on row焦点移到下一行;到末尾时按 loop 决定是否回绕
ArrowUpfocus on row焦点移到上一行;到开头时按 loop 决定是否回绕
Homefocus on row焦点移到第一行
Endfocus on row焦点移到最后一行
Spacefocus on selectable row单选时选中这一行,多选时切换这一行;不触发行内按钮
Shift+ArrowDown / Shift+ArrowUp / Shift+Home / Shift+Endfocus on row, selectionMode=multiple焦点移动,并把锚点到新焦点行那一段并进扩选开始前的选中;往回扩即收回,禁用行不被收进去
Shift+Spacefocus on row, selectionMode=multiple把锚点到焦点行那一段并进扩选开始前的选中;没有锚点时切换这一行并记为锚点
Enterfocus on row触发行主操作;未提供主操作且允许选择时改为选中这一行
Ctrl+A / Cmd+Afocus on multiple grid list选中全部可选行;已经全选时取消全部可选行
单个可打印字符focus on row, typeahead 未关闭按行标题连打检索,只移动焦点
Enter / Spacefocus on inline button交给原生按钮;不改变行选中状态,也不触发行主操作

ARIA ​

以下属性由 connect 生成。

部件属性值
rootaria-busy'true' | undefined
rootaria-disabled'true' | 'false'
rootaria-invalid'true' | 'false'
rootaria-labeltranslations.root
rootaria-labelledbylabel 部件的 id | undefined
rootaria-multiselectable'true' | undefined
rootaria-readonly'true' | 'false'
rootrole'grid'
rowaria-disabled'true' | 'false'
rowaria-selected'true' | 'false' | undefined
rowrole'row'
row-selection-indicatoraria-hidden'true'
row-contentrole'gridcell'
row-actionsrole'gridcell'

样式参考 ​

皮肤 ​

@xihan-ui/styles/grid-list.css 按 [data-scope="grid-list"][data-part="root"] 部件选择器书写,发布产物以挂载类 .xh-scope-grid-list 代替其中的 data-scope(特异性相同),位于 xihan.components 层。覆盖样式使用 xihan.overrides,部件选择器照常可用。

forced-colors: active 下另有一套规则:颜色交给系统,边框与状态标记改用系统色关键字。

数据属性 ​

由 connect 生成;条件不成立时不输出无值属性。

部件属性值
rootdata-disabled''(条件成立时才出现)
rootdata-invalid''(条件成立时才出现)
rootdata-loading''(条件成立时才出现)
rootdata-readonly''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-toneprops.tone
rootdata-variantprops.variant
labeldata-disabled''(条件成立时才出现)
rowdata-disabled''(条件成立时才出现)
rowdata-highlighted''(条件成立时才出现)
rowdata-pressed''(条件成立时才出现)
rowdata-state'checked' | 'unchecked'
rowdata-tonemetaOf.get(row.value)?.tone
rowdata-xh-collection-context'page'
rowdata-xh-collection-item''
rowdata-xh-collection-sizeprops.size
row-selection-indicatordata-disabled''(条件成立时才出现)
row-selection-indicatordata-highlighted''(条件成立时才出现)
row-selection-indicatordata-state'checked' | 'unchecked'
row-selection-indicatordata-xh-check-mark'checked' | 'unchecked'
row-selection-indicatordata-xh-check-mark-profile'box'
row-selection-indicatordata-xh-collection-slot'prefix'
row-contentdata-disabled''(条件成立时才出现)
row-contentdata-highlighted''(条件成立时才出现)
row-contentdata-state'checked' | 'unchecked'
row-textdata-disabled''(条件成立时才出现)
row-textdata-highlighted''(条件成立时才出现)
row-textdata-state'checked' | 'unchecked'
row-textdata-xh-collection-slot'text'
row-descriptiondata-disabled''(条件成立时才出现)
row-descriptiondata-highlighted''(条件成立时才出现)
row-descriptiondata-state'checked' | 'unchecked'
row-descriptiondata-xh-collection-slot'description'
row-actionsdata-disabled''(条件成立时才出现)
row-actionsdata-highlighted''(条件成立时才出现)
row-actionsdata-state'checked' | 'unchecked'
row-actiondata-disabled''(条件成立时才出现)
row-actiondata-highlighted''(条件成立时才出现)
row-actiondata-state'checked' | 'unchecked'
row-actiondata-xh-action-control''
row-actiondata-xh-action-display'always'
row-actiondata-xh-action-profile'text'
row-actiondata-xh-action-size'xs'
row-actiondata-xh-action-variant'ghost'
loadingdata-loading''(条件成立时才出现)
loadingdata-xh-loading-ring''

CSS 变量 ​

本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。

变量部件CSS 属性状态默认来源说明
--xh-grid-list-bgrootbackgrounddefault
variant=outline
variant=subtle
--xh-bg-subtle
--xh-bg-surface
transparent
grid-list 的 root 部件 background 覆盖槽。
--xh-grid-list-borderrootborder-colorvariant=outline--xh-border-defaultgrid-list 的 root 部件 border-color 覆盖槽。
--xh-grid-list-border-invalidrootborder-colorinvalid--xh-border-invalidgrid-list 的 root 部件 border-color 覆盖槽。
--xh-grid-list-gaprootgapdefault--xh-list-option-gapgrid-list 的 root 部件 gap 覆盖槽。
--xh-grid-list-icon-sizeroot--xh-icon-sizedefault
size=lg
size=sm
--xh-glyph-size-lg
--xh-glyph-size-md
--xh-glyph-size-sm
grid-list 的 root 部件 --xh-icon-size 覆盖槽。
--xh-grid-list-label-fglabelcolordefault--xh-fg-defaultgrid-list 的 label 部件 color 覆盖槽。
--xh-grid-list-label-font-sizelabelfont-sizedefault--xh-text-label-sizegrid-list 的 label 部件 font-size 覆盖槽。
--xh-grid-list-label-font-weightlabelfont-weightdefault--xh-font-weight-mediumgrid-list 的 label 部件 font-weight 覆盖槽。
--xh-grid-list-label-pxlabelpadding-inlinedefault--xh-control-px-mdgrid-list 的 label 部件 padding-inline 覆盖槽。
--xh-grid-list-label-pylabelpadding-blockdefault--xh-space-1grid-list 的 label 部件 padding-block 覆盖槽。
--xh-grid-list-prootpaddingdefault--xh-space-1grid-list 的 root 部件 padding 覆盖槽。
--xh-grid-list-radiusrootborder-radiusdefault--xh-shape-surfacegrid-list 的 root 部件 border-radius 覆盖槽。
--xh-grid-list-row-action-font-sizerow-actionfont-sizedefault--xh-control-font-smgrid-list 的 row-action 部件 font-size 覆盖槽。
--xh-grid-list-row-actions-gaprow-actionsgapdefault--xh-space-1grid-list 的 row-actions 部件 gap 覆盖槽。
--xh-grid-list-row-actions-msrow-actionsmargin-inline-startdefault--xh-control-gap-mdgrid-list 的 row-actions 部件 margin-inline-start 覆盖槽。
--xh-grid-list-row-bg-selectedrowbackground-colordisabled
error
highlighted
is(:focus-visible, [data-highlighted])
is([aria-selected='true'], [data-selected])
not(:focus-visible)
not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error])
selected
xh-collection-context=page
--xh-bg-brand-subtlegrid-list 的 row 部件 background-color 覆盖槽。
--xh-grid-list-row-content-gaprow-contentgapdefault--xh-space-1grid-list 的 row-content 部件 gap 覆盖槽。
--xh-grid-list-row-description-fgrow-descriptioncolordefault--xh-fg-mutedgrid-list 的 row-description 部件 color 覆盖槽。
--xh-grid-list-row-description-font-sizerow-descriptionfont-sizedefault--xh-control-caption-mdgrid-list 的 row-description 部件 font-size 覆盖槽。
--xh-grid-list-row-fg-selectedrowcolordisabled
error
highlighted
hover
is(:active, [data-pressed])
is(:focus-visible, [data-highlighted])
is([aria-selected='true'], [data-selected])
not([aria-disabled='true'], [data-disabled], [aria-busy='true'], [data-error])
pressed
selected
xh-collection-context=page
--xh-fg-on-brand-subtlegrid-list 的 row 部件 color 覆盖槽。
--xh-grid-list-row-indicator-bgrow-selection-indicatorbackgrounddefaulttransparentgrid-list 的 row-selection-indicator 部件 background 覆盖槽。
--xh-grid-list-row-indicator-bg-selectedrow-selection-indicatorbackgroundstate=checked--xh-_grid-list-indicator-accentgrid-list 的 row-selection-indicator 部件 background 覆盖槽。
--xh-grid-list-row-indicator-borderrow-selection-indicatorborderdefault--xh-border-controlgrid-list 的 row-selection-indicator 部件 border 覆盖槽。
--xh-grid-list-row-indicator-border-selectedrow-selection-indicatorborder-colorstate=checked--xh-_grid-list-indicator-accentgrid-list 的 row-selection-indicator 部件 border-color 覆盖槽。
--xh-grid-list-row-indicator-fg-selectedrow-selection-indicatorcolordefault--xh-_grid-list-indicator-on-accentgrid-list 的 row-selection-indicator 部件 color 覆盖槽。
--xh-grid-list-row-indicator-glyph-sizerow-selection-indicator--xh-icon-sizedefault--xh-_grid-list-indicator-glyphgrid-list 的 row-selection-indicator 部件 --xh-icon-size 覆盖槽。
--xh-grid-list-row-indicator-merow-selection-indicatormargin-inline-enddefault--xh-control-gap-mdgrid-list 的 row-selection-indicator 部件 margin-inline-end 覆盖槽。
--xh-grid-list-row-indicator-radiusrow-selection-indicatorborder-radiusdefault--xh-shape-insetgrid-list 的 row-selection-indicator 部件 border-radius 覆盖槽。
--xh-grid-list-row-indicator-sizerow-selection-indicatorblock-size
inline-size
default--xh-_grid-list-indicatorgrid-list 的 row-selection-indicator 部件 block-size、inline-size 覆盖槽。
--xh-grid-list-row-loading-opacityroot
row
opacityloading--xh-state-disabled-opacitygrid-list 的 root、row 部件 opacity 覆盖槽。
--xh-grid-list-row-radiusrowborder-radiusdefault--xh-shape-controlgrid-list 的 row 部件 border-radius 覆盖槽。
--xh-grid-list-state-fgempty
loading
colordefault--xh-fg-mutedgrid-list 的 empty、loading 部件 color 覆盖槽。
--xh-grid-list-state-font-sizeempty
loading
font-sizedefault--xh-_grid-list-state-font-sizegrid-list 的 empty、loading 部件 font-size 覆盖槽。
--xh-grid-list-state-gapempty
loading
gapdefault--xh-control-gap-mdgrid-list 的 empty、loading 部件 gap 覆盖槽。
--xh-grid-list-state-pxempty
loading
padding-inlinedefault--xh-_grid-list-state-pxgrid-list 的 empty、loading 部件 padding-inline 覆盖槽。
--xh-grid-list-state-pyempty
loading
padding-blockdefault--xh-space-3grid-list 的 empty、loading 部件 padding-block 覆盖槽。

动效 ​

动效角色:按压 · 状态 · 切换 · 出现(见动效规范)。

-webkit-mask-size · background-color · border-color · clip-path · color · mask-size · opacity 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

系统开启减弱动效时由令牌层统一收敛,皮肤不另作判断。

RTL ​

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像。

Released under The MIT License