{ "schemaVersion": 1, "sourceKind": "authored-spec", "provenance": "authored-in-repo", "specFile": "spec/移动端规格.md", "specSection": "33 · 单选框 Radio", "confidence": "high", "slug": "mobile-radio", "name": "单选框 Radio", "semanticTypeCandidates": [ "radio", "radio-group", "single-choice" ], "variantDimensions": [ { "name": "orientation", "values": [ "vertical", "horizontal" ] }, { "name": "button", "values": [ "false", "true" ] } ], "representativeVariants": [ { "orientation": "vertical", "button": "false", "label": "默认(圆点 + 文字,纵向排列并画分隔线)" }, { "orientation": "horizontal", "button": "false", "label": "横向排列(值少、文案短时用)" }, { "orientation": "vertical", "button": "true", "label": "胶囊标签式(无圆点,筛选条用)" } ], "anatomy": { "group": "根元素,role=\"radiogroup\" + aria-label 说明这组在选什么", "item": "单个选项,整行都是热区(原生 button + role=\"radio\")", "icon": "圆点,未选中是空心环、选中是实心圆 + 内圈反色点", "label": "选项文字,占满剩余宽度", "desc": "可选说明行,跟在文字下方(如「需先完成企业认证」)", "state": "选中态 is-checked 与 aria-checked 双写" }, "structurePatterns": { "orientation": "vertical(纵向排列,组内画分隔线)/ horizontal(横向排列,靠间距分组)", "button": "false(圆点 + 文字)/ true(胶囊标签式,无圆点)" }, "usageHints": [ "在一组互斥选项里选且只选一项(支付方式、配送时效、发票类型)", "触屏没有鼠标悬停可以预告状态,选中必须同时有形状差异(圆点内圈实心)与 aria-checked,不能只靠颜色", "整行(圆点 + 文字)都是热区,行高不小于 44px", "一次触摸即选中,不需要二次确认;选中后不能再点回空值", "互斥由组件负责:选中一项会立即清掉同组其它项的选中态,不留下两个选中" ], "doNotInvent": [ "「取消选中」的回到空值交互(单选的语义就是必有一项)", "横向组自动换行的列数策略(由宿主按文案长度决定,组件只负责 flex-wrap)", "与表单一起提交时的隐藏字段(由宿主添加)", "选项内容的异步加载与搜索过滤" ], "unknowns": [ "横向组超过一行时是否改成纵向(当前包裹后当行处理)", "圆点尺寸是否随字号一起放大(当前固定 20px)", "desc 说明行是否允许两行以上(当前单行省略)" ], "interaction": [ "整行(圆点 + 文字)都是热区,行高不小于 44px;横向组里每项自身也保持这个边长", "一次触摸即选中,不需要二次确认;选中后**不能**再点回空值(需要清空由宿主提供额外的「清除」动作)", "互斥由组件负责:选中一项会立即清掉同组其它项的选中态,不留下两个选中", "切换动效是圆点内圈 150ms 缩放;减少动态偏好下瞬时切换", "选中后立即触发 change 事件,回传该项的值" ], "accessibility": [ "组用 role=\"radiogroup\" + aria-label 说明分组名称", "每项是原生 button + role=\"radio\" + aria-checked(读屏会播报「单选按钮,已选中/未选中」)", "圆点与内圈是纯装饰,对读屏隐藏(aria-hidden),语义全靠 role=\"radio\"", "禁用项用原生 disabled 并补 aria-disabled=\"true\"" ], "api": { "source": "implementation", "note": "props / events / slots 为 6 端实现的公共接口(说明文字取自规格对应小节)。字段名与各端源码逐名核对:node tools/verify-mobile-docs.mjs", "requiredNote": "「必传」按严格定义:实现里**没有默认值**时才为 Y(本门禁逐条核对 props 与各端源码的默认值,防止契约与实现脱节)。", "props": [ { "name": "options", "type": "Array", "default": "[]", "desc": "选项数组,每项 { value, label, desc, disabled }(规格 §33.2)", "required": false }, { "name": "value", "type": "string", "default": "''", "desc": "受控选中值,与 aria-checked 同步写(规格 §33.5)", "required": false }, { "name": "orientation", "type": "'vertical' | 'horizontal'", "default": "'vertical'", "desc": "变体 orientation:纵向(画分隔线)还是横向排列(规格 §33.3)", "required": false }, { "name": "button", "type": "boolean", "default": "false", "desc": "变体 button:胶囊标签式(无圆点),用于筛选条(规格 §33.3)", "required": false }, { "name": "disabled", "type": "boolean", "default": "false", "desc": "状态 disabled:整组置灰且不可聚焦(规格 §33.4)", "required": false }, { "name": "label", "type": "string", "default": "'单选项'", "desc": "分组名称,落到 radiogroup 的 aria-label(规格 §33.6)", "required": false } ], "events": [ { "name": "change", "params": "(value)", "desc": "选中某项时触发,回传该项的值(规格 §33.5)" } ], "slots": [ { "name": "default", "desc": "额外选项内容(宿主自己渲染的项,追在 options 之后,规格 §33.2 item)" } ] }, "variantClasses": { "orientation": { "vertical": [], "horizontal": [ ".kole-m-radio-group--horizontal" ] }, "button": { "false": [], "true": [ ".kole-m-radio--button" ] } }, "demos": [ { "id": "basic", "group": "01 组件类型", "title": "单选组", "desc": "互斥:选中一项会自动清掉同组其它项;整行热区不小于 44px。", "variant": "orientation=vertical" }, { "id": "horizontal", "group": "01 组件类型", "title": "横向排列", "desc": "orientation=horizontal:值少、文案短时用,不再画分隔线。", "variant": "orientation=horizontal" }, { "id": "button", "group": "01 组件类型", "title": "胶囊按钮式", "desc": "button=true:无圆点,选中态用品牌色边框 + 浅底。", "variant": "button=true" }, { "id": "checked", "group": "02 组件状态", "title": "选中与未选中", "desc": "两者不能只靠颜色区分:内圈实心点 + aria-checked 双通道。", "variant": "状态 checked" }, { "id": "disabled", "group": "02 组件状态", "title": "禁用项", "desc": "置灰且不响应:原生 disabled 让读屏播报不可用、键盘跳过。", "variant": "disabled=true" } ], "related": [ { "slug": "mobile-checkbox", "why": "选项之间可以同时成立(多选、含全选)时用 Checkbox;只有一项能成立时才用 Radio" }, { "slug": "mobile-switch", "why": "「开 / 关」这类即时生效的二值状态用 Switch(即时切换);需要随表单一起提交的互斥选择用 Radio" }, { "slug": "mobile-form", "why": "单选组作为表单里的一个字段时,标签、必填星号与错误提示由 Form 的 item 提供" } ] }