生态产品多个设计器现已发布正式版

查看生态总览
跳转到内容

RadioGroup 单选组 ​

一组互斥选项共用一个值,所有选项同时可见。单个单选按钮是这里的 item 部件,不另立组件:它脱离组既没有互斥对象,也无法取消选中。

用法 ​

组内只有一个 Tab 停靠点,进组后四个方向键都能切换

套餐

组件结构 ​

加粗的是必需部件。

data-scope="radio-group":root · label · thumb · item · item-icon · item-text · item-description · indicator · hidden-input

示例 ​

受控 ​

传入 value 后由宿主决定;值可以是 null,表示没有任何一项选中

套餐
当前:free

横向排布 ​

orientation 只影响排版与 aria-orientation,方向键四个方向照样都能切换

尺寸

禁用 ​

单项禁用后不可点击,方向键也跳过它;整组禁用则每一项都随之禁用

单项禁用
整组禁用

颜色 ​

tone 决定选中圆点使用哪族颜色,六种语气各一组

brand
neutral
success
warning
danger
info

尺寸 ​

size 改变条目间距与字号,不写即默认中档

sm
缺省
lg

数据驱动 ​

数据字段的命名由数据决定,映射为条目的值、文本与禁用即可

优先级
当前:p1

卡片 ​

variant="card" 把每个选项画成一张可点的卡,文案下方用说明行交代差别

套餐

分段形态 ​

variant="segmented" 把一排短选项画成一条轨道,选中段由滑块标出,换段时滑块滑过去;缺省横排

时间粒度

撑满行宽 ​

segmented 形态加 block 使整组占满一行,各段等分剩余空间,长短不一的文字也能对齐

执行方式

图标 ​

条目文字前放一枚图标:图标对读屏隐藏,可及名仍是文字;直径与颜色随条目走,选中与悬停一并换色

视图

设计指引 ​

何时使用 ​

  • 二到五个互斥选项,且各选项的文字值得同时展开供用户比较。
  • 选项之间要靠一两句说明才分得清(套餐、配送方式、部署区域)时,用 variant="card" 把每个选项画成一张卡。
  • 选项少、名称短,要在一行里切换视图模式(列表 / 网格)、时间粒度(日 / 周 / 月)或排序方式时,用 variant="segmented" 画成一条分段轨道。

何时不用 ​

  • 选项超过五六个时,使用选择器。
  • 表达的是按钮的按下状态而不是一个字段值,或需要多选时,使用切换按钮组:它没有 name、不参与表单,也没有滑块。
  • 切换的是同一块区域的几屏内容时,使用标签页,它管理面板的显隐,不是一个值。
  • 可以多选时,使用复选框组。

特性 ​

  • 整组只占一个 Tab 位,组内靠方向键移动,与原生单选组一致。
  • hidden-input 承担表单参与,宿主表单重置时选中值回落到 defaultValue。
  • collection 可数据驱动,也可以逐项编写;节点的 description 与 icon 自动铺出说明行与图标位。
  • 不写结构时按标准结构铺出整套部件(Vue 不写默认插槽、React 不给 children、Web Components 不写部件或只写 root),三端出自同一个结构函数:label 给标题文字,segmented 形态在条目之前铺滑块,每个条目带表单影子、圆圈、图标、文字与说明。Web Components 里标题与条目文字可以写在宿主的直接子节点上接管:slot="label"、slot="item:<值>"。
  • 圆圈是字段家族的控制盒:不填底、描边与无影,选中后以语气色圆点填充;整行接 Action Control row 档,悬停 / 按下换面不缩放,圆圈随行换到承载面阶梯的下一档。
  • variant 是结构形态,三种形态共用同一台状态机、同一张键盘表:
    • 缺省 list 是一列「圆圈 + 文案」的行。
    • card 把每个条目画成一张可点的描边卡(surface 圆角,白底承载阶梯悬停 100 → 按下 200),圆圈在卡的行首,整张卡是命中区。选中卡换品牌淡底(写了 tone 换语气淡底),与表格选中行、穿梭框选中项同一种标记,描边不换。竖排时卡片撑满一列,横排时各卡等分一行、放不下就折行。
    • segmented 把条目画成一条与字段外壳同款的轨道(字段底 + 1px 字段描边、control 圆角、2px 内衬)里首尾相接的段,段与选中段的 thumb 部件嵌在轨道里、取 inset 圆角:滑块是一块品牌淡底(浅色 12%、深色 20%)的平面滑块,换段时滑过去;选中段字取品牌色、medium,悬停时滑块升一档(浅色 18%、深色 28%),禁用时退到 8% 淡底与浅品牌字;写了 tone 时滑块与字换成语气淡底与语气字(浅色 12% / 悬停 20%,深色 20% / 28%),禁用的选中段同样退到 8% 语气淡底、字往承载面兑一半。未选中段透明底、次级字色,悬停 100 → 按下 200,只换面不缩放;段横向内距 12px,段与段之间一道 1px × 14px 的分隔线,与选中段、悬停段相邻的那几道收起;这一形态不画圆圈,缺省横排,block 让整组撑满行宽、各段等分,一行排不下时折行。
  • 滑块的位置与尺寸由组件测量:只有换段时才滑,首次落位、窗口缩放、换上正式字体之类的重量直接到位,不拖尾;横排竖排、ltr 与 rtl 使用同一条规则。
  • item-icon 是文字前的图标位,对读屏隐藏,直径随尺寸档、颜色随条目;节点的 icon 字段写入图标文本,需要放置图形时手写部件,把图标组件或 svg 放进 item-icon。
  • item-description 是文案下方的说明行(13 / --xh-fg-muted),与文案一起构成条目的可及名;collection 里的 description 会自动铺出这一行。
  • 与复选框的不对称是有意的:一个复选框自身即成立(勾选同意条款),一个单选按钮自身不成立,因此复选框有独立组件、单选按钮没有。
  • 值可以是任意类型:value、defaultValue 与 collection 里交进来数字、对象都行,选中值是一个值或 null,onValueChange、v-model、插槽与 renderItem 拿到的是原值;Vue 与 React 按 value 或 collection 推断值的类型,两处对不上、valueKey 写错字段编译即报错。数字转成字符串当键,对象值给 valueKey(字段名或取值函数),同一个选项每次都是新对象(接口刚取回来)也认得出来,不给按对象身份认;键也是条目的 data-value与随表单提交的值。Vue 的 h() 推断不了泛型,那里按宽松的类型检查;Web Components 经 property 交值,写 querySelector<XhRadioGroupElement<number>>("xh-radio-group") 收窄。

组合 ​

  • 外层放表单字段,让标签、说明与错误文案一并接入;每项的补充说明放进 item-description。
  • segmented 形态与标签页搭配:分段切换数据口径,标签页切换内容面板,两者不互相替代。

最佳实践 ​

  • 提供默认选中项,除非“未选”本身有意义。
  • 选项文字写完整,不依赖共同前缀省略。
  • 卡片里只放一两句说明,不放按钮、链接等第二个可点目标:整张卡是一次选择,内嵌的动作会与选择抢同一次点击。
  • segmented 形态各段文字长度尽量接近:长短悬殊时滑块滑动,整排宽度会跟着跳动。
  • segmented 形态尽量一行排下:折行只是窄处的兜底,折行后下一行首段的起始缘仍会画出一道分隔线(样式层拿不到段落在第几行)。段多或容器窄时改用竖排或选择器。
  • segmented 形态的段文字不走 collection 而是手写、且会在运行期改动时,改动后调用一次 measure():滑块只跟随选中值、集合与尺寸变化,段内文字撑宽时它无法感知。
  • 动态移除正持有焦点的条目(例如按权限过滤)之后,焦点会回到 <body>。组件只保证 Tab 位退回容器、键盘可以再次进入;需要保持位置时由页面把焦点移到相邻的条目。

反模式 ​

  • 单选组只有一个选项,用户无从选择。
  • 选项可以被取消选中:单选组一旦选中就不应回到空值,需要空值时增加一项“不指定”。
  • 把 segmented 形态当按钮组使用:段是一个值的几个取值,不是几个动作。触发动作使用按钮组。
  • segmented 形态一行放七八段:那已经是下拉框,还占着整行宽度。

API 参考 ​

产物 ​

层值
自定义元素<xh-radio-group>
Vue 组件XhRadioGroupItem XhRadioGroupItemDescription XhRadioGroupItemIcon XhRadioGroupItemText XhRadioGroupLabel XhRadioGroupRoot XhRadioGroupThumb
组合式函数useRadioGroup
状态机radioGroupMachine
皮肤@xihan-ui/styles/radio-group.css

Props ​

属性类型必填说明
collectionRadioGroupNode<V>[]条目数据,显示文本与禁用的事实源。提供后条目部件只需声明 value。 未提供时回到文本与禁用都写在条目部件上的方式。
valueKeySelectionValueKey<V>对象值怎样取键:字段名或取值函数。同一个选项每次都是新对象(接口刚取回来)时给它; 不给时按对象身份认。值不是对象时用不着。键也是条目的 data-value 与随表单提交的值。
valueV | null
defaultValueV | null
disabledboolean
readOnlyboolean只读:不可选择,但仍可聚焦、方向键照常移动焦点,对比度不降低。
invalidboolean校验失败:只改变呈现,不阻止交互。
requiredboolean必填:随表单校验一起使用,只发无障碍属性,不自行拦截提交。
orientationOrientation视觉排布:list / card 缺省竖排,segmented 缺省横排。方向键接受的轴与它无关(四个方向键恒响应)。
dirDirection文字方向,只改写左右方向键的语义与滑块的起始缘,上下键与之无关。 未提供时从根节点的计算样式读取(祖先链上的 dir 与 CSS direction 都计入),提供后以它为准。
namestring表单字段名。
loopboolean方向键到达末尾是否回绕,默认 true。
blockboolean撑满行宽,各段等分剩余空间;只在 segmented 形态下生效。
toneTone语气:brand / neutral / success / warning / danger / info,决定使用哪族颜色。
sizeSize尺寸:sm / md / lg。
variantRadioGroupVariant结构形态,默认 list;card 把每个条目画成一张可点的卡,segmented 画成轨道里的一排段。
labelledboolean作者渲染了 label 部件时置真,由适配器统计而不是判断标题文字是否有值。 为假时根不输出 aria-labelledby:指向未渲染的 id 会让组没有名字,作者写在根上的 aria-label 也会被它压住。
ariaLabelstring不显示出来的名字,写成 aria-label 落在与字段标签同一个部件上。 放进字段(字段接线)或渲染了 label 部件时名字以它们为准,aria-labelledby 盖过它。
onValueChange(details: RadioGroupValueChangeDetails<V>) => voidvalue 变化回调。

RadioGroupNode ​

collection 的元素。

字段类型必填说明
valueV是
labelstring展示文本;默认回退为值(不是字符串的值退回它的键)。
descriptionstring说明文字,写入 item-description 部件;未提供时本条不铺该部件。
iconstring图标文本,写入文字前的 item-icon 部件,对读屏隐藏;需要放置图形时改为手写部件。未提供时本条不铺该部件。
disabledboolean条目禁用:方向键跳过它,但它仍可聚焦、仍是导航起点。

事件 ​

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

事件载荷说明
value-changeRadioGroupValueChangeDetails选中值变化;detail 为 { value: 值 | null },值是 value / collection 里交进来的原值(字符串、数字或对象)

React 适配器 props ​

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

React 组件属性类型必填说明
XhRadioGroupItemvalueunknown是条目代表的值,与根上的值同类型:字符串、数字或对象。
XhRadioGroupItemdisabledboolean默认交给 connect 查询 collection,写死 false 会覆盖数据中的禁用。
XhRadioGroupRootlabelReactNode标题文字。提供后不必再写 label 部件。
XhRadioGroupRootrenderItem(node: RadioGroupNodeMeta<V>) => ReactNode每个条目的自定义内容;未提供时使用 collection 中的 label。
XhRadioGroupRootchildrenReactNode

状态 ​

公开状态写入 data-state。

部件取值
item'checked' | 'unchecked'
item-icon'checked' | 'unchecked'
item-text'checked' | 'unchecked'
item-description'checked' | 'unchecked'
indicator'checked' | 'unchecked'
hidden-input'checked' | 'unchecked'

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

状态:idle

事件:VALUE.SET · ITEM.SELECT · ITEM.FOCUS · GROUP.BLUR · FORM.RESET · THUMB.MEASURE · PRESS.START · PRESS.END

判据:canPress

connect API ​

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

成员类型说明
valueV | null
collectionreadonly RadioGroupNodeMeta<V>[]由 collection 推导的条目元信息,按数据顺序排列;未提供 collection 时为空数组。
focusedValueV | null焦点在组外时为 null。
variantRadioGroupVariant结算后的结构形态:没传 variant 即 list。适配器据它决定按 collection 铺开时放不放滑块。
setValue(next: V) => void
measure() => void重新测量滑块(只在 segmented 形态下有落点)。选中值变化与 collection 增删改名都会自动重新测量, 根与条目的尺寸变化由尺寸观察器接管;条目的文字由部件手写(未经 collection)而后修改时需要手动调用。
getRootProps() => T['element']
getLabelProps() => T['element']
getItemProps(props: RadioGroupItemProps<V>) => T['element']
getItemIconProps(props: RadioGroupItemProps<V>) => T['element']条目文字前的图标位:纯装饰,对读屏隐藏,状态标记与条目一致。
getItemTextProps(props: RadioGroupItemProps<V>) => T['element']
getItemDescriptionProps(props: RadioGroupItemProps<V>) => T['element']条目的说明:文案下方一行次级文字,常用在 card 形态里。
getIndicatorProps(props: RadioGroupItemProps<V>) => T['element']条目行首的单选圆圈;segmented 形态由滑块标出选中,皮肤不画它。
getThumbProps() => T['element']segmented 形态里滑动的选中标记:整组一份,位置与尺寸由状态机量好写成私有槽;没有落点时收起。
getHiddenInputProps(props: RadioGroupItemProps<V>) => T['input']条目对应的隐藏原生 radio 输入,用于表单提交。

无障碍 ​

键盘 ​

规格出处:W3C APG

按键生效条件行为
Tab / Shift+Tabfocus outside the group整组只占一个 Tab 位:焦点进入锚点条目(即选中项);落到容器上时由容器转投锚点条目,锚点缺席或被禁用才落首个可停留项
ArrowDown / ArrowRightfocus in group, group not disabled焦点移到下一个可停留条目并选中(禁用条目跳过、尽头按 loop 回绕,缺省回绕到首项);只读时焦点照走但不落值;dir=rtl 时改由 ArrowLeft 承担,未给 dir 时按祖先链上的书写方向
ArrowUp / ArrowLeftfocus in group, group not disabled焦点移到上一个可停留条目并选中(尽头按 loop 回绕,缺省回绕到末项);只读时焦点照走但不落值;dir=rtl 时改由 ArrowRight 承担
Spacefocus on item, item not disabled选中当前条目;Enter 不是 role=radio 的激活键,按下不选中
Spaceheld on item, 条目未禁用且组未禁用、非只读按住期间该条目投影 data-pressed,与指针 :active 同一副按压面(list / card 的行与圆圈一起换面,segmented 的段换到按下面);抬起或失焦撤下,按住途中整组转入禁用或只读也撤下。Enter 不进按压面;选中与按压互相独立

ARIA ​

以下属性由 connect 生成。

部件属性值
rootaria-invalid'true' | 'false'
rootaria-labelprops.ariaLabel
rootaria-labelledbylabel 部件的 id | undefined
rootaria-orientation'horizontal' | 'vertical'
rootaria-readonly'true' | 'false'
rootaria-required'true' | 'false'
rootrole'radiogroup'
thumbaria-hidden'true'
itemaria-checked'true' | 'false'
itemaria-disabled'true' | 'false'
itemrole'radio'
item-iconaria-hidden'true'
indicatoraria-hidden'true'
hidden-inputaria-hidden'true'
  • 根节点是 radiogroup,每个条目是 radio 并显式报告 aria-checked;三种形态的语义相同,segmented 只是换了画法。
  • 焦点进组时落在已选中的条目上,没有选中项才落第一个;方向键移动焦点的同时选中。键盘按 APG 的单选组:Space 选中当前条目,Enter 与 Home / End 不归单选组管。
  • 禁用的条目使用 aria-disabled 而不是原生 disabled:它仍可聚焦,仍是方向键的起点。
  • label 部件是组的可及名。segmented 形态的轨道里不排标题,label 部件在这一形态下视觉隐藏、只作可及名;需要可见标题时放进表单字段,或给根节点写 aria-label。
  • 根节点只在 label 部件真渲染了时才输出 aria-labelledby;不写标题时给根节点写 aria-label。Vue / React 的 label 属性不论手写选项还是数据驱动都会铺出标题。
  • 方向键只认落在条目或根节点自身上的按键:组里放着的数字框、下拉等行内编辑控件,它们的方向键照常移光标、换值,不会切换选项。
  • 圆圈与滑块都是纯装饰,对读屏隐藏;当前项由条目自身的选中态表达。

样式参考 ​

皮肤 ​

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

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

数据属性 ​

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

部件属性值
rootdata-block''(条件成立时才出现)
rootdata-disabled''(条件成立时才出现)
rootdata-invalid''(条件成立时才出现)
rootdata-orientation'horizontal' | 'vertical'
rootdata-readonly''(条件成立时才出现)
rootdata-required''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-toneprops.tone
rootdata-variantprops.variant
thumbdata-instant''(条件成立时才出现)
thumbdata-valuecontext.get('value')
itemdata-disabled''(条件成立时才出现)
itemdata-invalid''(条件成立时才出现)
itemdata-pressed''(条件成立时才出现)
itemdata-readonly''(条件成立时才出现)
itemdata-state'checked' | 'unchecked'
itemdata-xh-action-controlundefined | ''
itemdata-xh-action-displayundefined | 'always'
itemdata-xh-action-profileundefined | 'row'
itemdata-xh-action-sizeundefined | 'xs'
itemdata-xh-action-variantundefined | 'outline' | 'ghost'
itemdata-xh-choice-card''(条件成立时才出现)
item-icondata-disabled''(条件成立时才出现)
item-icondata-invalid''(条件成立时才出现)
item-icondata-readonly''(条件成立时才出现)
item-icondata-state'checked' | 'unchecked'
item-textdata-disabled''(条件成立时才出现)
item-textdata-invalid''(条件成立时才出现)
item-textdata-readonly''(条件成立时才出现)
item-textdata-state'checked' | 'unchecked'
item-descriptiondata-disabled''(条件成立时才出现)
item-descriptiondata-invalid''(条件成立时才出现)
item-descriptiondata-readonly''(条件成立时才出现)
item-descriptiondata-state'checked' | 'unchecked'
indicatordata-disabled''(条件成立时才出现)
indicatordata-invalid''(条件成立时才出现)
indicatordata-readonly''(条件成立时才出现)
indicatordata-state'checked' | 'unchecked'
hidden-inputdata-disabled''(条件成立时才出现)
hidden-inputdata-invalid''(条件成立时才出现)
hidden-inputdata-readonly''(条件成立时才出现)
hidden-inputdata-state'checked' | 'unchecked'

CSS 变量 ​

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

变量部件CSS 属性状态默认来源说明
--xh-radio-group-card-title-font-weightitem
item-text
font-weightxh-choice-card--xh-text-label-weightradio-group 的 item、item-text 部件 font-weight 覆盖槽。
--xh-radio-group-gaprootgapdefault--xh-space-2radio-group 的 root 部件 gap 覆盖槽。
--xh-radio-group-icon-sizeroot--xh-icon-sizedefault
size=lg
size=sm
--xh-glyph-size-lg
--xh-glyph-size-md
--xh-glyph-size-sm
radio-group 的 root 部件 --xh-icon-size 覆盖槽。
--xh-radio-group-indicator-bgindicatorbackgrounddefaulttransparentradio-group 的 indicator 部件 background 覆盖槽。
--xh-radio-group-indicator-bg-disabledindicator
item
backgrounddisabled--xh-bg-subtleradio-group 的 indicator、item 部件 background 覆盖槽。
--xh-radio-group-indicator-bg-pressedindicator
item
backgrounddisabled
is(:active, [data-pressed])
not([data-disabled])
not([data-readonly])
pressed
readonly
--xh-_radio-group-host-bg-pressedradio-group 的 indicator、item 部件 background 覆盖槽。
--xh-radio-group-indicator-borderindicatorborderdefault--xh-border-strongradio-group 的 indicator 部件 border 覆盖槽。
--xh-radio-group-indicator-border-checkedindicatorborder-colorstate=checked--xh-_radio-group-accentradio-group 的 indicator 部件 border-color 覆盖槽。
--xh-radio-group-indicator-border-disabledindicator
item
border-colordisabled--xh-border-defaultradio-group 的 indicator、item 部件 border-color 覆盖槽。
--xh-radio-group-indicator-border-hoverindicator
item
border-colordisabled
hover
invalid
not([data-disabled])
not([data-invalid])
not([data-readonly])
not([data-state='checked'])
readonly
state=checked
--xh-border-control-hoverradio-group 的 indicator、item 部件 border-color 覆盖槽。
--xh-radio-group-indicator-border-invalidindicatorborder-colorinvalid
state=checked
--xh-border-invalidradio-group 的 indicator 部件 border-color 覆盖槽。
--xh-radio-group-indicator-dotindicatorbackgrounddefault--xh-_radio-group-accentradio-group 的 indicator 部件 background 覆盖槽。
--xh-radio-group-indicator-dot-disabledindicator
item
backgrounddisabled--xh-fg-disabledradio-group 的 indicator、item 部件 background 覆盖槽。
--xh-radio-group-indicator-dot-pressedindicator
item
backgrounddisabled
is(:active, [data-pressed])
not([data-disabled])
not([data-readonly])
pressed
readonly
state=checked
--xh-_tone-activeradio-group 的 indicator、item 部件 background 覆盖槽。
--xh-radio-group-indicator-radiusindicatorborder-radiusdefault--xh-shape-circleradio-group 的 indicator 部件 border-radius 覆盖槽。
--xh-radio-group-indicator-sizeindicatorblock-size
inline-size
default--xh-_radio-group-indicatorradio-group 的 indicator 部件 block-size、inline-size 覆盖槽。
--xh-radio-group-item-bg-hoveritembackground-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-bg-subtleradio-group 的 item 部件 background-color 覆盖槽。
--xh-radio-group-item-bg-presseditembackground-colordisabled
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-bg-subtle-hoverradio-group 的 item 部件 background-color 覆盖槽。
--xh-radio-group-item-description-fgitem-descriptioncolordefault--xh-fg-mutedradio-group 的 item-description 部件 color 覆盖槽。
--xh-radio-group-item-description-fg-disableditem
item-description
colordisabled--xh-fg-disabledradio-group 的 item、item-description 部件 color 覆盖槽。
--xh-radio-group-item-description-font-sizeitem-descriptionfont-sizedefault--xh-text-secondary-sizeradio-group 的 item-description 部件 font-size 覆盖槽。
--xh-radio-group-item-fgitemcolordefault
disabled
focus-visible
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-fg-defaultradio-group 的 item 部件 color 覆盖槽。
--xh-radio-group-item-fg-disableditemcolordisabled--xh-fg-disabledradio-group 的 item 部件 color 覆盖槽。
--xh-radio-group-item-font-sizeitem
root
font-sizedefault
variant=segmented
--xh-_radio-group-font-sizeradio-group 的 item、root 部件 font-size 覆盖槽。
--xh-radio-group-item-gapitem
root
gapdefault
variant=segmented
--xh-_radio-group-item-gapradio-group 的 item、root 部件 gap 覆盖槽。
--xh-radio-group-item-radiusitemborder-radiusdefault--xh-shape-controlradio-group 的 item 部件 border-radius 覆盖槽。
--xh-radio-group-item-row-gapitemrow-gaphas(> [data-scope='radio-group'][data-part='item-description'])
not([data-xh-choice-card])
xh-choice-card
--xh-space-1radio-group 的 item 部件 row-gap 覆盖槽。
--xh-radio-group-label-fglabelcolordefault--xh-fg-mutedradio-group 的 label 部件 color 覆盖槽。
--xh-radio-group-label-fg-disabledlabel
root
colordisabled--xh-fg-subtleradio-group 的 label、root 部件 color 覆盖槽。
--xh-radio-group-label-font-sizelabelfont-sizedefault--xh-text-label-sizeradio-group 的 label 部件 font-size 覆盖槽。
--xh-radio-group-label-font-weightlabelfont-weightdefault--xh-text-label-weightradio-group 的 label 部件 font-weight 覆盖槽。
--xh-radio-group-segment-bg-hoveritem
root
background-colordisabled
hover
not([data-disabled])
not([data-readonly])
not([data-state='checked'])
readonly
state=checked
variant=segmented
--xh-bg-subtleradio-group 的 item、root 部件 background-color 覆盖槽。
--xh-radio-group-segment-bg-presseditem
root
background-colordisabled
is(:active, [data-pressed])
not([data-disabled])
not([data-readonly])
not([data-state='checked'])
pressed
readonly
state=checked
variant=segmented
--xh-bg-subtle-hoverradio-group 的 item、root 部件 background-color 覆盖槽。
--xh-radio-group-segment-fgitem
root
color@media print
state=checked
variant=segmented
--xh-fg-default
--xh-fg-muted
radio-group 的 item、root 部件 color 覆盖槽。
--xh-radio-group-segment-fg-checkeditem
root
colorstate=checked
variant=segmented
--xh-_radio-group-segment-fg-checkedradio-group 的 item、root 部件 color 覆盖槽。
--xh-radio-group-segment-fg-checked-disableditem
root
colordisabled
state=checked
variant=segmented
--xh-_radio-group-segment-fg-checked-disabledradio-group 的 item、root 部件 color 覆盖槽。
--xh-radio-group-segment-fg-hoveritem
root
colordisabled
hover
not([data-disabled])
not([data-readonly])
not([data-state='checked'])
readonly
state=checked
variant=segmented
--xh-fg-defaultradio-group 的 item、root 部件 color 覆盖槽。
--xh-radio-group-segment-font-weightitem
root
font-weightvariant=segmented--xh-text-label-weightradio-group 的 item、root 部件 font-weight 覆盖槽。
--xh-radio-group-segment-font-weight-checkeditem
root
font-weightstate=checked
variant=segmented
--xh-font-weight-mediumradio-group 的 item、root 部件 font-weight 覆盖槽。
--xh-radio-group-segment-hitem
root
block-size
min-block-size
orientation=horizontal
variant=segmented
--xh-_radio-group-segment-hradio-group 的 item、root 部件 block-size、min-block-size 覆盖槽。
--xh-radio-group-segment-pxitem
root
padding-inlinevariant=segmented--xh-_radio-group-segment-pxradio-group 的 item、root 部件 padding-inline 覆盖槽。
--xh-radio-group-segment-radiusitem
root
border-radiusvariant=segmented--xh-shape-insetradio-group 的 item、root 部件 border-radius 覆盖槽。
--xh-radio-group-segment-separatoritem
root
background-colororientation=horizontal
variant=segmented
--xh-border-defaultradio-group 的 item、root 部件 background-color 覆盖槽。
--xh-radio-group-thumb-bgthumbbackgrounddefault--xh-_radio-group-thumb-bgradio-group 的 thumb 部件 background 覆盖槽。
--xh-radio-group-thumb-bg-disabledroot
thumb
backgrounddisabled
has(> [data-scope='radio-group'][data-part='item'][data-state='checked'][data-disabled])
state=checked
variant=segmented
--xh-_radio-group-thumb-bg-disabledradio-group 的 root、thumb 部件 background 覆盖槽。
--xh-radio-group-thumb-bg-hoverroot
thumb
backgrounddisabled
has(> [data-scope='radio-group'][data-part='item'][data-state='checked']:not([data-disabled])
hover
not([data-readonly])
readonly
state=checked
variant=segmented
--xh-_radio-group-thumb-bg-hoverradio-group 的 root、thumb 部件 background 覆盖槽。
--xh-radio-group-thumb-borderthumbborderdefaulttransparentradio-group 的 thumb 部件 border 覆盖槽。
--xh-radio-group-thumb-radiusthumbborder-radiusdefault--xh-shape-insetradio-group 的 thumb 部件 border-radius 覆盖槽。
--xh-radio-group-thumb-shadowthumbbox-shadowdefaultnoneradio-group 的 thumb 部件 box-shadow 覆盖槽。
--xh-radio-group-track-bgrootbackgroundvariant=segmented--xh-bg-fieldradio-group 的 root 部件 background 覆盖槽。
--xh-radio-group-track-bg-disabledrootbackgrounddisabled
variant=segmented
--xh-bg-mutedradio-group 的 root 部件 background 覆盖槽。
--xh-radio-group-track-borderrootbordervariant=segmented--xh-border-controlradio-group 的 root 部件 border 覆盖槽。
--xh-radio-group-track-border-invalidrootborder-colorinvalid
variant=segmented
--xh-border-invalidradio-group 的 root 部件 border-color 覆盖槽。
--xh-radio-group-track-paddingitem
root
inset-block-start
min-block-size
padding
@media (pointer: coarse)
orientation=horizontal
variant=segmented
--xh-space-0_5radio-group 的 item、root 部件 inset-block-start、min-block-size、padding 覆盖槽。
--xh-radio-group-track-radiusrootborder-radiusvariant=segmented--xh-shape-controlradio-group 的 root 部件 border-radius 覆盖槽。

动效 ​

动效角色:按压 · 状态 · 切换 · 指示与换位(见动效规范)。

background-color · block-size · border-color · color · inline-size · scale · translate 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

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

响应式 ​

皮肤另按输入能力分档:pointer: coarse:同一份皮肤在触屏与带指针的设备上不一样,与视口宽度无关。

RTL ​

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像;只认物理方向的量乘 --xh-direction-sign 换向,按就近的 dir 走。

  • 方向从 DOM 读取:整页或某个祖先声明了 dir='rtl'(或 CSS direction),左右方向键的语义与滑块的起始缘一起翻转,不需要再向组件传递。上下键不受影响。
  • dir 属性是显式覆盖:提供后以它为准,用于整页 ltr、局部 rtl 的场合。

Released under The MIT License