Row Expansion

Expands a row to show additional information.

Customer orders
ExpandOrderCustomerTotal
#1042A. Whitfield£64.00
Priority customer — handle with care.
#1041R. Okafor£128.50
#1040M. Iqbal£22.00

html

<div class="rexp" style="--accent:#241430;">
  <div class="rexp__scroll">
    <table class="rexp__table">
      <caption>Customer orders</caption>
      <thead><tr><th scope="col"><span class="sr-only">Expand</span></th><th scope="col">Order</th><th scope="col">Customer</th><th scope="col">Total</th></tr></thead>
      <tbody>
        <tr class="rexp__open">
          <td><button type="button" class="rexp__toggle" aria-expanded="true" aria-controls="rexp-1042"><span class="rexp__arrow" aria-hidden="true">&#9656;</span></button></td>
          <td>#1042</td><td>A. Whitfield</td><td>£64.00</td>
        </tr>
        
        <tr><td colspan="4" id="rexp-1042" class="rexp__detail">Priority customer — handle with care.</td></tr>
        
        <tr class="">
          <td><button type="button" class="rexp__toggle" aria-expanded="false" aria-controls="rexp-1041"><span class="rexp__arrow" aria-hidden="true">&#9656;</span></button></td>
          <td>#1041</td><td>R. Okafor</td><td>£128.50</td>
        </tr>
        
        <tr><td></td><td>#1040</td><td>M. Iqbal</td><td>£22.00</td></tr>
      </tbody>
    </table>
  </div>
</div>
<style>
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;}
.rexp { font: 14px system-ui, sans-serif; color: #241430; background: #FAF7F2; max-width: 480px; border: 1px solid #24143020; border-radius: 10px; overflow: hidden; }
.rexp__scroll { overflow-x: auto; }
.rexp__table { border-collapse: collapse; width: 100%; }
.rexp__table caption { text-align: left; font-weight: 600; padding: 10px 14px; }
.rexp__table th, .rexp__table td { padding: 10px 14px; text-align: left; border-bottom: 1px solid #24143020; white-space: nowrap; }
.rexp__table th { background: var(--accent); color: #FAF7F2; }
.rexp__toggle { background: none; border: 0; cursor: pointer; padding: 2px; display: inline-flex; }
.rexp__toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.rexp__toggle[aria-expanded="true"] .rexp__arrow { transform: rotate(90deg); }
.rexp__arrow { display: inline-block; color: var(--accent); }
@media (prefers-reduced-motion: no-preference) {
  .rexp__arrow { transition: transform .15s; }
}
.rexp__detail { background: #24143008; white-space: normal; color: #241430cc; font-size: 13px; }
.rexp__open { border-left: 3px solid var(--accent); }
</style>

tailwind

<div class="max-w-[480px] rounded-[10px] border border-[#24143020] font-sans text-sm text-[#241430] bg-[#FAF7F2] overflow-hidden" style="--accent:#241430;">
  <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"><span class="sr-only">Expand</span></th>
        <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">Total</th>
      </tr></thead>
      <tbody>
        <tr>
          <td class="p-3.5 border-b border-[#24143020]"><button type="button" class="rexp__toggle bg-transparent border-0 cursor-pointer p-0.5 inline-flex focus-visible:outline focus-visible:outline-2" aria-expanded="true" aria-controls="rexp-1042"><span aria-hidden="true" class="rexp__arrow inline-block motion-safe:transition-transform" style="color:#241430">&#9656;</span></button></td>
          <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">£64.00</td>
        </tr>
        
        <tr><td colspan="4" id="rexp-1042" class="bg-[#24143008] px-3.5 py-2 text-[13px] text-[#241430cc]">Priority customer — handle with care.</td></tr>
        
        <tr>
          <td class="p-3.5 border-b border-[#24143020]"><button type="button" class="rexp__toggle bg-transparent border-0 cursor-pointer p-0.5 inline-flex focus-visible:outline focus-visible:outline-2" aria-expanded="false" aria-controls="rexp-1041"><span aria-hidden="true" class="rexp__arrow inline-block motion-safe:transition-transform" style="color:#241430">&#9656;</span></button></td>
          <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">£128.50</td>
        </tr>
        
        <tr><td class="p-3.5 border-b border-[#24143020]"></td><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">£22.00</td></tr>
      </tbody>
    </table>
  </div>
</div>
<style>
.rexp__toggle[aria-expanded="true"] .rexp__arrow { transform: rotate(90deg); }
</style>

react

function RowExpansion({
  caption = "Customer orders",
  accent = "#241430",
  expand1042 = true,
  expand1041 = false,
  detailContent = "Priority customer — handle with care.",
}) {
  const cell = { padding: "10px 14px", borderBottom: "1px solid #24143020", whiteSpace: "nowrap" };
  const Toggle = ({ open, controls }) => (
    <button type="button" aria-expanded={open} aria-controls={controls} style={{ background: "none", border: 0, cursor: "pointer", padding: 2, display: "inline-flex" }}>
      <span aria-hidden="true" className="rexp-caret" style={{ display: "inline-block", transform: open ? "rotate(90deg)" : "none", color: accent }}>&#9656;</span>
    </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={{ 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", "Total"].map((h, i) => <th key={i} scope="col" style={cell}>{h}</th>)}
            </tr>
          </thead>
          <tbody>
            <tr style={{ borderLeft: expand1042 ? `3px solid ${accent}` : "none" }}>
              <td style={cell}><Toggle open={expand1042} controls="rexp-1042" /></td>
              <td style={cell}>#1042</td><td style={cell}>A. Whitfield</td><td style={cell}>£64.00</td>
            </tr>
            {expand1042 && <tr><td colSpan={4} id="rexp-1042" style={{ background: "#24143008", padding: "8px 14px", fontSize: 13, color: "#241430cc" }}>{detailContent}</td></tr>}
            <tr style={{ borderLeft: expand1041 ? `3px solid ${accent}` : "none" }}>
              <td style={cell}><Toggle open={expand1041} controls="rexp-1041" /></td>
              <td style={cell}>#1041</td><td style={cell}>R. Okafor</td><td style={cell}>£128.50</td>
            </tr>
            {expand1041 && <tr><td colSpan={4} id="rexp-1041" style={{ background: "#24143008", padding: "8px 14px", fontSize: 13, color: "#241430cc" }}>{detailContent}</td></tr>}
            <tr><td style={cell}></td><td style={cell}>#1040</td><td style={cell}>M. Iqbal</td><td style={cell}>£22.00</td></tr>
          </tbody>
        </table>
      </div>
      <style>{`
        @media (prefers-reduced-motion: no-preference) {
          .rexp-caret { transition: transform .15s; }
        }
      `}</style>
    </div>
  );
}