Toggle Sidebar B
AppearanceLight & dark mode D

Marker

Displays an inline status, system note, bordered row, or labeled separator in a conversation.

Marker displays inline conversation markers such as status updates, system notes, bordered rows, and labeled separators. Compose it with Message in a conversation thread.

Dark previewReplay preview
Switched to a new branch
Thinking...
Conversation compacted
Explored 4 files

Variants

Use variant to switch between an inline marker, bordered row, and labeled separator.

  • default: an inline marker for status, notes, and actions.
  • border: a default marker with a bottom border under the row.
  • separator: a centered label with divider lines on each side.
Dark previewReplay preview
A default marker for inline notes.
A separator marker
A border marker for row boundaries.

Status

Set role="status" and include a Spinner for streaming or in-progress markers so updates are announced.

Dark previewReplay preview
Compacting conversation
Running tests

Shimmer

Add the shimmer utility class to MarkerContent for an animated streaming-text effect. The utility ships with the stylesheet; see the Shimmer page for the modifiers.

Dark previewReplay preview
Thinking...
Reading 4 files

Separator

Use the separator variant for labeled dividers, such as dates or section breaks, in a conversation.

Dark previewReplay preview
Today
Worked for 42s
Conversation compacted

Border

Use the border variant for status rows that should keep the default marker alignment while separating the next row.

Dark previewReplay preview
Switched to release-candidate
Reviewed 8 related files
Opened implementation notes

With Icon

Use MarkerIcon to render an icon alongside the content. Use flex-col to stack the icon above the content.

Dark previewReplay preview
Switched to a new branch
Explored 4 files
Syncing completed

Anatomy

Import all parts and piece them together.

vue
<script setup>
import {
  Marker,
  MarkerContent,
  MarkerIcon,
} from "@/components/ui/marker";
</script>

<template>
  <Marker>
    <MarkerIcon />
    <MarkerContent />
  </Marker>
</template>

API Reference

Marker

PropTypeDefaultDescription
variant"default" | "separator" | "border""default"The marker layout. The value is mirrored on the root as data-variant, which the stylesheet reads through group-data-[variant=separator]/marker to center MarkerContent between the two divider rules.
asstring | Component"div"Element or component the root renders as. Forwarded to the reka-ui Primitive.
asChildbooleanfalseRender the single child element as the root instead of wrapping it, so a marker can be a real <a> or <button>. Forwarded to the reka-ui Primitive. Written as as-child in templates.
classstring—Extra classes, merged with cn() on top of markerVariants(). The root is tagged data-slot="marker", and markerVariants (the cva behind those classes) is exported from the same module for composing the marker look into a custom component.
SlotDescription
defaultMarker contents, usually a MarkerIcon followed by a MarkerContent.

MarkerIcon

PropTypeDefaultDescription
classstring—Extra classes, merged with cn(). The slot is tagged data-slot="marker-icon" and aria-hidden="true". It renders a plain span in this port, so it takes no as or as-child prop.
SlotDescription
defaultDecorative icon, hidden from assistive tech.

MarkerContent

PropTypeDefaultDescription
classstring—Extra classes, merged with cn(). The slot is tagged data-slot="marker-content" and its .cn-marker-content styles read the root through group-data-[variant=separator]/marker. Like MarkerIcon it renders a plain span, so it takes no as or as-child prop.
SlotDescription
defaultThe marker text content.

Accessibility

Keyboard shortcuts and ARIA behavior.

Shortcut Description
TabMoves focus to a marker rendered as a link or button. A presentational marker is not focusable.
EnterActivates a marker rendered as a link or button.
SpaceActivates a marker rendered as a button.
  • Marker is presentational by default. The correct semantics depend on how you use it, so choose the role based on intent rather than relying on a single default.
  • For streaming or progress markers such as "Thinking..." or a running tool, set role="status" so assistive tech announces the update as it appears. Marker forwards role to the underlying element.
  • A separator that carries text, such as a date or a section label, needs no role. The divider lines are decorative CSS pseudo-elements, and the text is announced as ordinary content.
  • Do not add role="separator" to a labeled divider. A separator takes its accessible name from aria-label, not from its text, and its contents are treated as presentational, so the visible label would not be announced. Reserve role="separator" for a divider with no meaningful text.
  • A bordered marker keeps the same semantics as the default marker. The bottom border is decorative, so choose role="status", as-child, or no role based on the marker's purpose.
  • MarkerIcon is decorative and hidden from assistive tech with aria-hidden, so the adjacent MarkerContent carries the meaning. For an icon-only marker, give the root an aria-label or visible text so it is not announced as empty.
  • When a marker links or triggers an action, render it as a real button or anchor with as-child so it is focusable and exposes the correct role. The accessible name comes from the marker text.