跳转到内容

Tag 标签

表示一个对象是什么:一个分类、一项技能、一个筛选条件。它承载实体身份,可以被移除。标签表达“它是什么”,不表达“发生了什么”;后者由徽标承担。

用法

一个标签就是 root 加一段 label 文字;不写 closable 就没有关闭按钮

前端无头内核可访问性

组件结构

加粗的是必需部件。

data-scope="tag"root · label · close-trigger

示例

变体

variant 决定颜色的使用方式:实心填底、淡色填底、只描边

solidsubtleoutline

颜色

tone 决定使用哪族颜色;语气只更换色相,形态与尺寸不受影响

品牌中性成功警告危险信息

可关闭

closable 提供关闭按钮;open 受控时去留由宿主决定,可访问名逐个带上标签文字,移除一个后焦点交给下一个

设计前端无头内核可访问性

禁用

disabled 使标签留在原地但不可移除:关闭按钮仍占据位置,标签宽度不因禁用跳变

可摘掉锁定的分类只读

尺寸

size 改变内边距、间距、字号与行框,不写即默认档;同一档有无关闭按钮高度相同,关闭按钮三档同一个尺寸

缺省缺省

只读

readOnly 只锁定关闭按钮:按钮留在原地但不可按下,标签本身不置灰;与 disabled 的区别只在标签本体的颜色

可摘掉只读禁用

设计指引

何时使用

  • 一条记录关联的若干分类、技能、关键词。
  • 已生效的筛选条件,用户可以逐条移除。
  • 需要用户看清对象身份并能移除的任何短文本。

何时不用

  • 提醒用户注意某个对象(未读数、小圆点、在线状态)时,使用徽标,它附着在其他元素上、不接受交互。
  • 用户需要在几个互斥选项中选一个时,使用单选组切换按钮组
  • 用户需要自行输入并累积多个值时,使用标签输入,它自带输入框与增删逻辑。
  • 整条页面级提示使用警告提示

特性

  • 形态、语气、尺寸三轴与其他组件同源。四种形态是 solid / subtle / outline / ghost:默认与 subtle 使用 M1 compact surface,solid 强调身份,outline 只保留轮廓,ghost 完全融入父表面。语气挂在显式形态之下;不写 variant 时保持中性 M1。尺寸档走间距、字号与行框,不占控件行高;同档标签有无关闭按钮高度一致,默认档放进默认档控件的行高内不撑高。默认档(26px)高于 14px 正文行(21px):随文排版、紧凑表格的状态列、下拉候选中的标签写 size="sm"(22px)。
  • closable 显示关闭按钮,显隐可受控(open / defaultOpen / open-change)。关闭按钮保持 16px 视觉盒,透明命中层扩到随文动作的 24px;不为命中面积撑高标签。
  • disabled 让标签留在原地但不可移除,宽度不因禁用而变化。
  • readOnly 只锁定关闭按钮:按钮留在原地但不可用,标签本身不置灰;宿主整体只读时逐个传下即可。
  • Vue 侧默认插槽内只有文字时自动包一层 label,截断规则直接生效。

组合

最佳实践

  • 关闭按钮的可访问名称带上标签文字:默认只读 Delete,一屏十个标签听起来完全相同。逐实例传 translations.close,写成“移除 前端”。
  • 移除一个标签之后安置焦点:标签成排出现,被移除的标签带着焦点一起消失,焦点会回到页面开头,键盘与读屏用户每移除一次就丢失一次位置。交给顶上来的标签的关闭按钮,没有剩余标签时交给列表容器或“还原”按钮。组件不替宿主决定去留,因此只能由宿主处理。
  • 移除标签之后提供回退路径,否则用户误点后无法恢复。
  • 标签文字尽量短:它是身份标记,不是句子。

反模式

  • 自定义元素中把文字直接写在 root 上:文字过长时会把关闭按钮挤出,应写进 data-xh-part="label"
  • 把标签当按钮使用:整块可点却没有按钮语义,键盘用户无法激活。
  • 一屏铺满高饱和度的实心标签,强调失去意义。
  • 只用颜色表达含义:色觉障碍的用户无法分辨,文字本身要说明。

API 参考

产物

自定义元素<xh-tag>
Vue 组件XhTagCloseTrigger XhTagLabel XhTagRoot
组合式函数useTag
状态机tagMachine
皮肤@xihan-ui/styles/tag.css

Props

属性类型必填说明
variantTagVariant形态:solid / subtle / outline / ghost,决定颜色的使用方式。
toneTone语气:brand / neutral / success / warning / danger / info,决定使用哪族颜色。
sizeSize尺寸:sm / md / lg。
closableboolean是否提供关闭按钮,默认 false。false 时该按钮同时被禁用与收起。
disabledboolean标签禁用:关闭按钮不可用,点击不改变显隐。
readOnlyboolean只读:关闭按钮保留位置但不可按下,标签本身不置灰。
openboolean受控显隐;未提供该 prop 即非受控。
defaultOpenboolean非受控初始显隐,默认显示。
onOpenChange(details: TagOpenChangeDetails) => voidopen 变化意图回调;受控时是唯一出口,非受控时随内部转移一并通知。
translationsPartial<TagTranslations>

事件

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

事件载荷说明
open-changeTagOpenChangeDetailsopen 状态变化;detail 为 { open: boolean }

状态

公开状态写入 data-state

部件取值
root'open' | 'closed'

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

状态open · closed

事件OPEN · CLOSE · CONTROLLED.OPEN · CONTROLLED.CLOSED · PRESS.START · PRESS.END

判据isOpenControlled · canPress

connect API

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

成员类型说明
openboolean
closableboolean
disabledboolean
setOpen(next: boolean) => void
getRootProps() => T['element']
getLabelProps() => T['element']
getCloseTriggerProps() => T['button']

无障碍

键盘

规格出处:W3C APG

按键生效条件行为
Enter / Spacefocus 在 close-trigger 上,且 closable 且未禁用、非只读收起标签并通知 open=false;关闭按钮是原生 button,这两个键由平台转换为 click
Enter / Spaceheld in close-trigger, closable 且未禁用、非只读按住期间关闭按钮投影 data-pressed,与指针 :active 同一副按压面;抬起或失焦撤下,按住途中转入禁用 / 只读、收回关闭按钮或标签收起也撤下。root 由把标签当条目用的宿主(tag-group)接同一条通道

ARIA

以下属性由 connect 生成。

部件属性
close-triggeraria-labelprops.translations.close

样式参考

皮肤

@xihan-ui/styles/tag.css 使用 [data-scope="tag"][data-part="root"] 部件选择器,位于 xihan.components 层。覆盖样式使用 xihan.overrides

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

数据属性

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

部件属性
rootdata-disabled''(条件成立时才出现)
rootdata-pressed''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-state'open' | 'closed'
rootdata-toneprops.tone
rootdata-variantprops.variant
close-triggerdata-disabled''(条件成立时才出现)
close-triggerdata-pressed''(条件成立时才出现)

CSS 变量

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

变量部件CSS 属性状态默认来源说明
--xh-tag-bgrootbackgrounddefault
tone
variant=solid
variant=subtle
--xh-_tone
--xh-_tone-subtle
--xh-bg-brand
--xh-material-soft-bg
tag 的 root 部件 background 覆盖槽。
--xh-tag-bg-disabledrootbackgrounddisabled
tone
--xh-bg-mutedtag 的 root 部件 background 覆盖槽。
--xh-tag-borderrootborder
border-color
default
tone
variant=outline
variant=subtle
--xh-_tone-border-control
--xh-border-default
--xh-material-soft-border
tag 的 root 部件 border、border-color 覆盖槽。
--xh-tag-border-disabledrootborder-colordisabled
tone
--xh-border-defaulttag 的 root 部件 border-color 覆盖槽。
--xh-tag-close-bg-activeclose-triggerbackgroundis(:active, [data-pressed])
not(:disabled)
pressed
color-mix(in oklab, currentColor 22%, transparent)tag 的 close-trigger 部件 background 覆盖槽。
--xh-tag-close-bg-hoverclose-triggerbackgroundhover
not(:disabled)
color-mix(in oklab, currentColor 14%, transparent)tag 的 close-trigger 部件 background 覆盖槽。
--xh-tag-close-fgclose-triggercolordefaultcurrentColortag 的 close-trigger 部件 color 覆盖槽。
--xh-tag-close-radiusclose-triggerborder-radiusdefault--xh-shape-insettag 的 close-trigger 部件 border-radius 覆盖槽。
--xh-tag-close-sizeclose-triggerblock-size
inline-size
inset
default--xh-control-indicator-sizetag 的 close-trigger 部件 block-size、inline-size、inset 覆盖槽。
--xh-tag-fgrootcolordefault
tone
variant=ghost
variant=outline
variant=solid
variant=subtle
--xh-_tone-fg
--xh-_tone-on
--xh-fg-default
--xh-fg-on-brand
--xh-material-soft-fg
tag 的 root 部件 color 覆盖槽。
--xh-tag-font-sizerootfont-sizedefault--xh-_tag-font-sizetag 的 root 部件 font-size 覆盖槽。
--xh-tag-font-weightrootfont-weightdefault--xh-font-weight-mediumtag 的 root 部件 font-weight 覆盖槽。
--xh-tag-gaprootgapdefault--xh-_tag-gaptag 的 root 部件 gap 覆盖槽。
--xh-tag-icon-sizeroot--xh-icon-sizedefault--xh-glyph-size-texttag 的 root 部件 --xh-icon-size 覆盖槽。
--xh-tag-pxrootpadding-inlinedefault--xh-_tag-pxtag 的 root 部件 padding-inline 覆盖槽。
--xh-tag-pyrootpadding-blockdefault--xh-_tag-pytag 的 root 部件 padding-block 覆盖槽。
--xh-tag-radiusrootborder-radiusdefault--xh-shape-pilltag 的 root 部件 border-radius 覆盖槽。
--xh-tag-shadowrootbox-shadowdefault
variant=solid
--xh-_tag-highlight
--xh-material-soft-shadow
tag 的 root 部件 box-shadow 覆盖槽。

动效

background · scaletransition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

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

RTL

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

Released under The MIT License