react-form-stepwise
v0.1.0
Published
A headless, TypeScript-first form stepwise library for React
Downloads
4
Maintainers
Readme
React Form Stepwise
A headless, TypeScript-first library for building multi-step forms in React.
You bring the UI. We handle the complexity.
✨ Features
- 🎯 Headless - No UI components, full styling control
- 🔒 Type-safe - Built with TypeScript, full autocomplete support
- ✅ Validation - Works with Zod, Yup, or custom validators
- 💾 Persistence - Auto-save to localStorage (optional)
- 🔀 Conditional steps - Show/hide steps based on form data
- 📊 Progress tracking - Built-in progress calculation
- 🪶 Lightweight - Small bundle size
- ⚡ Framework agnostic validation - Use any validation library
- 🎨 Accessible - You control the markup and ARIA attributes
📦 Installation
npm install react-form-stepwisePeer dependencies:
react^18.0.0 or ^19.0.0
Note: zustand is included automatically as a dependency.
🚀 Quick Start
1. Define your Steps
import { createStepwiseStore } from 'react-form-stepwise';
type Steps = 'personal' | 'address' | 'confirmation';
const config = {
steps: ['personal', 'address', 'confirmation'] as Steps[],
persistKey: 'onboarding-form', // Optional: enables auto-save
};
const useFormSteps = createStepwiseStore(config);2. Use in your component
import { useStepwise } from 'react-form-stepwise';
function MyForm() {
const store = useFormSteps();
const stepwise = useStepwise(store, config.steps);
return (
Step {stepwise.currentStepIndex + 1} of {stepwise.totalSteps}
{/* Your step components */}
{stepwise.currentStep === 'personal' && }
{stepwise.currentStep === 'address' && }
{stepwise.currentStep === 'confirmation' && }
{/* Navigation */}
Previous
Next
);
}###3. Build Your Step Components
function PersonalStep({ stepwise }) {
const data = stepwise.getStepData('personal') || {};
const errors = stepwise.errors.personal || {};
return (
<input
value={data.name || ''}
onChange={(e) => stepwise.updateCurrentStepData({ name: e.target.value })}
/>
{errors.name && {errors.name}}
);
}📖 Core Concepts
Type-Safe Steps
Define your steps with TypeScript for full autocomplete:
type OnboardingSteps = 'account' | 'profile' | 'preferences';
const useOnboarding = createStepwiseStore<OnboardingSteps>({
steps: ['account', 'profile', 'preferences'],
});
// In your component
function MyComponent() {
const store = useOnboarding();
const stepwise = useStepwise(store, ['account', 'profile', 'preferences']);
stepwise.goToStep('account'); // ✅ Autocomplete works
stepwise.goToStep('invalid'); // ❌ TypeScript error
}Validation
Use any validation library (zod, yup, custom functions):
Example with zod
import { z } from 'zod';
const personalSchema = z.object({
name: z.string().min(1, 'Name is required'),
email: z.string().email('Invalid email'),
});
const config = {
steps: ['personal', 'address'],
schemas: {
personal: async (data) => {
const result = personalSchema.safeParse(data);
if (!result.success) {
const errors = {};
result.error.errors.forEach((err) => {
if (err.path[0]) {
errors[err.path[0]] = err.message;
}
});
return errors;
}
return null;
},
},
};Example with custom validation
const config = {
steps: ['signup'],
schemas: {
signup: async (data) => {
const errors = {};
if (!data.email) {
errors.email = 'Email is required';
}
// Async validation
const isEmailTaken = await checkEmailAvailability(data.email);
if (isEmailTaken) {
errors.email = 'Email already registered';
}
return Object.keys(errors).length > 0 ? errors : null;
},
},
};The stepwise automatically validates before advancing steps.
Persistence
Enable auto-save to local-storage:
const config = {
steps: ['step1', 'step2'],
persistKey: 'my-form', // Saves to localStorage as 'stepwise_my-form'
};Users can close the browser and continue later. Clear persisted data with:
stepwise.clearPersistedData();Conditional steps
Show/hide steps based on form data:
const config = {
steps: [
{ id: 'account' },
{
id: 'business',
shouldShow: (formData) => formData.account?.type === 'business'
},
{ id: 'payment' },
],
};🎨 API Reference
createStepwiseStore(config)
Creates a Zustand store for your stepwise form.
Config options:
interface StepwiseConfig {
// Required: list of step identifiers
steps: TStepId[] | StepConfig[];
// Optional: validation schemas per step
schemas?: Partial<Record>;
// Optional: localStorage key for persistence
persistKey?: string;
// Optional: initial form data
initialData?: FormData;
// Optional: callbacks
onStepChange?: (from: TStepId | null, to: TStepId) => void;
onComplete?: (data: FormData) => void;
onError?: (error: Error) => void;
}useStepwise(store, steps)
Hook that provides stepwise state and actions.
Returns:
{
// Current state
currentStep: string;
currentStepIndex: number;
totalSteps: number;
isFirstStep: boolean;
isLastStep: boolean;
progress: number; // 0-100
// Form data
formData: Record;
errors: Record>;
// Navigation
nextStep: () => Promise;
previousStep: () => void;
goToStep: (step: string) => Promise;
canGoNext: boolean;
canGoPrevious: boolean;
// Data management
updateStepData: (step: string, data: any) => void;
updateCurrentStepData: (data: any) => void;
resetForm: () => void;
clearPersistedData: () => void;
// Validation
validateStep: (step: string) => Promise;
validateAllSteps: () => Promise;
setFieldError: (step: string, field: string, message: string) => void;
clearErrors: (step?: string) => void;
// Submission
submitForm: (submitFn: (data) => Promise) => Promise;
isSubmitting: boolean;
// Utilities
getStepData: (step: string) => T | undefined;
hasStepData: (step: string) => boolean;
visitedSteps: Set;
}🎯 Use Cases
Perfect for:
- ✅ Multi-step onboarding flows
- ✅ Checkout processes
- ✅ Survey forms
- ✅ User registration forms
- ✅ Configuration wizards
- ✅ Application forms
Not ideal for:
- ❌ Single-page forms (use React Hook Form directly)
- ❌ Simple contact forms
📄 License
MIT © fhdzleon
🙏 Credits
Built with:
- Zustand - State management
- TypeScript - Type safety
- Vite - Build tool
Inspired by the headless UI philosophy and the need for a simple, type-safe multi-step form solution.
🌟 Star us on GitHub!
If you find this library useful, please consider giving it a star ⭐
Built with ❤️ by skullDev81 ☠️ in spare time as part of continuous learning# react-form-stepwise
