Selectable List

List with selection capability.

Select recipients

1 selected

html

<div class="sel sel--card" style="--accent:#BFD9F2;">
  <h3 class="sel__heading">Select recipients</h3>
  <p class="sel__count" role="status">1 selected</p>
  <ul class="sel__list">
    <li class="sel__row"><input type="checkbox" id="sel-a" class="sel__checkbox"><label for="sel-a">Alicia Ferreira</label></li>
    <li class="sel__row"><input type="checkbox" id="sel-b" class="sel__checkbox" checked><label for="sel-b">Ben Sato</label></li>
    <li class="sel__row"><input type="checkbox" id="sel-c" class="sel__checkbox"><label for="sel-c">Charu Deshpande</label></li>
  </ul>
</div>
<style>
.sel { font: 14px/1.4 system-ui, sans-serif; color: #241430; background: #FAF7F2; max-width: 300px; width: 300px; padding: 16px; border-radius: 12px; box-sizing: border-box; }
.sel__heading { margin: 0 0 6px; font-size: 15px; font-weight: 700; }
.sel__count { margin: 0 0 10px; font-size: 12px; color: #241430a0; }
.sel__list { list-style: none; margin: 0; padding: 0; }
.sel__row { display: flex; align-items: center; gap: 10px; padding: 9px 8px; }
.sel__row label { cursor: pointer; }
.sel__checkbox { width: 17px; height: 17px; accent-color: var(--accent); cursor: pointer; }
.sel--card .sel__row { background: #fff; border-radius: 8px; margin-bottom: 6px; box-shadow: 0 1px 4px rgba(36,20,48,.08); }
.sel--card .sel__row:last-child { margin-bottom: 0; }
.sel--divided .sel__row { border-bottom: 1px solid #24143020; }
.sel--divided .sel__row:last-child { border-bottom: none; }
.sel__checkbox:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
</style>

tailwind

<div class="sel-tw sel-tw--card font-sans text-sm text-[#241430] bg-[#FAF7F2] max-w-[300px] w-[300px] p-4 rounded-xl box-border" style="--accent:#BFD9F2">
  <h3 class="m-0 mb-1.5 text-[15px] font-bold">Select recipients</h3>
  <p role="status" class="m-0 mb-2.5 text-xs text-[#241430a0]">1 selected</p>
  <ul class="list-none m-0 p-0">
    <li class="sel-tw__row flex items-center gap-2.5 py-2 px-2"><input type="checkbox" id="selt-a" class="w-[17px] h-[17px] cursor-pointer" style="accent-color:#BFD9F2"><label for="selt-a" class="cursor-pointer">Alicia Ferreira</label></li>
    <li class="sel-tw__row flex items-center gap-2.5 py-2 px-2"><input type="checkbox" id="selt-b" class="w-[17px] h-[17px] cursor-pointer" style="accent-color:#BFD9F2" checked><label for="selt-b" class="cursor-pointer">Ben Sato</label></li>
    <li class="sel-tw__row flex items-center gap-2.5 py-2 px-2"><input type="checkbox" id="selt-c" class="w-[17px] h-[17px] cursor-pointer" style="accent-color:#BFD9F2"><label for="selt-c" class="cursor-pointer">Charu Deshpande</label></li>
  </ul>
</div>
<style>
.sel-tw--card .sel-tw__row { background: #fff; border-radius: 8px; margin-bottom: 6px; box-shadow: 0 1px 4px rgba(36,20,48,.08); }
.sel-tw--card .sel-tw__row:last-child { margin-bottom: 0; }
.sel-tw--divided .sel-tw__row { border-bottom: 1px solid #24143020; }
.sel-tw--divided .sel-tw__row:last-child { border-bottom: none; }
</style>

react

import { useState } from "react";

export function SelectableList({
  heading = "Select recipients",
  accent = "#BFD9F2",
  style = "card",
  secondChecked = true,
  showCount = true,
}) {
  const [checked, setChecked] = useState({ a: false, b: secondChecked, c: false });
  const count = Object.values(checked).filter(Boolean).length;
  const rowStyle = {
    display: "flex", alignItems: "center", gap: 10, padding: "9px 8px",
    background: style === "card" ? "#fff" : "transparent",
    borderRadius: style === "card" ? 8 : 0,
    marginBottom: style === "card" ? 6 : 0,
    boxShadow: style === "card" ? "0 1px 4px rgba(36,20,48,.08)" : "none",
    borderBottom: style === "divided" ? "1px solid #24143020" : "none",
  };
  const people = [["a", "Alicia Ferreira"], ["b", "Ben Sato"], ["c", "Charu Deshpande"]];
  return (
    <div style={{ fontFamily: "system-ui, sans-serif", fontSize: 14, color: "#241430", background: "#FAF7F2", maxWidth: 300, width: 300, padding: 16, borderRadius: 12, boxSizing: "border-box" }}>
      <h3 style={{ margin: "0 0 6px", fontSize: 15, fontWeight: 700 }}>{heading}</h3>
      {showCount && <p role="status" style={{ margin: "0 0 10px", fontSize: 12, color: "#241430a0" }}>{count} selected</p>}
      <ul style={{ listStyle: "none", margin: 0, padding: 0 }}>
        {people.map(([id, name]) => (
          <li key={id} style={rowStyle}>
            <input type="checkbox" id={`rsel-${id}`} checked={checked[id]} onChange={() => setChecked((c) => ({ ...c, [id]: !c[id] }))} style={{ width: 17, height: 17, accentColor: accent, cursor: "pointer" }} />
            <label htmlFor={`rsel-${id}`} style={{ cursor: "pointer" }}>{name}</label>
          </li>
        ))}
      </ul>
    </div>
  );
}