Build dynamic multi-step forms faster
A reusable stepper form package with separate field components, clean variants, React Hook Form support, and config-driven field rendering.
Reusable stepper form
Separate exportable field components
React Hook Form + Zod friendly
Tailwind + twMerge + CVA variants
Dynamic config-based fields
Searchable select and multi-select
Country / state / city fields
Installation
Install the package and required form dependencies.
npx @aravindvjn/stepper-form initQuick Usage
Define your schema, create a steps config, and pass it into the stepper form.
import { StepperForm } from "@aravindvjn/stepper-form";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const schema = z.object({
full_name: z.string().min(1, "Full name is required"),
email: z.string().email("Enter a valid email"),
skills: z.array(z.string()).min(1, "Select at least one skill"),
});
type FormInput = z.input<typeof schema>;
type FormValues = z.output<typeof schema>;
const steps = [
{
step: 1,
title: "Basic Details",
fields: [
{
name: "full_name",
label: "Full Name",
type: "text",
placeholder: "Enter your full name",
required: true,
},
{
name: "email",
label: "Email",
type: "email",
placeholder: "Enter your email",
required: true,
},
],
},
{
step: 2,
title: "Skills",
fields: [
{
name: "skills",
label: "Skills",
type: "multi-select",
required: true,
options: [
{ label: "React", value: "react" },
{ label: "Next.js", value: "nextjs" },
{ label: "TypeScript", value: "typescript" },
],
selectProps: {
searchable: true,
},
},
],
},
];
export default function Example() {
const form = useForm<FormInput, any, FormValues>({
resolver: zodResolver(schema),
defaultValues: {
full_name: "",
email: "",
skills: [],
},
});
return (
<StepperForm
form={form}
steps={steps}
title="Example Form"
description="Simple reusable stepper form"
onSubmit={(values) => {
console.log(values);
}}
/>
);
}How it works
Define fields as objects with type, name, label, placeholder, options, and any extra props like inputProps, selectProps, or phoneProps.
Each field is a separate reusable component, so you can export and use them independently or through the central renderer.
Styling is controlled through CVA variants and merged with tailwind-merge so overrides stay clean.
Package highlights
• Config-driven fields
• Supports custom rendering for uncommon fields
• Works well for admin panels, onboarding forms, and internal tools
• Easy to extend with your own custom field types
• Separate demo page ready for hosting
Live Demo
This is the interactive example showing the supported field types and step flow.
All Input Types Demo
A reusable package-friendly stepper form with separate input components
Notes
This demo is meant for package showcase and documentation. You can deploy this page as your public demo site.
Later you can add tabs for API docs, field props, variants, and CLI usage.