Skip to content

Form Flow Examples

This document provides practical examples of common form flow patterns.

A basic flow with sequential steps:

import {
flow,
step,
textInput,
emailInput,
nextFromInput,
} from '@getevy/evy-ui/flow';
const registrationFlow = flow({
id: 'registration',
steps: [
// Step 1: Personal Information
step({
id: 'personal-info',
blocks: [
textInput({ id: 'firstName' }),
textInput({ id: 'lastName' }),
emailInput({ id: 'email' }),
],
next: 'address', // Go to address step next
}),
// Step 2: Address
step({
id: 'address',
blocks: [
textInput({ id: 'street' }),
textInput({ id: 'city' }),
textInput({ id: 'zipCode' }),
],
next: 'submit', // End the flow
}),
],
});

A flow that branches based on user input:

import {
flow,
step,
dropdown,
textInput,
nextFromInput,
} from '@getevy/evy-ui/flow';
const supportFlow = flow({
id: 'support-request',
steps: [
// Step 1: Request Type
step({
id: 'request-type',
blocks: [
dropdown({
id: 'type',
values: [
{ value: 'technical', label: 'Technical Issue' },
{ value: 'billing', label: 'Billing Question' },
{ value: 'feedback', label: 'General Feedback' },
],
}),
],
// Route based on the selected request type
next: nextFromInput({
path: 'request-type.type',
routes: [
{ value: 'technical', next: 'technical-details' },
{ value: 'billing', next: 'billing-details' },
{ value: 'feedback', next: 'feedback-details' },
],
}),
}),
// Technical Issue Branch
step({
id: 'technical-details',
blocks: [
dropdown({
id: 'product',
values: [
{ value: 'website', label: 'Website' },
{ value: 'mobile-app', label: 'Mobile App' },
{ value: 'desktop-app', label: 'Desktop App' },
],
}),
textInput({ id: 'description' }),
],
next: 'contact-info',
}),
// Billing Question Branch
step({
id: 'billing-details',
blocks: [
textInput({ id: 'accountNumber' }),
dropdown({
id: 'billingIssue',
values: [
{ value: 'charge', label: 'Unexpected Charge' },
{ value: 'cancellation', label: 'Cancellation Problem' },
{ value: 'other', label: 'Other' },
],
}),
textInput({ id: 'description' }),
],
next: 'contact-info',
}),
// Feedback Branch
step({
id: 'feedback-details',
blocks: [textInput({ id: 'description', isRequired: true })],
next: 'contact-info',
}),
// Common Final Step
step({
id: 'contact-info',
blocks: [
emailInput({ id: 'email' }),
textInput({ id: 'phone', isRequired: false }),
],
next: 'submit',
}),
],
});

A form with nested data organization:

import { flow, step, textInput, emailInput } from '@getevy/evy-ui/flow';
const userProfileFlow = flow({
id: 'user-profile',
steps: [
// Basic Information
step({
id: 'basic-info',
blocks: [
textInput({ id: 'profile.firstName' }),
textInput({ id: 'profile.lastName' }),
emailInput({ id: 'profile.email' }),
],
next: 'contact-details',
}),
// Contact Information
step({
id: 'contact-details',
blocks: [
textInput({ id: 'contact.primary.phone' }),
textInput({ id: 'contact.primary.address' }),
textInput({ id: 'contact.emergency.name' }),
textInput({ id: 'contact.emergency.phone' }),
],
next: 'submit',
}),
],
});
// Resulting data structure:
// {
// "basic-info": {
// "profile": {
// "firstName": "John",
// "lastName": "Doe",
// "email": "john.doe@example.com"
// }
// },
// "contact-details": {
// "contact": {
// "primary": {
// "phone": "555-123-4567",
// "address": "123 Main St"
// },
// "emergency": {
// "name": "Jane Doe",
// "phone": "555-987-6543"
// }
// }
// }
// }

Form with Content Blocks and Various Input Types

Section titled “Form with Content Blocks and Various Input Types”

A form with a mix of content blocks and different input types:

import {
flow,
step,
text,
section,
textInput,
dateInput,
dropdown,
checkbox,
file,
singleChoice,
} from '@getevy/evy-ui/flow';
const insuranceClaimFlow = flow({
id: 'insurance-claim',
steps: [
// Introduction Step
step({
id: 'intro',
blocks: [
text({ id: 'intro-text' }),
section({
id: 'important-notice',
color: 'warning',
}),
],
next: 'personal-details',
}),
// Personal Details
step({
id: 'personal-details',
blocks: [
textInput({ id: 'fullName' }),
textInput({ id: 'policyNumber' }),
emailInput({ id: 'email' }),
],
next: 'incident-details',
}),
// Incident Details
step({
id: 'incident-details',
blocks: [
dateInput({
id: 'incidentDate',
withDatePicker: true,
rule: 'only-in-past',
}),
dropdown({
id: 'incidentType',
values: [
{ value: 'theft', label: 'Theft' },
{ value: 'damage', label: 'Damage' },
{ value: 'loss', label: 'Loss' },
],
}),
singleChoice({
id: 'locationTypes',
options: [
{ id: 'home', icon: 'home' },
{ id: 'street', icon: 'signpost' },
{ id: 'store', icon: 'storefront' },
{ id: 'transport', icon: 'directions_bus' },
],
}),
textInput({ id: 'description' }),
],
next: 'documentation',
}),
// Documentation
step({
id: 'documentation',
blocks: [
text({ id: 'documentation-instructions' }),
file({ id: 'purchaseReceipt' }),
file({ id: 'damagePhotos' }),
checkbox({ id: 'confirmTruth' }),
],
next: 'submit',
}),
],
});

A form with dropdowns where the options of one depend on the selection in another:

import {
flow,
step,
dropdownWithCondition,
dropdown,
} from '@getevy/evy-ui/flow';
const productSelectionFlow = flow({
id: 'product-selection',
steps: [
step({
id: 'product-selection',
blocks: [
dropdown({
id: 'category',
values: [
{ value: 'electronics', label: 'Electronics' },
{ value: 'clothing', label: 'Clothing' },
{ value: 'food', label: 'Food & Beverages' },
],
}),
// Options depend on the selected category
dropdownWithCondition({
id: 'subcategory',
dependency: 'category',
values: {
electronics: [
{ value: 'phones', label: 'Smartphones' },
{ value: 'laptops', label: 'Laptops' },
{ value: 'accessories', label: 'Accessories' },
],
clothing: [
{ value: 'mens', label: "Men's Clothing" },
{ value: 'womens', label: "Women's Clothing" },
{ value: 'kids', label: "Kids' Clothing" },
],
food: [
{ value: 'fresh', label: 'Fresh Produce' },
{ value: 'frozen', label: 'Frozen Foods' },
{ value: 'snacks', label: 'Snacks & Candy' },
],
},
}),
],
next: 'submit',
}),
],
});
import { FlowRender } from '@getevy/evy-ui/flow-render';
import { registrationFlow } from './flows/registration';
function RegistrationPage() {
const handleSubmit = data => {
console.log('Registration submitted:', data);
// Process submission
};
return (
<div className="registration-page">
<h1>Create an Account</h1>
<FlowRender
flow={registrationFlow}
locale="en"
onSubmit={handleSubmit}
useStorage={true}
/>
</div>
);
}