Form step
The form step breaks a longer form into numbered stages. Each step is automatically numbered and pairs a required title with an optional subtitle, followed by its own content at full width.
Accessibility
Every step is exposed as a labelled group (role="group" + aria-labelledby) so assistive technology announces the title as the name of its content. The number badge is decorative (aria-hidden).
TIP
This component is best used within a Form, which resets the numbering. Steps are numbered automatically with a CSS counter.
Props
title: string
The title of the step. Always required.
subtitle?: string
An optional line of supporting text shown below the title.
Slots
default
The content of the step, rendered at full width below the header.
end
Trailing content aligned to the end of the header, such as a status badge.
Examples
End slot
Add trailing content, like a status badge, to the step header through the end slot.
<template>
<FluxPane style="max-width: 480px">
<FluxPaneBody>
<FluxForm>
<FluxFormStep
title="Billing address"
subtitle="Where should we send the invoices?">
<template #end>
<FluxBadge
color="success"
label="Completed"/>
</template>
<FluxFormField label="Street">
<FluxFormInput placeholder="E.g. Main Street 1"/>
</FluxFormField>
</FluxFormStep>
<FluxFormStep
title="Payment method"
subtitle="Add a card to finish setting up billing.">
<template #end>
<FluxBadge
color="warning"
label="Action needed"/>
</template>
<FluxFormField label="Card number">
<FluxFormInput placeholder="E.g. 4242 4242 4242 4242"/>
</FluxFormField>
</FluxFormStep>
</FluxForm>
</FluxPaneBody>
</FluxPane>
</template>
<script
setup
lang="ts">
import { FluxBadge, FluxForm, FluxFormField, FluxFormInput, FluxFormStep, FluxPane, FluxPaneBody } from '@flux-ui/components';
</script>Snippet
<template>
<Preview>
<FluxPane style="max-width: 480px">
<FluxPaneBody>
<FluxForm>
<FluxFormStep
title="Choose how to connect"
subtitle="Bring an existing subscription or supply credentials from a provider.">
<FluxFormRadioGroup
v-model="method"
is-connected>
<FluxFormRadioTile
value="subscription"
icon="sparkles"
label="Use an existing subscription"
sub-label="Bring a plan you already pay for."/>
<FluxFormRadioTile
value="credentials"
icon="user-key"
label="Provider credentials"
sub-label="Supply an API key to power your agents."/>
</FluxFormRadioGroup>
</FluxFormStep>
<FluxFormStep
title="Name your workspace"
subtitle="Pick a name your team will recognise.">
<FluxFormField label="Workspace name">
<FluxFormInput placeholder="E.g. Acme Inc."/>
</FluxFormField>
</FluxFormStep>
<FluxFormStep
title="Link an agent"
subtitle="Pick which agent you want to link, then finish authenticating.">
<FluxFormField label="Agent">
<FluxFormSelect
v-model="agent"
:options="agents"/>
</FluxFormField>
</FluxFormStep>
</FluxForm>
</FluxPaneBody>
</FluxPane>
</Preview>
</template>
<script
setup
lang="ts">
import { FluxForm, FluxFormField, FluxFormInput, FluxFormRadioGroup, FluxFormRadioTile, FluxFormSelect, FluxFormStep, FluxPane, FluxPaneBody } from '@flux-ui/components';
import { ref } from 'vue';
const method = ref('subscription');
const agent = ref('claude-code');
const agents = [
{label: 'Claude Code', value: 'claude-code'},
{label: 'Codex CLI', value: 'codex-cli'},
{label: 'Custom agent', value: 'custom'}
];
</script>