Framework Setup
Next.js, Vite, Remix, Create React App and testing setup.
Framework Setup
The package ships ESM, CommonJS and UMD builds with correct TypeScript types for every module-resolution mode, so most setups need no configuration at all.
Next.js — App Router
The published bundles carry a "use client" directive, so importing from a
server component works with no wrapper.
import "react-form-wizard-component/styles.css";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}import FormWizard from "react-form-wizard-component";
export default function Page() {
return (
<FormWizard title="Signup">
<FormWizard.TabContent title="Account">…</FormWizard.TabContent>
<FormWizard.TabContent title="Review">…</FormWizard.TabContent>
</FormWizard>
);
}Before v1.2.0 the bundles carried no directive, so App Router users hit "useState only works in Client Components" and had to wrap the import. That directive now ships in the package.
Your own step content is a different matter: a step containing useState or an
event handler needs "use client" at the top of that file, as usual.
Next.js — Pages Router
Import the stylesheet in _app:
import "react-form-wizard-component/styles.css";
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}The wizard renders on the server and hydrates normally — storage and URL access
are guarded, so persist and syncToUrl are SSR-safe.
Vite
Nothing to configure.
import "react-form-wizard-component/styles.css";Remix / React Router
Export the stylesheet from your route's links:
import styles from "react-form-wizard-component/styles.css?url";
export const links = () => [{ rel: "stylesheet", href: styles }];Create React App
import "react-form-wizard-component/styles.css";CRA 5 resolves the package's exports map correctly. On CRA 4 or older, use
the long path instead:
import "react-form-wizard-component/dist/style.css";Testing
Jest
react-form-wizard-component is ESM-first but also ships CommonJS, so
require() works in a default Jest setup. You only need to map the stylesheet:
export default {
testEnvironment: "jsdom",
moduleNameMapper: {
"\\.(css|less|scss)$": "identity-obj-proxy",
},
};Older releases resolved the require condition to a file that exported
nothing, so Jest received an empty object. Fixed — there is a real CommonJS
build now.
Vitest
export default defineConfig({
test: { environment: "jsdom", css: true },
});Querying the wizard in tests
The markup is accessible, so query by role rather than by class:
render(<Signup />);
expect(screen.getByRole("tablist")).toBeInTheDocument();
await userEvent.click(screen.getByText("Next"));
expect(screen.getByRole("status")).toHaveTextContent("Step 2 of 3");TypeScript
Types ship with the package — no @types/* install. Resolution is verified in
CI under bundler, node16 and node10.
{
"compilerOptions": {
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true
}
}Bundle size
Roughly 5 kB gzipped for the JavaScript and 2 kB for the stylesheet,
with React left external. The package is side-effect free apart from the CSS,
so tree-shaking works: importing only useWizard pulls in neither the
component nor the styles.