Progressive Onboarding

Introduces functionality gradually.

Step 1 of 3

New: Quick actions

Press Cmd+K anytime to jump to any page.

html

<div class="pon" style="--accent:#BFD9F2;" data-feature="search">
  <div class="pon__toolbar" role="toolbar" aria-label="Quick actions">
    <button type="button" class="pon__icon pon__icon--search" aria-label="Search">🔍</button>
    <button type="button" class="pon__icon pon__icon--shortcuts" aria-label="Keyboard shortcuts">⌨️</button>
    <button type="button" class="pon__icon pon__icon--reactions" aria-label="Reactions">😊</button>
  </div>
  <div class="pon__coach" role="status">
    <p class="pon__step">Step 1 of 3</p>
    <h4 class="pon__heading">New: Quick actions</h4>
    <p class="pon__body">Press Cmd+K anytime to jump to any page.</p>
    <div class="pon__actions">
      <button type="button" class="pon__next">Next</button>
      <button type="button" class="pon__dismiss">Dismiss</button>
    </div>
  </div>
</div>
<style>
.pon { font: 13.5px/1.4 system-ui, sans-serif; color: #241430; background: #FAF7F2; max-width: 320px; width: 320px; padding: 16px; border-radius: 12px; box-sizing: border-box; }
.pon__toolbar { display: flex; gap: 8px; margin-bottom: 14px; }
.pon__icon { width: 34px; height: 34px; border-radius: 8px; border: 1px solid #24143020; background: #fff; font-size: 15px; cursor: pointer; }
.pon[data-feature="search"] .pon__icon--search,
.pon[data-feature="shortcuts"] .pon__icon--shortcuts,
.pon[data-feature="reactions"] .pon__icon--reactions { box-shadow: 0 0 0 3px var(--accent); border-color: transparent; }
.pon__coach { background: #fff; border-radius: 10px; padding: 12px 14px; position: relative; }
.pon__coach::before { content: ""; position: absolute; top: -6px; left: 20px; width: 12px; height: 12px; background: #fff; transform: rotate(45deg); }
.pon__step { margin: 0 0 4px; font-size: 11px; font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: .04em; }
.pon__heading { margin: 0 0 4px; font-size: 14px; font-weight: 700; }
.pon__body { margin: 0 0 10px; color: #241430b3; }
.pon__actions { display: flex; gap: 8px; }
.pon__next { background: var(--accent); border: none; border-radius: 6px; padding: 6px 12px; font: inherit; font-weight: 700; cursor: pointer; }
.pon__dismiss { background: transparent; border: none; color: #241430a0; font: inherit; cursor: pointer; text-decoration: underline; }
</style>

tailwind

<div class="pon-tw font-sans text-[13.5px] text-[#241430] bg-[#FAF7F2] max-w-[320px] w-[320px] p-4 rounded-xl box-border" style="--accent:#BFD9F2" data-feature="search">
  <div role="toolbar" aria-label="Quick actions" class="flex gap-2 mb-3.5">
    <button type="button" aria-label="Search" class="pon-tw__icon pon-tw__icon--search w-[34px] h-[34px] rounded-lg border border-[#24143020] bg-white text-[15px] cursor-pointer">🔍</button>
    <button type="button" aria-label="Keyboard shortcuts" class="pon-tw__icon pon-tw__icon--shortcuts w-[34px] h-[34px] rounded-lg border border-[#24143020] bg-white text-[15px] cursor-pointer">⌨️</button>
    <button type="button" aria-label="Reactions" class="pon-tw__icon pon-tw__icon--reactions w-[34px] h-[34px] rounded-lg border border-[#24143020] bg-white text-[15px] cursor-pointer">😊</button>
  </div>
  <div role="status" class="bg-white rounded-[10px] py-3 px-3.5">
    <p class="m-0 mb-1 text-[11px] font-bold uppercase tracking-wide" style="color:#BFD9F2">Step 1 of 3</p>
    <h4 class="m-0 mb-1 text-sm font-bold">New: Quick actions</h4>
    <p class="m-0 mb-2.5 text-[#241430b3]">Press Cmd+K anytime to jump to any page.</p>
    <div class="flex gap-2">
      <button type="button" class="rounded-md py-1.5 px-3 font-bold border-0 cursor-pointer" style="background:#BFD9F2">Next</button>
      <button type="button" class="bg-transparent border-0 text-[#241430a0] underline cursor-pointer">Dismiss</button>
    </div>
  </div>
</div>
<style>
.pon-tw[data-feature="search"] .pon-tw__icon--search,
.pon-tw[data-feature="shortcuts"] .pon-tw__icon--shortcuts,
.pon-tw[data-feature="reactions"] .pon-tw__icon--reactions { box-shadow: 0 0 0 3px #BFD9F2; border-color: transparent; }
</style>

react

export function ProgressiveOnboarding({
  heading = "New: Quick actions",
  body = "Press Cmd+K anytime to jump to any page.",
  feature = "search",
  accent = "#BFD9F2",
  stepIndex = 1,
  stepTotal = 3,
}) {
  const iconStyle = (id) => ({ width: 34, height: 34, borderRadius: 8, border: "1px solid #24143020", background: "#fff", fontSize: 15, cursor: "pointer", boxShadow: feature === id ? `0 0 0 3px ${accent}` : "none", borderColor: feature === id ? "transparent" : "#24143020" });
  return (
    <div style={{ fontFamily: "system-ui, sans-serif", fontSize: 13.5, color: "#241430", background: "#FAF7F2", maxWidth: 320, width: 320, padding: 16, borderRadius: 12, boxSizing: "border-box" }}>
      <div role="toolbar" aria-label="Quick actions" style={{ display: "flex", gap: 8, marginBottom: 14 }}>
        <button type="button" aria-label="Search" style={iconStyle("search")}>🔍</button>
        <button type="button" aria-label="Keyboard shortcuts" style={iconStyle("shortcuts")}>⌨️</button>
        <button type="button" aria-label="Reactions" style={iconStyle("reactions")}>😊</button>
      </div>
      <div role="status" style={{ background: "#fff", borderRadius: 10, padding: "12px 14px" }}>
        <p style={{ margin: "0 0 4px", fontSize: 11, fontWeight: 700, color: accent, textTransform: "uppercase", letterSpacing: ".04em" }}>Step {stepIndex} of {stepTotal}</p>
        <h4 style={{ margin: "0 0 4px", fontSize: 14, fontWeight: 700 }}>{heading}</h4>
        <p style={{ margin: "0 0 10px", color: "#241430b3" }}>{body}</p>
        <div style={{ display: "flex", gap: 8 }}>
          <button type="button" style={{ background: accent, border: "none", borderRadius: 6, padding: "6px 12px", font: "inherit", fontWeight: 700, cursor: "pointer" }}>Next</button>
          <button type="button" style={{ background: "transparent", border: "none", color: "#241430a0", font: "inherit", cursor: "pointer", textDecoration: "underline" }}>Dismiss</button>
        </div>
      </div>
    </div>
  );
}