Empty-State Onboarding

Empty state doubling as a getting-started prompt.

No projects yet

Create your first project to start tracking work with your team.

html

<div class="empty-onboard" data-icon="rocket" style="--accent:#E8A020">
  <div class="empty-onboard__icon">
    <svg class="ico-rocket" viewBox="0 0 24 24" width="40" height="40" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 2c3 2 5 6 5 10 0 2-1 4-2 5l-3 3-3-3c-1-1-2-3-2-5 0-4 2-8 5-10z"/><circle cx="12" cy="10" r="2"/><path d="M9 16l-3 3 1 3 3-1M15 16l3 3-1 3-3-1"/></svg>
    <svg class="ico-folder" viewBox="0 0 24 24" width="40" height="40" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z"/></svg>
    <svg class="ico-chart" viewBox="0 0 24 24" width="40" height="40" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 20V10M12 20V4M20 20v-7"/></svg>
  </div>
  <h3 class="empty-onboard__heading">No projects yet</h3>
  <p class="empty-onboard__desc">Create your first project to start tracking work with your team.</p>
  <button type="button" class="empty-onboard__action">Create project</button>
</div>
<style>
.empty-onboard { font: 16px/1.5 system-ui, sans-serif; text-align: center; max-width: 300px; padding: 32px 24px; background: #FAF7F2; border: 1.5px dashed #24143030; border-radius: 14px; color: #241430; }
.empty-onboard__icon { color: var(--accent); margin-bottom: 12px; display: flex; justify-content: center; }
.empty-onboard__icon svg { display: none; }
.empty-onboard[data-icon="rocket"] .ico-rocket,
.empty-onboard[data-icon="folder"] .ico-folder,
.empty-onboard[data-icon="chart"] .ico-chart { display: block; }
.empty-onboard__heading { margin: 0 0 6px; font-size: 17px; font-weight: 600; }
.empty-onboard__desc { margin: 0 0 18px; font-size: 13.5px; color: #241430cc; }
.empty-onboard__action { background: var(--accent); color: #241430; border: none; padding: 10px 18px; border-radius: 8px; font: 600 14px system-ui, sans-serif; cursor: pointer; }
.empty-onboard__action:focus-visible { outline: 2px solid #241430; outline-offset: 2px; }
</style>

tailwind

<div class="empty-onboard-tw text-center max-w-[300px] p-8 bg-[#FAF7F2] border-[1.5px] border-dashed border-[#24143030] rounded-2xl text-[#241430] font-sans" data-icon="rocket" style="--accent:#E8A020">
  <div class="flex justify-center mb-3" style="color:#E8A020">
    <svg class="ico-rocket-tw" viewBox="0 0 24 24" width="40" height="40" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 2c3 2 5 6 5 10 0 2-1 4-2 5l-3 3-3-3c-1-1-2-3-2-5 0-4 2-8 5-10z"/><circle cx="12" cy="10" r="2"/></svg>
    <svg class="ico-folder-tw" viewBox="0 0 24 24" width="40" height="40" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z"/></svg>
    <svg class="ico-chart-tw" viewBox="0 0 24 24" width="40" height="40" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 20V10M12 20V4M20 20v-7"/></svg>
  </div>
  <h3 class="m-0 mb-1.5 text-[17px] font-semibold">No projects yet</h3>
  <p class="m-0 mb-4.5 text-[13.5px] text-[#241430]/80">Create your first project to start tracking work with your team.</p>
  <button type="button" class="border-0 px-4.5 py-2.5 rounded-lg text-sm font-semibold text-[#241430]" style="background:#E8A020">Create project</button>
</div>
<style>
.empty-onboard-tw .ico-rocket-tw, .empty-onboard-tw .ico-folder-tw, .empty-onboard-tw .ico-chart-tw { display: none; }
.empty-onboard-tw[data-icon="rocket"] .ico-rocket-tw,
.empty-onboard-tw[data-icon="folder"] .ico-folder-tw,
.empty-onboard-tw[data-icon="chart"] .ico-chart-tw { display: block; }
</style>

react

export function EmptyStateOnboarding({
  heading = "No projects yet",
  description = "Create your first project to start tracking work with your team.",
  actionLabel = "Create project",
  icon = "rocket",
  accent = "#E8A020",
}) {
  const icons = {
    rocket: (
      <svg viewBox="0 0 24 24" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M12 2c3 2 5 6 5 10 0 2-1 4-2 5l-3 3-3-3c-1-1-2-3-2-5 0-4 2-8 5-10z" /><circle cx="12" cy="10" r="2" /></svg>
    ),
    folder: (
      <svg viewBox="0 0 24 24" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z" /></svg>
    ),
    chart: (
      <svg viewBox="0 0 24 24" width="40" height="40" fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M4 20V10M12 20V4M20 20v-7" /></svg>
    ),
  };
  return (
    <div style={{ fontFamily: "system-ui, sans-serif", textAlign: "center", maxWidth: 300, padding: "32px 24px", background: "#FAF7F2", border: "1.5px dashed #24143030", borderRadius: 14, color: "#241430" }}>
      <div style={{ color: accent, marginBottom: 12, display: "flex", justifyContent: "center" }}>{icons[icon] ?? icons.rocket}</div>
      <h3 style={{ margin: "0 0 6px", fontSize: 17, fontWeight: 600 }}>{heading}</h3>
      <p style={{ margin: "0 0 18px", fontSize: 13.5, color: "#241430cc" }}>{description}</p>
      <button type="button" style={{ background: accent, color: "#241430", border: "none", padding: "10px 18px", borderRadius: 8, fontWeight: 600, fontSize: 14, cursor: "pointer" }}>{actionLabel}</button>
    </div>
  );
}