This is a quick tutorial to show you the barebones of how to create a Wizzard Steps component.
import type { NextPage } from 'next';
import React, { useReducer } from 'react';
type StepsProps = {
children: React.ReactNode;
};
const Steps = ({ children }: StepsProps) => {
let idx = 0;
const _children = React.Children.map(children, (child) => {
if (!React.isValidElement(child)) return null;
return React.cloneElement(child, { ...child.props, idx: ++idx });
});
return <div className="space-y-1">{_children}</div>;
};
type StepProps = {
title: string;
children: React.ReactNode;
idx?: number;
};
const Step = ({ title, idx, children }: StepProps) => {
return (
<div className="border border-dashed border-gray-400 p-2">
<div className="flex gap-2">
<span className="bg-red-300 px-1">{idx}</span>
<h4>{title}</h4>
</div>
<div className="mt-2">{children}</div>
</div>
);
};
const Home: NextPage = () => {
const [hasWarranty, toggleWarranty] = useReducer((s) => !s, false);
return (
<div className="p-4">
<h1 className="text-2xl">Checkout</h1>
<button
onClick={toggleWarranty}
className="bg-gray-700 px-2 py-1 text-white"
>
Toggle Warranty Step
</button>
<div className="mt-3">
<Steps>
<Step title="Contact Details">Step Details</Step>
<Step title="Aditional Add-Ons">Step Details</Step>
{hasWarranty && <Step title="Extended Warranty">Step Details</Step>}
<Step title="Shipping Details">Step Details</Step>
<Step title="Payment Details">Step Details</Step>
</Steps>
</div>
</div>
);
};
export default Home;
Notice how the <Steps/>
injects the idx into the <Step/>
component without having to manually enter it.
const Steps = ({ children }: StepsProps) => {
let idx = 0;
const _children = React.Children.map(children, (child) => {
if (!React.isValidElement(child)) return null;
return React.cloneElement(child, { ...child.props, idx: ++idx });
});
return <div className="space-y-1">{_children}</div>;
};
Top comments (0)