Think

A folding block that shows a model's reasoning above its answer, with a spinner while it is still thinking.

Accessibility

What Think does for you, and what it leaves to the page around it.

What Think renders

Plain <div> elements with no roles: a header row and the reasoning under it. A screen reader reads the title and then the reasoning, in document order, like any other text.
  • The default icon and the spinner come from the icon pack and are hidden from screen readers. The title has to carry the state in words.
  • The folding arrow is announced as an image named “right”. Make the title's words carry the meaning, so the stray word does not matter.
  • aria-* and data-* props land on the root. Give the block an aria-label only together with a role like group, since a label on a plain <div> is not read.

The header is mouse only

The header that folds the block is a <div> with a click handler. It cannot be reached with Tab, Enter and Space do nothing, and it does not say whether the block is open.
  • Put a <button type="button"> in title. Its click reaches the header, so Enter and Space fold the block, and the button is in the tab order.
  • Control the state with expanded and onExpand, and set aria-expanded on that button from it.
  • With the default destroyOnHidden, folded reasoning is removed from the page, so a screen reader cannot find it until the block is unfolded.

Announcing progress

Think is not a live region. When loading ends and the title changes to “Thought for 4 seconds”, a screen reader says nothing.
  • Announce the change yourself, from one polite live region for the whole conversation, like a visually hidden <div role="status"> you write “Answer ready” into.
  • Do not make the reasoning itself a live region. Streamed text read aloud token by token is noise, and it talks over the answer.

Contrast

The header uses the secondary text color and the reasoning uses the description color, which is lighter. That keeps the reasoning visibly apart from the answer, and it is close to the minimum contrast for body text.
  • While blink is on, the title is drawn in the description color with a moving highlight, so its contrast is lower still. Keep it on only while the model is working.
  • Check both colors with a custom theme, in light and dark mode. The Tokens tab lists the ones this component reads.

Motion

Three things move: the spinner while loading is on, the title's shimmer while blink is on, and the fold, which animates height and opacity over motionDurationMid.
  • The shimmer loops for as long as blink is on, and does not stop for a reader who has asked for reduced motion. Turn blink off for them, for example from a prefers-reduced-motion media query in your code.
  • motion: false in your token file's seed stops the fold animation, but not the spinner or the shimmer. Those two stop only when you turn loading and blink off.