ChoiceCard
A question card answered with rich rows, optionally split into steps.
Installation
pnpm add @talex-touch/tuffex
import { TxChoiceCard } from '@talex-touch/tuffex/choice-card'
import '@talex-touch/tuffex/choice-card/style.css'
// It renders TxIcon and TxSkeleton, whose sheets are separate
import '@talex-touch/tuffex/icon/style.css'
import '@talex-touch/tuffex/skeleton/style.css'
import '@talex-touch/tuffex/base.css' // tokens + resets, once per app
Usage
Single Question
selected marks the picked row; a disabled row can't be picked.
Loading demo...
Steps
The host pages by updating v-model:step in select; columns="2" lays the rows out two per row.
Loading demo...
Loading
loading draws skeleton rows in the rows' own boxes, so nothing shifts when the options arrive.
Loading demo...
Best Practices
- Ask one question per step, with three to six answers.
- Page by updating
v-model:stepinselect, and passselectedfor the page on screen so going back shows the pick. - Bind
loadingthroughuseDeferredLoading, and setloadingRowsto the number of answers coming. - Keep a row that needs something first disabled rather than hidden, and say what it needs in its description.
- Pass
prevLabel,nextLabel, andstepLabelin the page's language; the card ships English defaults only.
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
steps | ChoiceStep[] | - | The pages. Required; when empty and not loading, nothing renders. |
step | number | undefined | Current page, 0-based, for v-model:step; clamped to the pages there are. |
selected | string | undefined | Id of the answer to mark on the page on screen. |
loading | boolean | false | Replaces the rows with skeleton rows and sets aria-busy; the title and pager stay. |
loadingRows | number | 3 | How many skeleton rows loading draws. |
columns | 1 | 2 | 1 | 2 lays rows out two per row; below a 480px card it falls back to one. |
appear | boolean | true | Rows rise in one after another on first render and when loading ends. |
prevLabel | string | 'Previous' | Accessible name of the back arrow. |
nextLabel | string | 'Next' | Accessible name of the forward arrow. |
stepLabel | (current: number, total: number) => string | `${current} / ${total}` | Text of the pager counter; both numbers are 1-based. |
Events
| Event | Params | Description |
|---|---|---|
select | (payload: ChoiceSelectPayload) | Fires when an enabled row is clicked or activated with Enter or Space; the page stays. |
update:step | (index: number) | Fires when an arrow moves to page index, 0-based. |
Slots
| Slot | Props | Description |
|---|---|---|
header | { step: ChoiceStep, stepIndex: number, total: number } | Replaces the default <h3> title; it names the card, so keep the question in it. |
Types
ChoiceStep, one entry of steps:
| Field | Type | Description |
|---|---|---|
id | string | Page identity; a new id on the page on screen replays the page entrance. Required. |
title | string | The question: the card's heading and the name of its answer list. Required. |
options | ChoiceOption[] | The answers. Required. |
ChoiceOption, one answer:
| Field | Type | Default | Description |
|---|---|---|---|
id | string | - | Unique within the page; what selected matches. Required. |
label | string | - | The row's title and accessible name. Required. |
description | string | - | One line under the label, announced as the row's description. |
icon | TxIconSource | string | - | A TxIcon source, or an icon class such as 'i-carbon-edit'. |
disabled | boolean | false | Dimmed; the arrow keys skip it and it emits nothing. |
import type {
ChoiceCardColumns, // 1 | 2
ChoiceCardEmits,
ChoiceCardProps,
ChoiceOption,
ChoiceSelectPayload, // { step, stepIndex, option }
ChoiceStep,
ChoiceStepLabelFormatter, // (current, total) => string
TxChoiceCardInstance,
} from '@talex-touch/tuffex/choice-card'
CSS Variables
| Variable | Description |
|---|---|
--tx-choice-card-pad | Inset between the card edge and the rows, default 8px; the card radius grows with it. |
--tx-choice-card-option-radius | Row corner radius, default 10px; the card radius adds the inset, keeping corners concentric. |
--tx-choice-card-option-pad-x | Horizontal inset of the rows and the title, default 12px. |
--tx-choice-card-label-line | Label line height and icon box height, default 20px. |
--tx-choice-card-desc-line | Description line height, default 18px. |
Set them on the card or any ancestor; the component only writes --tx-choice-card-index (the row's stagger position) on each row.
Overview
- Semantics: a
<section>named by the question, with rows as native<button>s in a<ul role="list">, named by the label and described by the description. The selected row has a check andaria-current="true", so colour is never the only mark. selectnever changes the page. Withoutstep, the card tracks its own page and emitsupdate:step; the pager renders only with two or more pages, and its counter is arole="status"region.- Keyboard: the list is one Tab stop (the selected row, else the first enabled one); Up and Down move and wrap, Left and Right move in reading order in two columns, Home and End jump to the ends, and disabled rows are skipped.
- When the page changes with focus in the list, focus moves to the new page's Tab stop; when the arrow in use becomes disabled, focus moves to the other arrow.
- Two columns fall back to one below a 480px card (a container query), and the arrow keys follow the rendered column count.
- Entrance and page-change motion are CSS animations on fresh nodes, so rows are clickable from their first frame; reduced motion drops them.
Technologies
- Skeleton rows reuse the loaded row's own containers, with
TxSkeletonbars inside. - Source:
packages/tuffex/packages/components/src/choice-card/.
Use cases
- An assistant's opening guide: "Where should we start?", one question per step.
- A "Ready for you" list of suggestions that arrives after the card.
- Reviewing an answered question:
selectedmarks what was picked.
Related components
| Component | For |
|---|---|
| SuggestionChips | One-line follow-up prompts |
| RecommendationCard | One recommendation with alternatives |
| ApprovalCard | Multi-question answers, sent together |
查看源码
packages/tuffex/packages/components/src/choice-card/index.ts