简体中文
QuestionFlow 澄清问卷 alpha
执行前先提问:一次一题,逐题作答,答完一起提交。
用法
一次一题:单选选中后自动进入下一题,多选等待用户点击继续,末题的按钮变为发送
这次改动动到哪一层?
Question 1 of 3
收到:(还没发送)
组件结构
加粗的是必需部件。
data-scope="question-flow":root · viewport · track · question · prompt · description · group · item · item-indicator · item-text · item-description · note · footer · prev-trigger · counter · next-trigger · skip-trigger · submit-trigger · result · live-region
示例
自由文本与跳过
选项之外还可自行填写一句,填写后即视为已作答;关闭自动前进,每题都等待用户点击继续
文案用什么口吻?
Question 1 of 2
(还没操作)
受控当前题
进度由宿主管理:外部按钮直接跳题,答案也一并受控,组件只发意图
先修哪一处?
Question 1 of 2
宿主手上的进度:第 1 题;已答 0 题
尺寸
size 改变问句、选项行与页脚按钮的几何档,三档共用同一份问题
这次改动动到哪一层?(sm)
这次改动动到哪一层?(md)
这次改动动到哪一层?(lg)
说明与多选上下限
选项的 description 写进 item-description,跟着选项名一起念;多选的 minSelections / maxSelections 管选够与选满,数量要求写进题目说明 description 并描述选项组
按什么节奏发布?
会影响发布说明的写法。
Question 1 of 2
收到:(还没发送)
设计指引
何时使用
- 需求尚有几处不明确,把含糊的地方拆成几道选择题。
- 一次需要问多件事,且每件都只需一两秒作答。
何时不用
- 只问一件事时,使用单选组或复选框组,不需要套一层问卷。
- 需要用户批准一次危险操作时,使用审批:它的出口只有批准与拒绝,没有“跳过”,也没有“答完再说”。
- 收集一份长表单时,字段之间有校验与联动,使用表单。
特性
- 一次只暴露一题:非当前题对读屏
aria-hidden、对键盘inert,其中的可聚焦元素另发tabindex="-1"。它们仍留在轨道上,只是不可到达,这样卡片高度可以测量,来回翻页也不需要重建 DOM。 - 高度与位移是测量得出的:状态机在活动 DOM 上测量当前题的盒,把结果写入 context,连接层只把它格式化为两个私有槽(视口高度与轨道位移)。连接层是渲染期纯函数,不查询 DOM、不启动定时器、不读取时钟。
- 单选自动前进,多选等待用户点击继续:选中一项后隔一小段自动翻到下一题;连续更改时,每次更改都从整段延时重新计时。自动前进只走到下一题,末题上停止,不替用户提交。
- 一个按钮两个身份:不是末题时为“继续”,末题时为“发送”。它原位切换
data-mode与可访问名称,正在按它的用户不会按空。 - 自由文本与选项同等有效:填写了“都不是,我想要……”即视为已作答,继续键随之可用。
- 多选的数量要求:
minSelections管选够——选够之前继续键不可用(写了自由文本同样算作答);maxSelections管选满——选满之后其余未选项转为不可选(aria-disabled),取消一项又能再选,程序化的toggleOption守同一条上限。选项组带data-at-max供皮肤取用。 - 两种说明:题目的
description写进description部件并成为选项组的描述,缺席时由多选的数量要求代填(文案取translations.selectionRange);选项的description写进item-description部件,排在选项之内另起一行。有没有题目说明看数据,没有时该部件收起。 - 进度只播报一次:
counter部件aria-hidden,逐题跳动的数字不进入活动区域;换题与提交由announcement读出一句。 - 跳过是明确路径:
allowSkip关闭时整个跳过键收起,而不是保留一个不可用的按钮。末题上跳过即提交,否则最后一题没有出口。
组合
- 步进计数器需要做成逐位滚动时,把
counter作为容器,数字交给数值动画,判定权仍在本组件。 - 问卷提交后需要执行危险操作时,把审批排在它后面,两件事分开:问卷收集的是“怎么做”,闸门收集的是“做不做”。
- 放入对话框时把
initialFocus指向当前题的第一个选项,打开即可用方向键作答。
最佳实践
- 题目控制在三到五道:这是执行前的澄清,不是问卷调查。
- 单选题的选项写成互斥的完整答案,不依赖自由文本补充关键信息。
- 提交之后卡片不会自动消失:宿主需要在
onSubmit中决定后续动作,需要保留时渲染result部件。
反模式
- 用它承载不可逆的动作确认:问卷没有“拒绝”路径,跳过与不答都会让流程继续。
- 把
counter的文字当作播报:该部件对读屏隐藏,修改它不会被读出。 - 关闭自动前进的同时隐藏继续键:单选题将没有出口。
API 参考
产物
| 层 | 值 |
|---|---|
| 自定义元素 | <xh-question-flow> |
| Vue 组件 | XhQuestionFlowCounter XhQuestionFlowDescription XhQuestionFlowFooter XhQuestionFlowGroup XhQuestionFlowItem XhQuestionFlowItemDescription XhQuestionFlowItemIndicator XhQuestionFlowItemText XhQuestionFlowLiveRegion XhQuestionFlowNextTrigger XhQuestionFlowNote XhQuestionFlowPrevTrigger XhQuestionFlowPrompt XhQuestionFlowQuestion XhQuestionFlowResult XhQuestionFlowRoot XhQuestionFlowSkipTrigger XhQuestionFlowSubmitTrigger XhQuestionFlowTrack XhQuestionFlowViewport |
| 组合式函数 | useQuestionFlow |
| 状态机 | questionFlowMachine |
| 皮肤 | @xihan-ui/styles/question-flow.css |
Props
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
questions | readonly QuestionFlowQuestion[] | ||
index | number | 当前题下标。提供即受控:内部不再自行修改,只发 onIndexChange。 | |
defaultIndex | number | ||
answers | QuestionFlowAnswers | 答案表。提供即受控。 | |
defaultAnswers | QuestionFlowAnswers | ||
notes | QuestionFlowNotes | 自由文本表。提供即受控。 | |
defaultNotes | QuestionFlowNotes | ||
status | QuestionFlowStatus | 答题状态。提供即受控。 | |
defaultStatus | QuestionFlowStatus | ||
autoAdvance | boolean | 单选选中后自动进入下一题,默认开启。 它只进入下一题,末题上不会替用户提交。 | |
autoAdvanceDelay | number | 自动前进前等待的时长(毫秒),默认 480。非有限值或负数不启动计时器。 | |
allowSkip | boolean | 允许跳过,默认开启。关闭后跳过按钮收起,SKIP 事件也不再生效。 | |
loop | boolean | 选项组内漫游到达末尾是否回绕,默认 true。 | |
variant | ControlVariant | 形态:outline 描边、subtle 底色分区、ghost 无壳内联。默认 outline。 | |
tone | Tone | ||
size | Size | ||
translations | Partial<QuestionFlowTranslations> | ||
onIndexChange | (details: QuestionFlowIndexChangeDetails) => void | ||
onAnswersChange | (details: QuestionFlowAnswersChangeDetails) => void | ||
onNotesChange | (details: QuestionFlowNotesChangeDetails) => void | ||
onSkip | (details: QuestionFlowSkipDetails) => void | ||
onSubmit | (details: QuestionFlowSubmitDetails) => void |
QuestionFlowQuestion
questions 的元素。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | |
prompt | string | 题干。它同时是选项组的可访问名;未提供时回退为 translations 的兜底文案。 | |
type | QuestionFlowType | single = 互斥单选(radiogroup),multiple = 多选(group + checkbox)。默认 single。 | |
options | readonly QuestionFlowOption[] | 是 | |
optional | boolean | 允许不作答直接进入下一题。 | |
description | string | 题目的补充说明,写进 description 部件并成为选项组的描述;缺席时由多选的数量要求代填。 | |
minSelections | number | 多选至少选几项,默认 1。选够之前继续键不可用(写了自由文本同样算作答)。 只对 multiple 生效;非有限值或小于 1 按 1 算。 | |
maxSelections | number | 多选最多选几项。选满之后其余未选项转为不可选(aria-disabled),取消一项又能再选。 只对 multiple 生效;非有限值或小于 1 当没给,小于 minSelections 时按 minSelections 算。 |
事件
自定义元素将载荷放在 detail;Vue 使用同名 emit。
| 事件 | 载荷 | 说明 |
|---|---|---|
index-change | QuestionFlowIndexChangeDetails | 当前题变化;detail 为 { index } |
answers-change | QuestionFlowAnswersChangeDetails | 答案变化;detail 为 { answers } |
notes-change | QuestionFlowNotesChangeDetails | 自由文本变化;detail 为 { notes } |
skip | QuestionFlowSkipDetails | 跳过一题;detail 为 { index, questionId } |
submit | QuestionFlowSubmitDetails | 交卷;detail 为 { answers, notes } |
插槽
仅列出带载荷的插槽。
| Vue 组件 | 插槽 | 载荷 | 说明 |
|---|---|---|---|
XhQuestionFlowItem | default | QuestionFlowOptionSlotProps | |
XhQuestionFlowRoot | default | QuestionFlowRootSlotProps |
React 适配器 props
只列各组件自己声明的那些:继承自 ComponentPropsWithRef 的 DOM 属性不在其中,根组件上与上面 Props 表同名的也不重复列。Vue 的对应物是上面的插槽表。
| React 组件 | 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
XhQuestionFlowDescription | questionId | string | 是 | |
XhQuestionFlowGroup | questionId | string | 是 | |
XhQuestionFlowItem | questionId | string | 是 | |
XhQuestionFlowItem | optionValue | string | 是 | |
XhQuestionFlowItem | optionDisabled | boolean | 默认交给 connect 查询 questions,写死 false 会覆盖数据中的禁用。 | |
XhQuestionFlowItem | children | SlotChildren<QuestionFlowOptionSlotProps> | ||
XhQuestionFlowItemDescription | questionId | string | 是 | |
XhQuestionFlowItemDescription | optionValue | string | 是 | |
XhQuestionFlowItemIndicator | questionId | string | 是 | |
XhQuestionFlowItemIndicator | optionValue | string | 是 | |
XhQuestionFlowItemText | questionId | string | 是 | |
XhQuestionFlowItemText | optionValue | string | 是 | |
XhQuestionFlowNote | questionId | string | 是 | |
XhQuestionFlowPrompt | questionId | string | 是 | |
XhQuestionFlowQuestion | questionId | string | 是 | |
XhQuestionFlowRoot | children | SlotChildren<QuestionFlowRootSlotProps> |
状态
公开状态写入 data-state。
| 部件 | 取值 |
|---|---|
root | 'answering' | 'submitted' |
item | 'checked' | 'unchecked' |
item-indicator | 'checked' | 'unchecked' |
item-text | 'checked' | 'unchecked' |
item-description | 'checked' | 'unchecked' |
result | 'answering' | 'submitted' |
以下名称仅用于内部状态机。
状态:answering · submitted
事件:OPTION.TOGGLE · NOTE.SET · GOTO · NEXT · PREV · SKIP · SUBMIT · VIEWPORT.MEASURE · after.autoAdvance · CONTROLLED.ANSWERING · CONTROLLED.SUBMITTED · PRESS.START · PRESS.END
判据:isStatusControlled · canToggle · canSkip · isFirstQuestion · isLastQuestion · canPress
connect API
getXxxProps() 返回对应部件的宿主属性。
| 成员 | 类型 | 说明 |
|---|---|---|
status | QuestionFlowStatus | |
submitted | boolean | 已提交。 |
index | number | 夹到题数范围内的当前题下标。 |
count | number | 题数。 |
current | QuestionFlowQuestion | undefined | 当前题;没有题目时为 undefined。 |
isFirst | boolean | |
isLast | boolean | |
canAdvance | boolean | 当前题是否可以进入下一题:选够了选项、已填自由文本,或该题本身可跳过。 |
allowSkip | boolean | |
counter | string | 视觉上的 N / M。它对读屏隐藏,进度由播报区朗读。 |
announcement | string | 读屏朗读的语句:答题中朗读进度,提交后朗读结果。 |
answers | QuestionFlowAnswers | |
notes | QuestionFlowNotes | |
answersOf | (questionId: string) => readonly string[] | |
noteOf | (questionId: string) => string | |
isOptionSelected | (questionId: string, value: string) => boolean | |
isCurrent | (questionId: string) => boolean | |
selectionLimitsOf | (questionId: string) => QuestionFlowSelectionLimits | 这一题的数量要求;单选恒为 { min: 1, max: 1 }。 |
descriptionOf | (questionId: string) => string | 这一题的说明文字:题目自带的 description,缺席时由多选的数量要求代填;都没有时为空串。 |
goTo | (index: number) => void | |
next | () => void | |
prev | () => void | |
skip | () => void | |
submit | () => void | |
toggleOption | (questionId: string, value: string) => void | |
setNote | (questionId: string, value: string) => void | |
measure | () => void | 重新测量当前题的几何。换题与题目增删都会自动重新测量,容器尺寸变化由尺寸观察器接管。 |
getRootProps | () => T['element'] | |
getViewportProps | () => T['element'] | |
getTrackProps | () => T['element'] | |
getQuestionProps | (props: QuestionFlowQuestionProps) => T['element'] | |
getPromptProps | (props: QuestionFlowQuestionProps) => T['element'] | |
getDescriptionProps | (props: QuestionFlowQuestionProps) => T['element'] | 题目说明:有说明文字时成为选项组的 aria-describedby。 |
getGroupProps | (props: QuestionFlowQuestionProps) => T['element'] | |
getItemProps | (props: QuestionFlowItemProps) => T['button'] | |
getItemIndicatorProps | (props: QuestionFlowItemProps) => T['element'] | |
getItemTextProps | (props: QuestionFlowItemProps) => T['element'] | |
getItemDescriptionProps | (props: QuestionFlowItemProps) => T['element'] | |
getNoteProps | (props: QuestionFlowQuestionProps) => T['input'] | |
getFooterProps | () => T['element'] | |
getPrevTriggerProps | () => T['button'] | |
getCounterProps | () => T['element'] | |
getNextTriggerProps | () => T['button'] | |
getSkipTriggerProps | () => T['button'] | |
getSubmitTriggerProps | () => T['button'] | |
getResultProps | () => T['element'] | |
getLiveRegionProps | () => T['element'] |
无障碍
键盘
规格出处:W3C APG
| 按键 | 生效条件 | 行为 |
|---|---|---|
ArrowDown / ArrowRight | 焦点在当前题的选项上 | 焦点移到下一个可停留选项(禁用项跳过、尽头按 loop 回绕);单选时同时选中它 |
ArrowUp / ArrowLeft | 焦点在当前题的选项上 | 焦点移到上一个可停留选项;单选时同时选中它 |
Home | 焦点在当前题的选项上 | 焦点移到首个可停留选项;单选时同时选中它 |
End | 焦点在当前题的选项上 | 焦点移到末个可停留选项;单选时同时选中它 |
Space | 焦点在当前题的选项上 | 切换该项。单选点已选中的那一项不取消;多选已选满 maxSelections 时,未选项转为不可选,按了不加,取消已选项照常 |
Enter | 焦点在当前题的选项或自由文本上,且这一题答得能往下走 | 前进一题;已经在末题就交卷 |
Space | 按住当前题的未禁用选项 | 按住期间该选项投影 data-pressed,与指针 :active 同一副按压面(row 档只换面不缩放);抬起、失焦、换题或交卷撤下。Enter 不是选项的激活键,不进按压面 |
Enter / Space | 按住未禁用的上一题 / 下一题 / 跳过 / 继续(发送)按钮 | 按住期间该按钮投影 data-pressed,与指针 :active 同一副按压面;抬起、失焦、换题或交卷撤下 |
ARIA
以下属性由 connect 生成。
| 部件 | 属性 | 值 |
|---|---|---|
question | aria-hidden | undefined | 'true' |
question | aria-label | undefined | translations.prompt |
question | aria-labelledby | prompt 部件的 id | undefined |
question | role | 'group' |
group | aria-describedby | undefined | description 部件的 id |
group | aria-label | undefined | translations.options |
group | aria-labelledby | prompt 部件的 id | undefined |
group | role | 'radiogroup' | 'group' |
item | aria-checked | 'true' | 'false' |
item | aria-disabled | 'true' | 'false' |
item | role | 'radio' | 'checkbox' |
item-indicator | aria-hidden | 'true' |
note | aria-label | translations.note |
prev-trigger | aria-label | translations.prev |
counter | aria-hidden | 'true' |
next-trigger | aria-label | translations.next |
skip-trigger | aria-label | translations.skip |
submit-trigger | aria-label | translations.send | translations.continue |
result | aria-hidden | 'true' |
live-region | aria-atomic | 'true' |
live-region | aria-live | 'polite' |
- 每题是
role=group,题干是它的可访问名称;题干缺席时退到translations.prompt。 - 选项组按题型取
role=radiogroup(单选)或role=group(多选),同样由题干命名、由题目说明描述(aria-describedby,多选的数量要求就在其中);选项各自是role=radio或role=checkbox并显式报告aria-checked。选项说明排在选项之内,跟着选项名一起念。 - 选项组内是漫游焦点:整组只占一个 Tab 位,落在选中项上,没有选中时落在首个可停留项。
- 上一题 / 下一题只提供按钮入口,不接管全局按键,避免与选项漫游争抢方向键。这两个按钮通常只绘制箭头,因此它们的可访问名称始终发出(
translations.prev/translations.next,默认Previous question/Next question);跳过键一般带可见文字,未提供translations.skip时不产出aria-label。 - 自由文本取
translations.note作为可访问名称(默认Other answer),占位文字取translations.notePlaceholder。 - 备注框与选项组都处理输入法组合态:组合期间的 Enter 用于确认候选词,不前进。
样式参考
皮肤
@xihan-ui/styles/question-flow.css 按 [data-scope="question-flow"][data-part="root"] 部件选择器书写,发布产物以挂载类 .xh-scope-question-flow 代替其中的 data-scope(特异性相同),位于 xihan.components 层。覆盖样式使用 xihan.overrides,部件选择器照常可用。
forced-colors: active 下另有一套规则:颜色交给系统,边框与状态标记改用系统色关键字。
数据属性
由 connect 生成;条件不成立时不输出无值属性。
| 部件 | 属性 | 值 |
|---|---|---|
root | data-size | props.size |
root | data-state | 'answering' | 'submitted' |
root | data-tone | props.tone |
root | data-variant | props.variant |
question | data-current | ''(条件成立时才出现) |
group | data-at-max | ''(条件成立时才出现) |
group | data-select-mode | 'single' | 'multiple' |
item | data-disabled | ''(条件成立时才出现) |
item | data-pressed | ''(条件成立时才出现) |
item | data-select-mode | 'single' | 'multiple' |
item | data-state | 'checked' | 'unchecked' |
item | data-xh-action-control | '' |
item | data-xh-action-display | 'always' |
item | data-xh-action-profile | 'row' |
item | data-xh-action-size | props.size |
item | data-xh-action-variant | 'ghost' |
item-indicator | data-select-mode | 'single' | 'multiple' |
item-indicator | data-state | 'checked' | 'unchecked' |
item-indicator | data-xh-check-mark | undefined | 'checked' | 'unchecked' |
item-indicator | data-xh-check-mark-profile | undefined | 'box' |
item-text | data-state | 'checked' | 'unchecked' |
item-text | data-value | item.value |
item-description | data-state | 'checked' | 'unchecked' |
item-description | data-value | item.value |
prev-trigger | data-disabled | ''(条件成立时才出现) |
prev-trigger | data-pressed | ''(条件成立时才出现) |
prev-trigger | data-xh-action-control | '' |
prev-trigger | data-xh-action-display | 'always' |
prev-trigger | data-xh-action-profile | 'icon' |
prev-trigger | data-xh-action-size | 'xs' |
prev-trigger | data-xh-action-variant | 'ghost' |
next-trigger | data-disabled | ''(条件成立时才出现) |
next-trigger | data-pressed | ''(条件成立时才出现) |
next-trigger | data-xh-action-control | '' |
next-trigger | data-xh-action-display | 'always' |
next-trigger | data-xh-action-profile | 'icon' |
next-trigger | data-xh-action-size | 'xs' |
next-trigger | data-xh-action-variant | 'ghost' |
skip-trigger | data-disabled | ''(条件成立时才出现) |
skip-trigger | data-pressed | ''(条件成立时才出现) |
skip-trigger | data-xh-action-control | '' |
skip-trigger | data-xh-action-display | 'always' |
skip-trigger | data-xh-action-profile | 'text' |
skip-trigger | data-xh-action-size | props.size |
skip-trigger | data-xh-action-variant | 'ghost' |
submit-trigger | data-disabled | ''(条件成立时才出现) |
submit-trigger | data-mode | 'send' | 'continue' |
submit-trigger | data-pressed | ''(条件成立时才出现) |
submit-trigger | data-tone | props.tone |
submit-trigger | data-xh-action-control | '' |
submit-trigger | data-xh-action-display | 'always' |
submit-trigger | data-xh-action-profile | 'text' |
submit-trigger | data-xh-action-size | props.size |
submit-trigger | data-xh-action-variant | 'solid' |
submit-trigger | data-xh-ink-surface | '' |
result | data-state | 'answering' | 'submitted' |
result | data-tone | 'success' | undefined |
CSS 变量
本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。
| 变量 | 部件 | CSS 属性 | 状态 | 默认来源 | 说明 |
|---|---|---|---|---|---|
--xh-question-flow-action-font-size | skip-triggersubmit-trigger | font-size | default | --xh-text-label-size | question-flow 的 skip-trigger、submit-trigger 部件 font-size 覆盖槽。 |
--xh-question-flow-action-font-weight | skip-triggersubmit-trigger | font-weight | default | --xh-text-label-weight | question-flow 的 skip-trigger、submit-trigger 部件 font-weight 覆盖槽。 |
--xh-question-flow-action-gap | skip-triggersubmit-trigger | gap | default | --xh-space-1 | question-flow 的 skip-trigger、submit-trigger 部件 gap 覆盖槽。 |
--xh-question-flow-action-h | skip-triggersubmit-trigger | block-sizeinline-sizemin-block-size | defaultxh-action-profile=iconxh-action-profile=row | --xh-_question-flow-h | question-flow 的 skip-trigger、submit-trigger 部件 block-size、inline-size、min-block-size 覆盖槽。 |
--xh-question-flow-action-px | skip-triggersubmit-trigger | padding-inline | default | --xh-_question-flow-px | question-flow 的 skip-trigger、submit-trigger 部件 padding-inline 覆盖槽。 |
--xh-question-flow-action-radius | skip-triggersubmit-trigger | border-radius | default | --xh-shape-control | question-flow 的 skip-trigger、submit-trigger 部件 border-radius 覆盖槽。 |
--xh-question-flow-bg | root | background | defaultvariant=subtle | --xh-_tone-subtle--xh-bg-surface | question-flow 的 root 部件 background 覆盖槽。 |
--xh-question-flow-border | root | border | default | --xh-border-default | question-flow 的 root 部件 border 覆盖槽。 |
--xh-question-flow-counter-fg | counter | color | default | --xh-fg-subtle | question-flow 的 counter 部件 color 覆盖槽。 |
--xh-question-flow-counter-font-size | counter | font-size | default | --xh-text-caption-size | question-flow 的 counter 部件 font-size 覆盖槽。 |
--xh-question-flow-description-fg | description | color | default | --xh-fg-muted | question-flow 的 description 部件 color 覆盖槽。 |
--xh-question-flow-description-font-size | description | font-size | default | --xh-text-secondary-size | question-flow 的 description 部件 font-size 覆盖槽。 |
--xh-question-flow-dot-radius | item-indicator | border-radius | emptyselect-mode=single | --xh-shape-circle | question-flow 的 item-indicator 部件 border-radius 覆盖槽。 |
--xh-question-flow-dot-size | item-indicator | block-sizeinline-size | emptyselect-mode=single | --xh-question-flow-indicator-size | question-flow 的 item-indicator 部件 block-size、inline-size 覆盖槽。 |
--xh-question-flow-footer-gap | footer | gap | default | --xh-space-3 | question-flow 的 footer 部件 gap 覆盖槽。 |
--xh-question-flow-gap | root | gap | default | --xh-_question-flow-gap | question-flow 的 root 部件 gap 覆盖槽。 |
--xh-question-flow-group-gap | group | gap | default | --xh-space-1 | question-flow 的 group 部件 gap 覆盖槽。 |
--xh-question-flow-icon-size | root | --xh-icon-size | defaultsize=lgsize=mdsize=sm | --xh-glyph-size-lg--xh-glyph-size-md--xh-glyph-size-sm | question-flow 的 root 部件 --xh-icon-size 覆盖槽。 |
--xh-question-flow-indicator-bg | item-indicator | background | default | transparent | question-flow 的 item-indicator 部件 background 覆盖槽。 |
--xh-question-flow-indicator-bg-checked | item-indicator | background | state=checked | --xh-_tone | question-flow 的 item-indicator 部件 background 覆盖槽。 |
--xh-question-flow-indicator-border | item-indicator | border | default | --xh-border-strong | question-flow 的 item-indicator 部件 border 覆盖槽。 |
--xh-question-flow-indicator-border-checked | item-indicator | border-color | state=checked | --xh-_tone | question-flow 的 item-indicator 部件 border-color 覆盖槽。 |
--xh-question-flow-indicator-fg | item-indicator | color | default | --xh-_tone-on | question-flow 的 item-indicator 部件 color 覆盖槽。 |
--xh-question-flow-indicator-icon-size | item-indicator | --xh-icon-size | default | --xh-_question-flow-indicator-glyph | question-flow 的 item-indicator 部件 --xh-icon-size 覆盖槽。 |
--xh-question-flow-indicator-radius | item-indicator | border-radius | default | --xh-shape-inset | question-flow 的 item-indicator 部件 border-radius 覆盖槽。 |
--xh-question-flow-indicator-radius-single | item-indicator | border-radius | select-mode=single | --xh-shape-circle | question-flow 的 item-indicator 部件 border-radius 覆盖槽。 |
--xh-question-flow-indicator-size | item-descriptionitem-indicator | --xh-icon-sizeblock-sizeinline-sizepadding-inline-start | defaultemptyselect-mode=single | --xh-_question-flow-indicator | question-flow 的 item-description、item-indicator 部件 --xh-icon-size、block-size、inline-size、padding-inline-start 覆盖槽。 |
--xh-question-flow-item-bg | item | --xh-ink-surfacebackground-color | defaultxh-ink-surface | --xh-_action-variant-bg-rest | question-flow 的 item 部件 --xh-ink-surface、background-color 覆盖槽。 |
--xh-question-flow-item-bg-hover | item | background-color | disabledhoverloadingnot([data-disabled])not([data-loading]) | --xh-_action-variant-bg-hover | question-flow 的 item 部件 background-color 覆盖槽。 |
--xh-question-flow-item-description-fg | item-description | color | default | --xh-fg-subtle | question-flow 的 item-description 部件 color 覆盖槽。 |
--xh-question-flow-item-description-font-size | item-description | font-size | default | --xh-text-caption-size | question-flow 的 item-description 部件 font-size 覆盖槽。 |
--xh-question-flow-item-fg | item | color | defaultdisabledhoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressed | --xh-fg-muted | question-flow 的 item 部件 color 覆盖槽。 |
--xh-question-flow-item-fg-checked | item | color | disabledhoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressedstate=checked | --xh-fg-default | question-flow 的 item 部件 color 覆盖槽。 |
--xh-question-flow-item-font-size | item | font-size | default | --xh-_question-flow-font-size | question-flow 的 item 部件 font-size 覆盖槽。 |
--xh-question-flow-item-gap | itemitem-description | gappadding-inline-start | default | --xh-space-1_5 | question-flow 的 item、item-description 部件 gap、padding-inline-start 覆盖槽。 |
--xh-question-flow-item-px | item | padding-inline | default | --xh-space-2 | question-flow 的 item 部件 padding-inline 覆盖槽。 |
--xh-question-flow-item-py | item | padding-block | xh-action-profile=row | --xh-space-1 | question-flow 的 item 部件 padding-block 覆盖槽。 |
--xh-question-flow-item-radius | item | border-radius | default | --xh-_action-profile-radius | question-flow 的 item 部件 border-radius 覆盖槽。 |
--xh-question-flow-note-bg | note | background | default | --xh-bg-field | question-flow 的 note 部件 background 覆盖槽。 |
--xh-question-flow-note-bg-disabled | note | background | disabled | --xh-bg-subtle | question-flow 的 note 部件 background 覆盖槽。 |
--xh-question-flow-note-bg-focus | note | background | focus-within | --xh-bg-surface | question-flow 的 note 部件 background 覆盖槽。 |
--xh-question-flow-note-border | note | border | default | --xh-border-control | question-flow 的 note 部件 border 覆盖槽。 |
--xh-question-flow-note-border-disabled | note | border-color | disabled | --xh-border-default | question-flow 的 note 部件 border-color 覆盖槽。 |
--xh-question-flow-note-border-focus | note | border-colorbox-shadow | focus-within | --xh-border-control-focus | question-flow 的 note 部件 border-color、box-shadow 覆盖槽。 |
--xh-question-flow-note-border-hover | note | border-color | hoverinvalidnot(:disabled, :focus, [data-invalid]) | --xh-border-strong | question-flow 的 note 部件 border-color 覆盖槽。 |
--xh-question-flow-note-fg | note | color | default | --xh-fg-default | question-flow 的 note 部件 color 覆盖槽。 |
--xh-question-flow-note-font-size | note | font-size | default | --xh-_question-flow-font-size | question-flow 的 note 部件 font-size 覆盖槽。 |
--xh-question-flow-note-px | note | padding-inline | default | --xh-space-2 | question-flow 的 note 部件 padding-inline 覆盖槽。 |
--xh-question-flow-note-py | note | padding-block | default | --xh-space-1_5 | question-flow 的 note 部件 padding-block 覆盖槽。 |
--xh-question-flow-note-radius | note | border-radius | default | --xh-shape-control | question-flow 的 note 部件 border-radius 覆盖槽。 |
--xh-question-flow-padding | root | padding | default | --xh-_question-flow-p | question-flow 的 root 部件 padding 覆盖槽。 |
--xh-question-flow-placeholder-fg | note | color | placeholder | --xh-fg-subtle | question-flow 的 note 部件 color 覆盖槽。 |
--xh-question-flow-prompt-fg | prompt | color | default | --xh-fg-default | question-flow 的 prompt 部件 color 覆盖槽。 |
--xh-question-flow-prompt-font-size | prompt | font-size | default | --xh-text-label-size | question-flow 的 prompt 部件 font-size 覆盖槽。 |
--xh-question-flow-prompt-font-weight | prompt | font-weight | default | --xh-font-weight-semibold | question-flow 的 prompt 部件 font-weight 覆盖槽。 |
--xh-question-flow-question-gap | question | gap | default | --xh-space-2 | question-flow 的 question 部件 gap 覆盖槽。 |
--xh-question-flow-radius | root | border-radius | default | --xh-shape-surface | question-flow 的 root 部件 border-radius 覆盖槽。 |
--xh-question-flow-result-bg | result | background | default | --xh-_tone-subtle | question-flow 的 result 部件 background 覆盖槽。 |
--xh-question-flow-result-fg | result | color | default | --xh-_tone-fg | question-flow 的 result 部件 color 覆盖槽。 |
--xh-question-flow-result-font-size | result | font-size | default | --xh-text-caption-size | question-flow 的 result 部件 font-size 覆盖槽。 |
--xh-question-flow-result-font-weight | result | font-weight | default | --xh-font-weight-medium | question-flow 的 result 部件 font-weight 覆盖槽。 |
--xh-question-flow-result-gap | result | gap | default | --xh-space-1 | question-flow 的 result 部件 gap 覆盖槽。 |
--xh-question-flow-result-h | result | min-block-size | default | --xh-chip-h-sm | question-flow 的 result 部件 min-block-size 覆盖槽。 |
--xh-question-flow-result-px | result | padding-inline | default | --xh-space-1_5 | question-flow 的 result 部件 padding-inline 覆盖槽。 |
--xh-question-flow-result-py | result | padding-block | default | 0 | question-flow 的 result 部件 padding-block 覆盖槽。 |
--xh-question-flow-result-radius | result | border-radius | default | --xh-shape-control | question-flow 的 result 部件 border-radius 覆盖槽。 |
--xh-question-flow-shadow | root | box-shadow | default | none | question-flow 的 root 部件 box-shadow 覆盖槽。 |
--xh-question-flow-skip-bg | skip-trigger | --xh-ink-surfacebackground-color | defaultxh-ink-surface | --xh-_action-variant-bg-rest | question-flow 的 skip-trigger 部件 --xh-ink-surface、background-color 覆盖槽。 |
--xh-question-flow-skip-bg-hover | skip-trigger | background-color | disabledhoverloadingnot([data-disabled])not([data-loading]) | --xh-_action-variant-bg-hover | question-flow 的 skip-trigger 部件 background-color 覆盖槽。 |
--xh-question-flow-skip-fg | skip-trigger | color | default | --xh-fg-muted | question-flow 的 skip-trigger 部件 color 覆盖槽。 |
--xh-question-flow-skip-fg-hover | skip-trigger | color | disabledhoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressed | --xh-fg-default | question-flow 的 skip-trigger 部件 color 覆盖槽。 |
--xh-question-flow-step-bg | next-triggerprev-trigger | --xh-ink-surfacebackground-color | defaultxh-ink-surface | --xh-_action-variant-bg-rest | question-flow 的 next-trigger、prev-trigger 部件 --xh-ink-surface、background-color 覆盖槽。 |
--xh-question-flow-step-bg-hover | next-triggerprev-trigger | background-color | disabledhoverloadingnot([data-disabled])not([data-loading]) | --xh-_action-variant-bg-hover | question-flow 的 next-trigger、prev-trigger 部件 background-color 覆盖槽。 |
--xh-question-flow-step-fg | next-triggerprev-trigger | color | default | --xh-fg-subtle | question-flow 的 next-trigger、prev-trigger 部件 color 覆盖槽。 |
--xh-question-flow-step-fg-hover | next-triggerprev-trigger | color | disabledhoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressed | --xh-fg-default | question-flow 的 next-trigger、prev-trigger 部件 color 覆盖槽。 |
--xh-question-flow-step-padding | next-triggerprev-trigger | padding-inline | default | --xh-_action-profile-padding-inline | question-flow 的 next-trigger、prev-trigger 部件 padding-inline 覆盖槽。 |
--xh-question-flow-step-radius | next-triggerprev-trigger | border-radius | default | --xh-shape-inset | question-flow 的 next-trigger、prev-trigger 部件 border-radius 覆盖槽。 |
--xh-question-flow-step-size | next-triggerprev-trigger | block-sizeinline-sizemin-block-size | defaultxh-action-profile=iconxh-action-profile=row | --xh-_action-profile-visual-size | question-flow 的 next-trigger、prev-trigger 部件 block-size、inline-size、min-block-size 覆盖槽。 |
--xh-question-flow-submit-bg | submit-trigger | --xh-ink-surfacebackground-color | defaultxh-ink-surface | --xh-_action-variant-bg-rest | question-flow 的 submit-trigger 部件 --xh-ink-surface、background-color 覆盖槽。 |
--xh-question-flow-submit-bg-active | submit-trigger | background-color | disabledis(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressed | --xh-_action-variant-bg-pressed | question-flow 的 submit-trigger 部件 background-color 覆盖槽。 |
--xh-question-flow-submit-bg-hover | submit-trigger | background-color | disabledhoverloadingnot([data-disabled])not([data-loading]) | --xh-_action-variant-bg-hover | question-flow 的 submit-trigger 部件 background-color 覆盖槽。 |
--xh-question-flow-submit-bg-off | submit-trigger | --xh-ink-surfacebackground-color | disabledxh-ink-surface | --xh-_action-variant-bg-disabled | question-flow 的 submit-trigger 部件 --xh-ink-surface、background-color 覆盖槽。 |
--xh-question-flow-submit-fg | submit-trigger | color | defaultdisabledhoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressed | --xh-_action-variant-fg-hover--xh-_action-variant-fg-pressed--xh-_action-variant-fg-rest | question-flow 的 submit-trigger 部件 color 覆盖槽。 |
--xh-question-flow-submit-shadow | submit-trigger | box-shadow | defaultdisabledhoveris(:active, [data-pressed])loadingnot([data-disabled])not([data-loading])pressed | --xh-_highlight-tone | question-flow 的 submit-trigger 部件 box-shadow 覆盖槽。 |
--xh-question-flow-track-gap | track | gap | default | --xh-_question-flow-gap | question-flow 的 track 部件 gap 覆盖槽。 |
--xh-question-flow-track-y | track | translate | default | --xh-_question-flow-track-y | question-flow 的 track 部件 translate 覆盖槽。 |
--xh-question-flow-viewport-h | viewport | block-size | default | --xh-_question-flow-viewport-h | question-flow 的 viewport 部件 block-size 覆盖槽。 |
动效
动效角色:按压 · 状态 · 切换 · 指示与换位 · 出现 · 列表(见动效规范)。
共享关键帧 xh-item-in · xh-pop-in · xh-rise-in 由 family/motion.css 提供,皮肤 @import 它,单独引入仍成立;-webkit-mask-size · background-color · block-size · border-color · clip-path · color · mask-size · opacity · scale · translate 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。
系统开启减弱动效时由令牌层统一收敛,皮肤不另作判断。
RTL
皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像。
