Live Region

Dynamic content announced by screen readers.

3 items added to your cart

html

<div class="lr-demo" data-politeness="polite" style="--accent:#A8E6C1;">
  <div class="lr-demo__region" aria-live="polite" role="status">
    <p class="lr-demo__msg">3 items added to your cart</p>
  </div>
  <p class="lr-demo__caption"></p>
</div>
<style>
.lr-demo { width: 320px; font: 14px system-ui, sans-serif; color: #241430; }
.lr-demo__region { min-height: 40px; border-radius: 8px; border: 1.5px dashed var(--accent); padding: 10px 12px; }
.lr-demo__msg { margin: 0; font-weight: 600; }
.lr-demo__caption { margin-top: 10px; font-size: 12px; color: #241430aa; }
.lr-demo[data-politeness="polite"] .lr-demo__caption::after { content: "announced after the screen reader finishes its current sentence"; }
.lr-demo[data-politeness="assertive"] .lr-demo__caption::after { content: "announced immediately, interrupting whatever is being read"; }
.lr-demo[data-politeness="off"] .lr-demo__caption::after { content: "not announced at all"; }
</style>

tailwind

<div class="lr-tw lr-tw--polite" style="width:320px;font-family:system-ui,sans-serif;color:#241430">
  <div aria-live="polite" role="status" class="min-h-[40px] rounded-lg border-[1.5px] border-dashed px-3 py-2.5" style="border-color:#A8E6C1">
    <p class="m-0 font-semibold">3 items added to your cart</p>
  </div>
  <p class="lr-tw__caption mt-2.5 text-xs text-[#241430aa]"></p>
</div>
<style>
.lr-tw--polite .lr-tw__caption::after { content: "announced after the screen reader finishes its current sentence"; }
.lr-tw--assertive .lr-tw__caption::after { content: "announced immediately, interrupting whatever is being read"; }
.lr-tw--off .lr-tw__caption::after { content: "not announced at all"; }
</style>

react

export function LiveRegion({
  message = "3 items added to your cart",
  politeness = "polite",
  visible = true,
  accent = "#A8E6C1",
}) {
  const captions = {
    polite: "announced after the screen reader finishes its current sentence",
    assertive: "announced immediately, interrupting whatever is being read",
    off: "not announced at all",
  };
  return (
    <div style={{ width: 320, fontFamily: "system-ui, sans-serif", fontSize: 14, color: "#241430" }}>
      <div aria-live={politeness} role="status" style={{ minHeight: 40, borderRadius: 8, border: "1.5px dashed " + accent, padding: "10px 12px" }}>
        {visible && <p style={{ margin: 0, fontWeight: 600 }}>{message}</p>}
      </div>
      <p style={{ marginTop: 10, fontSize: 12, color: "#241430aa" }}>{captions[politeness]}</p>
    </div>
  );
}