Saved View

Persisted combination of filters/sort/columns.

Customer orders
OrderCustomerStatusTotal
#1042A. WhitfieldShipped£64.00
#1041R. OkaforProcessing£128.50
#1040M. IqbalShipped£22.00
#1038L. DuarteShipped£96.20

html

<div class="svw" data-view="All orders" style="--accent:#241430;">
  <div class="svw__bar">
    <div class="svw__pills" role="group" aria-label="Saved views">
      <button type="button" class="svw__pill svw__pill--all"><span class="svw__star" aria-hidden="true">&#9733;</span>All orders</button>
      <button type="button" class="svw__pill svw__pill--shipped"><span class="svw__star" aria-hidden="true">&#9733;</span>Shipped only</button>
      <button type="button" class="svw__pill svw__pill--high"><span class="svw__star" aria-hidden="true">&#9733;</span>High value</button>
    </div>
    <button type="button" class="svw__manage">Manage views</button>
  </div>
  <div class="svw__scroll">
    <table class="svw__table">
      <caption>Customer orders</caption>
      <thead><tr><th scope="col">Order</th><th scope="col">Customer</th><th scope="col">Status</th><th scope="col">Total</th></tr></thead>
      <tbody>
        <tr data-status="shipped" data-tier="low"><td>#1042</td><td>A. Whitfield</td><td>Shipped</td><td>£64.00</td></tr>
        <tr data-status="processing" data-tier="high"><td>#1041</td><td>R. Okafor</td><td>Processing</td><td>£128.50</td></tr>
        <tr data-status="shipped" data-tier="low"><td>#1040</td><td>M. Iqbal</td><td>Shipped</td><td>£22.00</td></tr>
        <tr data-status="shipped" data-tier="high"><td>#1038</td><td>L. Duarte</td><td>Shipped</td><td>£96.20</td></tr>
      </tbody>
    </table>
  </div>
</div>
<style>
.svw { font: 14px system-ui, sans-serif; color: #241430; background: #FAF7F2; max-width: 480px; border: 1px solid #24143020; border-radius: 10px; overflow: hidden; }
.svw__bar { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid #24143020; }
.svw__pills { display: flex; gap: 6px; flex-wrap: wrap; }
.svw__pill { border: 1px solid #24143040; background: #FAF7F2; color: #241430; padding: 5px 10px; border-radius: 999px; font: inherit; font-size: 12px; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; }
.svw__pill:hover { background: #24143010; }
.svw__pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.svw__star { display: none; color: #E8A020; }
.svw[data-view="All orders"] .svw__pill--all,
.svw[data-view="Shipped only"] .svw__pill--shipped,
.svw[data-view="High value"] .svw__pill--high { background: var(--accent); color: #FAF7F2; border-color: var(--accent); }
.svw[data-view="All orders"] .svw__pill--all .svw__star,
.svw[data-view="Shipped only"] .svw__pill--shipped .svw__star,
.svw[data-view="High value"] .svw__pill--high .svw__star { display: inline; }
.svw__manage { font-size: 12px; border: 1px solid #24143040; background: #FAF7F2; border-radius: 6px; padding: 5px 10px; cursor: pointer; }
.svw__scroll { overflow-x: auto; }
.svw__table { border-collapse: collapse; width: 100%; }
.svw__table caption { text-align: left; font-weight: 600; padding: 10px 14px; }
.svw__table th, .svw__table td { padding: 10px 14px; text-align: left; border-bottom: 1px solid #24143020; white-space: nowrap; }
.svw__table th { background: var(--accent); color: #FAF7F2; }
.svw[data-view="Shipped only"] tbody tr:not([data-status="shipped"]) { display: none; }
.svw[data-view="High value"] tbody tr:not([data-tier="high"]) { display: none; }
</style>

tailwind

<div class="max-w-[480px] rounded-[10px] border border-[#24143020] font-sans text-sm text-[#241430] bg-[#FAF7F2] overflow-hidden" data-view="All orders" style="--accent:#241430;">
  <div class="flex flex-wrap justify-between items-center gap-2 px-3.5 py-2.5 border-b border-[#24143020]">
    <div class="flex gap-1.5 flex-wrap" role="group" aria-label="Saved views">
      <button type="button" class="svw__pill svw__pill--all inline-flex items-center gap-1 border border-[#24143040] bg-[#FAF7F2] text-[#241430] px-2.5 py-1 rounded-full text-xs"><span aria-hidden="true" class="svw__star text-[#E8A020] hidden">&#9733;</span>All orders</button>
      <button type="button" class="svw__pill svw__pill--shipped inline-flex items-center gap-1 border border-[#24143040] bg-[#FAF7F2] text-[#241430] px-2.5 py-1 rounded-full text-xs"><span aria-hidden="true" class="svw__star text-[#E8A020] hidden">&#9733;</span>Shipped only</button>
      <button type="button" class="svw__pill svw__pill--high inline-flex items-center gap-1 border border-[#24143040] bg-[#FAF7F2] text-[#241430] px-2.5 py-1 rounded-full text-xs"><span aria-hidden="true" class="svw__star text-[#E8A020] hidden">&#9733;</span>High value</button>
    </div>
    <button type="button" class="text-xs border border-[#24143040] bg-[#FAF7F2] rounded-md px-2.5 py-1">Manage views</button>
  </div>
  <div class="overflow-x-auto">
    <table class="border-collapse w-full">
      <caption class="text-left font-semibold px-3.5 py-2.5">Customer orders</caption>
      <thead><tr class="text-[#FAF7F2]" style="background:#241430">
        <th scope="col" class="p-3.5 text-left whitespace-nowrap">Order</th>
        <th scope="col" class="p-3.5 text-left whitespace-nowrap">Customer</th>
        <th scope="col" class="p-3.5 text-left whitespace-nowrap">Status</th>
        <th scope="col" class="p-3.5 text-left whitespace-nowrap">Total</th>
      </tr></thead>
      <tbody>
        <tr data-status="shipped" data-tier="low"><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">#1042</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">A. Whitfield</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">Shipped</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">£64.00</td></tr>
        <tr data-status="processing" data-tier="high"><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">#1041</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">R. Okafor</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">Processing</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">£128.50</td></tr>
        <tr data-status="shipped" data-tier="low"><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">#1040</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">M. Iqbal</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">Shipped</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">£22.00</td></tr>
        <tr data-status="shipped" data-tier="high"><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">#1038</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">L. Duarte</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">Shipped</td><td class="p-3.5 border-b border-[#24143020] whitespace-nowrap">£96.20</td></tr>
      </tbody>
    </table>
  </div>
</div>
<style>
[data-view="All orders"] .svw__pill--all,
[data-view="Shipped only"] .svw__pill--shipped,
[data-view="High value"] .svw__pill--high { background: var(--accent); color: #FAF7F2; border-color: var(--accent); }
[data-view="All orders"] .svw__pill--all .svw__star,
[data-view="Shipped only"] .svw__pill--shipped .svw__star,
[data-view="High value"] .svw__pill--high .svw__star { display: inline; }
[data-view="Shipped only"] tbody tr:not([data-status="shipped"]) { display: none; }
[data-view="High value"] tbody tr:not([data-tier="high"]) { display: none; }
</style>

react

function SavedView({
  caption = "Customer orders",
  accent = "#241430",
  view = "All orders",
  showStar = true,
  manageLabel = "Manage views",
}) {
  const rows = [
    ["#1042", "A. Whitfield", "shipped", "low", "£64.00"],
    ["#1041", "R. Okafor", "processing", "high", "£128.50"],
    ["#1040", "M. Iqbal", "shipped", "low", "£22.00"],
    ["#1038", "L. Duarte", "shipped", "high", "£96.20"],
  ];
  const visible = rows.filter((r) => view === "All orders" || (view === "Shipped only" && r[2] === "shipped") || (view === "High value" && r[3] === "high"));
  const cell = { padding: "10px 14px", borderBottom: "1px solid #24143020", whiteSpace: "nowrap" };
  const pill = (key, label) => (
    <button key={key} type="button" style={{
      display: "inline-flex", alignItems: "center", gap: 4,
      border: `1px solid ${view === key ? accent : "#24143040"}`, background: view === key ? accent : "#FAF7F2",
      color: view === key ? "#FAF7F2" : "#241430", padding: "5px 10px", borderRadius: 999, font: "inherit", fontSize: 12, cursor: "pointer",
    }}>{showStar && view === key && <span aria-hidden="true" style={{ color: "#E8A020" }}>&#9733;</span>}{label}</button>
  );
  return (
    <div style={{ maxWidth: 480, borderRadius: 10, border: "1px solid #24143020", overflow: "hidden", font: "14px system-ui, sans-serif", color: "#241430", background: "#FAF7F2" }}>
      <div style={{ display: "flex", flexWrap: "wrap", justifyContent: "space-between", alignItems: "center", gap: 8, padding: "10px 14px", borderBottom: "1px solid #24143020" }}>
        <div role="group" aria-label="Saved views" style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
          {pill("All orders", "All orders")}{pill("Shipped only", "Shipped only")}{pill("High value", "High value")}
        </div>
        <button type="button" style={{ fontSize: 12, border: "1px solid #24143040", background: "#FAF7F2", borderRadius: 6, padding: "5px 10px", cursor: "pointer" }}>{manageLabel}</button>
      </div>
      <div style={{ overflowX: "auto" }}>
        <table style={{ borderCollapse: "collapse", width: "100%" }}>
          <caption style={{ textAlign: "left", fontWeight: 600, padding: "10px 14px" }}>{caption}</caption>
          <thead>
            <tr style={{ background: accent, color: "#FAF7F2" }}>
              {["Order", "Customer", "Status", "Total"].map((h) => <th key={h} scope="col" style={cell}>{h}</th>)}
            </tr>
          </thead>
          <tbody>
            {visible.map((row) => (
              <tr key={row[0]}>
                <td style={cell}>{row[0]}</td><td style={cell}>{row[1]}</td>
                <td style={cell}>{row[2][0].toUpperCase() + row[2].slice(1)}</td><td style={cell}>{row[4]}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}