AI Status

Indicates AI processing state.

Idle Thinking… Responding… Something went wrong

html

<div class="ai-status ai-status--thinking ai-status--pulse" role="status" aria-live="polite" style="--accent:#D9C8F0;">
  <span class="ai-status__icon" aria-hidden="true">
    <span class="glyph glyph--idle">&#9679;</span>
    <span class="glyph glyph--thinking">&#8230;</span>
    <span class="glyph glyph--responding">&#9646;&#9646;&#9646;</span>
    <span class="glyph glyph--error">&#9650;!</span>
  </span>
  <span class="ai-status__text">
    
    
    <span class="fallback fallback--idle">Idle</span>
    <span class="fallback fallback--thinking">Thinking&#8230;</span>
    <span class="fallback fallback--responding">Responding&#8230;</span>
    <span class="fallback fallback--error">Something went wrong</span>
    
  </span>
</div>
<style>
.ai-status { display: inline-flex; align-items: center; gap: 8px; font: 13px/1.4 system-ui, sans-serif; padding: 6px 12px; border-radius: 999px; background: #24143008; color: #241430; }
.ai-status__icon { display: inline-flex; font-size: 13px; font-weight: 700; color: var(--accent); }
.ai-status__icon .glyph { display: none; }
.ai-status--idle .glyph--idle, .ai-status--thinking .glyph--thinking, .ai-status--responding .glyph--responding, .ai-status--error .glyph--error { display: inline; }
.ai-status__text .fallback { display: none; }
.ai-status--idle .fallback--idle, .ai-status--thinking .fallback--thinking, .ai-status--responding .fallback--responding, .ai-status--error .fallback--error { display: inline; }
.ai-status--error { color: #8A2F2F; }
.ai-status--error .ai-status__icon { color: #8A2F2F; }
@media (prefers-reduced-motion: no-preference) {
.ai-status--pulse .ai-status__icon { animation: ai-status-pulse .22s ease-in-out infinite; }
}
@keyframes ai-status-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
</style>

tailwind

<div class="ai-status-tw ai-status-tw--thinking ai-status-tw--pulse inline-flex items-center gap-2 font-sans text-[13px] px-3 py-1.5 rounded-full bg-[#24143008] text-[#241430]" role="status" aria-live="polite" style="--accent:#D9C8F0;">
  <span class="ai-status-tw__icon inline-flex text-[13px] font-bold" style="color:var(--accent)" aria-hidden="true">
    <span class="glyph glyph--idle">&#9679;</span>
    <span class="glyph glyph--thinking">&#8230;</span>
    <span class="glyph glyph--responding">&#9646;&#9646;&#9646;</span>
    <span class="glyph glyph--error">&#9650;!</span>
  </span>
  <span>
    
    
    <span class="fallback fallback--idle">Idle</span>
    <span class="fallback fallback--thinking">Thinking&#8230;</span>
    <span class="fallback fallback--responding">Responding&#8230;</span>
    <span class="fallback fallback--error">Something went wrong</span>
    
  </span>
</div>
<style>
.ai-status-tw__icon .glyph { display: none; }
.ai-status-tw--idle .glyph--idle, .ai-status-tw--thinking .glyph--thinking, .ai-status-tw--responding .glyph--responding, .ai-status-tw--error .glyph--error { display: inline; }
.ai-status-tw span .fallback { display: none; }
.ai-status-tw--idle .fallback--idle, .ai-status-tw--thinking .fallback--thinking, .ai-status-tw--responding .fallback--responding, .ai-status-tw--error .fallback--error { display: inline; }
.ai-status-tw--error { color: #8A2F2F; }
.ai-status-tw--error .ai-status-tw__icon { color: #8A2F2F; }
@media (prefers-reduced-motion: no-preference) {
.ai-status-tw--pulse .ai-status-tw__icon { animation: ai-status-tw-pulse .22s ease-in-out infinite; }
}
@keyframes ai-status-tw-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
</style>

react

export function AiStatus({
  state = "thinking",
  label = "",
  accent = "#D9C8F0",
  pulse = true,
}) {
  const info = {
    idle: { icon: "\u25CF", text: "Idle", color: accent },
    thinking: { icon: "\u2026", text: "Thinking\u2026", color: accent },
    responding: { icon: "\u2588\u2588\u2588", text: "Responding\u2026", color: accent },
    error: { icon: "\u25B2!", text: "Something went wrong", color: "#8A2F2F" },
  }[state] ?? { icon: "\u25CF", text: "Idle", color: accent };
  return (
    <div role="status" aria-live="polite" style={{ display: "inline-flex", alignItems: "center", gap: 8, fontSize: 13,
      padding: "6px 12px", borderRadius: 999, background: "#24143008", color: state === "error" ? "#8A2F2F" : "#241430",
      fontFamily: "system-ui, sans-serif" }}>
      <span aria-hidden="true" className={pulse ? "ais-pulse-icon" : undefined} style={{ fontSize: 13, fontWeight: 700, color: info.color }}>{info.icon}</span>
      <span>{label || info.text}</span>
      <style>{`@media (prefers-reduced-motion: no-preference) { .ais-pulse-icon { animation: ai-status-react-pulse .22s ease-in-out infinite; } } @keyframes ai-status-react-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }`}</style>
    </div>
  );
}