Multi-step workflow contained in a modal.
Step 1 of 3
Untitled project will be created for the Design team with Editor access.
<div class="wizard-demo wizard-demo--backdrop">
<div class="wizard wizard--standard wizard--step1" style="width:420px;--accent:#A8E6C1;" role="dialog" aria-modal="true" aria-labelledby="wizard-title">
<div class="wizard__header">
<h3 class="wizard__title" id="wizard-title">Create project</h3>
<button class="wizard__close" type="button" aria-label="Close">
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><path d="M1 1l12 12M13 1L1 13" stroke="currentColor" stroke-width="1.6" fill="none" stroke-linecap="round"/></svg>
</button>
</div>
<p class="wizard__progress">Step 1 of 3</p>
<div class="wizard__dots" aria-hidden="true">
<span class="wizard__dot wizard__dot--1"></span>
<span class="wizard__dot wizard__dot--2"></span>
<span class="wizard__dot wizard__dot--3"></span>
</div>
<div class="wizard__step wizard__step--1">
<h4>Project details</h4>
<label class="wizard__field">Name<input class="wizard__input" type="text" value="Untitled project" readonly></label>
<label class="wizard__field">Description<input class="wizard__input" type="text" value="A short summary" readonly></label>
</div>
<div class="wizard__step wizard__step--2">
<h4>Team and permissions</h4>
<label class="wizard__field">Team<input class="wizard__input" type="text" value="Design" readonly></label>
<label class="wizard__field">Role<input class="wizard__input" type="text" value="Editor" readonly></label>
</div>
<div class="wizard__step wizard__step--3">
<h4>Review and confirm</h4>
<p class="wizard__summary">Untitled project will be created for the Design team with Editor access.</p>
</div>
<div class="wizard__actions">
<button class="wizard__btn wizard__btn--ghost" type="button">Back</button>
<button class="wizard__btn wizard__btn--solid" type="button">Next</button>
</div>
</div>
</div>
<style>
.wizard-demo { display: grid; place-items: center; min-height: 380px; border-radius: 12px; }
.wizard-demo--backdrop { background: rgba(36,20,48,.45); padding: 24px; }
.wizard { font: 16px/1.5 system-ui, sans-serif; background: #FAF7F2; color: #241430; border-radius: 14px; box-shadow: 0 20px 44px rgba(36,20,48,.28); padding: 24px; box-sizing: border-box; }
.wizard--compact { padding: 16px; }
.wizard__header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.wizard__title { margin: 0; font-size: 18px; font-weight: 600; }
.wizard__close { background: none; border: none; cursor: pointer; color: #241430; padding: 4px; border-radius: 6px; }
.wizard__close:hover, .wizard__close:focus-visible { background: var(--accent); outline: none; }
.wizard__progress { margin: 0 0 10px; font-size: 13px; color: #24143099; }
.wizard__dots { display: flex; gap: 6px; margin-bottom: 18px; }
.wizard__dot { width: 8px; height: 8px; border-radius: 50%; background: #24143026; }
.wizard__step { display: none; }
.wizard__step h4 { margin: 0 0 12px; font-size: 15px; }
.wizard__field { display: block; font-size: 13px; font-weight: 500; margin-bottom: 12px; }
.wizard__input { display: block; width: 100%; box-sizing: border-box; margin-top: 4px; padding: 8px 10px; border-radius: 8px; border: 1.5px solid #24143033; font: 14px system-ui, sans-serif; color: #241430; background: #fff; }
.wizard__summary { font-size: 14px; color: #241430cc; margin: 0; }
.wizard__actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 8px; }
.wizard__btn { font: 500 14px system-ui, sans-serif; padding: 9px 16px; border-radius: 8px; border: 1.5px solid transparent; cursor: pointer; }
.wizard__btn--ghost { background: transparent; border-color: #24143033; color: #241430; }
.wizard__btn--solid { background: var(--accent); border-color: var(--accent); color: #241430; }
.wizard__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.wizard--step1 .wizard__step--1 { display: block; }
.wizard--step1 .wizard__dot--1 { background: var(--accent); }
.wizard--step2 .wizard__step--2 { display: block; }
.wizard--step2 .wizard__dot--1, .wizard--step2 .wizard__dot--2 { background: var(--accent); }
.wizard--step3 .wizard__step--3 { display: block; }
.wizard--step3 .wizard__dot--1, .wizard--step3 .wizard__dot--2, .wizard--step3 .wizard__dot--3 { background: var(--accent); }
</style><div class="grid place-items-center min-h-[380px] rounded-xl bg-[#241430]/45 p-6">
<div role="dialog" aria-modal="true" aria-labelledby="wizard-tw-title" class="wizard-tw wizard-tw--standard wizard-tw--step1 bg-[#FAF7F2] text-[#241430] rounded-2xl shadow-2xl p-6 box-border font-sans" style="width:420px;--accent:#A8E6C1;">
<div class="flex items-center justify-between mb-1.5">
<h3 id="wizard-tw-title" class="m-0 text-lg font-semibold">Create project</h3>
<button type="button" aria-label="Close" class="bg-transparent border-none cursor-pointer text-[#241430] p-1 rounded-md hover:bg-[var(--accent)] focus-visible:bg-[var(--accent)] focus-visible:outline-none">
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><path d="M1 1l12 12M13 1L1 13" stroke="currentColor" stroke-width="1.6" fill="none" stroke-linecap="round"/></svg>
</button>
</div>
<p class="m-0 mb-2.5 text-[13px] text-[#241430]/60">Step 1 of 3</p>
<div class="flex gap-1.5 mb-[18px]" aria-hidden="true">
<span class="wizard-tw__dot wizard-tw__dot--1 w-2 h-2 rounded-full bg-[#24143026]"></span>
<span class="wizard-tw__dot wizard-tw__dot--2 w-2 h-2 rounded-full bg-[#24143026]"></span>
<span class="wizard-tw__dot wizard-tw__dot--3 w-2 h-2 rounded-full bg-[#24143026]"></span>
</div>
<div class="wizard-tw__step wizard-tw__step--1 hidden">
<h4 class="mt-0 mb-3 text-[15px]">Project details</h4>
<label class="block text-[13px] font-medium mb-3">Name<input type="text" value="Untitled project" readonly class="block w-full box-border mt-1 px-2.5 py-2 rounded-lg border border-[#24143033] text-sm bg-white"></label>
<label class="block text-[13px] font-medium mb-3">Description<input type="text" value="A short summary" readonly class="block w-full box-border mt-1 px-2.5 py-2 rounded-lg border border-[#24143033] text-sm bg-white"></label>
</div>
<div class="wizard-tw__step wizard-tw__step--2 hidden">
<h4 class="mt-0 mb-3 text-[15px]">Team and permissions</h4>
<label class="block text-[13px] font-medium mb-3">Team<input type="text" value="Design" readonly class="block w-full box-border mt-1 px-2.5 py-2 rounded-lg border border-[#24143033] text-sm bg-white"></label>
<label class="block text-[13px] font-medium mb-3">Role<input type="text" value="Editor" readonly class="block w-full box-border mt-1 px-2.5 py-2 rounded-lg border border-[#24143033] text-sm bg-white"></label>
</div>
<div class="wizard-tw__step wizard-tw__step--3 hidden">
<h4 class="mt-0 mb-3 text-[15px]">Review and confirm</h4>
<p class="text-sm text-[#241430]/80 m-0">Untitled project will be created for the Design team with Editor access.</p>
</div>
<div class="flex justify-end gap-2.5 mt-2">
<button type="button" class="px-4 py-2 rounded-lg text-sm font-medium border border-[#24143033]">Back</button>
<button type="button" class="px-4 py-2 rounded-lg text-sm font-medium" style="background:#A8E6C1;border:1.5px solid #A8E6C1;">Next</button>
</div>
</div>
</div>
<style>
.wizard-tw--compact { padding: 16px !important; }
.wizard-tw--step1 .wizard-tw__step--1 { display: block; }
.wizard-tw--step1 .wizard-tw__dot--1 { background: var(--accent); }
.wizard-tw--step2 .wizard-tw__step--2 { display: block; }
.wizard-tw--step2 .wizard-tw__dot--1, .wizard-tw--step2 .wizard-tw__dot--2 { background: var(--accent); }
.wizard-tw--step3 .wizard-tw__step--3 { display: block; }
.wizard-tw--step3 .wizard-tw__dot--1, .wizard-tw--step3 .wizard-tw__dot--2, .wizard-tw--step3 .wizard-tw__dot--3 { background: var(--accent); }
</style>export function ModalWizard({
title = "Create project",
step = 1,
variant = "standard",
accent = "#A8E6C1",
width = 420,
backdrop = true,
}) {
const padding = variant === "compact" ? 16 : 24;
const fieldStyle = { display: "block", fontSize: 13, fontWeight: 500, marginBottom: 12 };
const inputStyle = { display: "block", width: "100%", boxSizing: "border-box", marginTop: 4,
padding: "8px 10px", borderRadius: 8, border: "1.5px solid #24143033", fontSize: 14, background: "#fff", color: "#241430" };
const stepContent = {
1: (
<>
<h4 style={{ margin: "0 0 12px", fontSize: 15 }}>Project details</h4>
<label style={fieldStyle}>Name<input type="text" defaultValue="Untitled project" readOnly style={inputStyle} /></label>
<label style={fieldStyle}>Description<input type="text" defaultValue="A short summary" readOnly style={inputStyle} /></label>
</>
),
2: (
<>
<h4 style={{ margin: "0 0 12px", fontSize: 15 }}>Team and permissions</h4>
<label style={fieldStyle}>Team<input type="text" defaultValue="Design" readOnly style={inputStyle} /></label>
<label style={fieldStyle}>Role<input type="text" defaultValue="Editor" readOnly style={inputStyle} /></label>
</>
),
3: (
<>
<h4 style={{ margin: "0 0 12px", fontSize: 15 }}>Review and confirm</h4>
<p style={{ fontSize: 14, color: "#241430cc", margin: 0 }}>Untitled project will be created for the Design team with Editor access.</p>
</>
),
}[step] ?? null;
return (
<div style={{ display: "grid", placeItems: "center", minHeight: 380, borderRadius: 12,
background: backdrop ? "rgba(36,20,48,.45)" : "transparent", padding: backdrop ? 24 : 0 }}>
<div role="dialog" aria-modal={backdrop ? "true" : "false"} aria-labelledby="wizard-title" style={{
width, boxSizing: "border-box", background: "#FAF7F2", color: "#241430", borderRadius: 14,
boxShadow: "0 20px 44px rgba(36,20,48,.28)", padding, fontFamily: "system-ui, sans-serif" }}>
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 6 }}>
<h3 id="wizard-title" style={{ margin: 0, fontSize: 18, fontWeight: 600 }}>{title}</h3>
<button type="button" aria-label="Close" style={{ background: "none", border: "none", cursor: "pointer",
color: "#241430", padding: 4, borderRadius: 6 }}>
<svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><path d="M1 1l12 12M13 1L1 13" stroke="currentColor" strokeWidth="1.6" fill="none" strokeLinecap="round"/></svg>
</button>
</div>
<p style={{ margin: "0 0 10px", fontSize: 13, color: "#24143099" }}>Step {step} of 3</p>
<div style={{ display: "flex", gap: 6, marginBottom: 18 }} aria-hidden="true">
<span style={{ width: 8, height: 8, borderRadius: "50%", background: step >= 1 ? accent : "#24143026" }} />
<span style={{ width: 8, height: 8, borderRadius: "50%", background: step >= 2 ? accent : "#24143026" }} />
<span style={{ width: 8, height: 8, borderRadius: "50%", background: step >= 3 ? accent : "#24143026" }} />
</div>
{stepContent}
<div style={{ display: "flex", justifyContent: "flex-end", gap: 10, marginTop: 8 }}>
<button type="button" style={{ padding: "9px 16px", borderRadius: 8, border: "1.5px solid #24143033",
background: "transparent", color: "#241430", fontSize: 14, fontWeight: 500 }}>Back</button>
<button type="button" style={{ padding: "9px 16px", borderRadius: 8, border: `1.5px solid ${accent}`,
background: accent, color: "#241430", fontSize: 14, fontWeight: 500 }}>{step >= 3 ? "Finish" : "Next"}</button>
</div>
</div>
</div>
);
}