Command Palette

Search for a command to run...

Github

Marker

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

Switched to a new branch
Thinking...
Conversation compacted
Explored 4 files
import { GitBranchIcon, SearchIcon } from "lucide-react";

import {
	Marker,
	MarkerContent,
	MarkerIcon,
} from "@/components/ui/marker";
import { Spinner } from "@/components/ui/spinner";

export function MarkerDemo() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-8 py-12">
			<Marker>
				<MarkerIcon>
					<GitBranchIcon />
				</MarkerIcon>
				<MarkerContent>Switched to a new branch</MarkerContent>
			</Marker>
			<Marker role="status">
				<MarkerIcon>
					<Spinner size="sm" />
				</MarkerIcon>
				<MarkerContent className="shimmer">Thinking...</MarkerContent>
			</Marker>
			<Marker variant="separator">
				<MarkerContent>Conversation compacted</MarkerContent>
			</Marker>
			<Marker>
				<MarkerIcon>
					<SearchIcon />
				</MarkerIcon>
				<MarkerContent>Explored 4 files</MarkerContent>
			</Marker>
		</div>
	);
}

Installation

pnpm dlx shadcn@latest add https://herocn.dev/r/marker.json

Usage

import { Marker, MarkerContent, MarkerIcon } from "@/components/ui/marker"
<Marker>
  <MarkerIcon>
    <CheckIcon />
  </MarkerIcon>
  <MarkerContent>Explored 4 files</MarkerContent>
</Marker>

Composition

Use the following composition to build a marker:

Marker
├── MarkerIcon
└── MarkerContent

Examples

Variants

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

A default marker for inline notes.
A separator marker
A border marker for row boundaries.
import { Marker, MarkerContent } from "@/components/ui/marker";

export function MarkerVariants() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-8 py-12">
			<Marker>
				<MarkerContent>A default marker for inline notes.</MarkerContent>
			</Marker>
			<Marker variant="separator">
				<MarkerContent>A separator marker</MarkerContent>
			</Marker>
			<Marker variant="border">
				<MarkerContent>A border marker for row boundaries.</MarkerContent>
			</Marker>
		</div>
	);
}

Status

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

Compacting conversation
Running tests
import {
	Marker,
	MarkerContent,
	MarkerIcon,
} from "@/components/ui/marker";
import { Spinner } from "@/components/ui/spinner";

export function MarkerStatus() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-8 py-12">
			<Marker role="status">
				<MarkerIcon>
					<Spinner size="sm" />
				</MarkerIcon>
				<MarkerContent>Compacting conversation</MarkerContent>
			</Marker>
			<Marker variant="separator" role="status">
				<MarkerIcon>
					<Spinner size="sm" />
				</MarkerIcon>
				<MarkerContent>Running tests</MarkerContent>
			</Marker>
		</div>
	);
}

Shimmer

Add the shimmer utility class to MarkerContent for an animated streaming-text effect.

Thinking...
Reading 4 files
import { Marker, MarkerContent } from "@/components/ui/marker";

export function MarkerShimmer() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-8 py-12">
			<Marker role="status">
				<MarkerContent className="shimmer">Thinking...</MarkerContent>
			</Marker>
			<Marker variant="separator" role="status">
				<MarkerContent className="shimmer">Reading 4 files</MarkerContent>
			</Marker>
		</div>
	);
}

Separator

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

Today
Worked for 42s
Conversation compacted
import { Marker, MarkerContent } from "@/components/ui/marker";

export function MarkerSeparator() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-8 py-12">
			<Marker variant="separator">
				<MarkerContent>Today</MarkerContent>
			</Marker>
			<Marker variant="separator">
				<MarkerContent>Worked for 42s</MarkerContent>
			</Marker>
			<Marker variant="separator">
				<MarkerContent>Conversation compacted</MarkerContent>
			</Marker>
		</div>
	);
}

Border

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

Switched to release-candidate
Reviewed 8 related files
Opened implementation notes
import { FileTextIcon, GitBranchIcon, SearchIcon } from "lucide-react";

import {
	Marker,
	MarkerContent,
	MarkerIcon,
} from "@/components/ui/marker";

export function MarkerBorder() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-3 py-12">
			<Marker variant="border">
				<MarkerIcon>
					<GitBranchIcon />
				</MarkerIcon>
				<MarkerContent>Switched to release-candidate</MarkerContent>
			</Marker>
			<Marker variant="border">
				<MarkerIcon>
					<SearchIcon />
				</MarkerIcon>
				<MarkerContent>Reviewed 8 related files</MarkerContent>
			</Marker>
			<Marker variant="border">
				<MarkerIcon>
					<FileTextIcon />
				</MarkerIcon>
				<MarkerContent>Opened implementation notes</MarkerContent>
			</Marker>
		</div>
	);
}

With Icon

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

Switched to a new branch
Explored 4 files
Syncing completed
import { BookOpenCheck, GitBranchIcon, SearchIcon } from "lucide-react";

import {
	Marker,
	MarkerContent,
	MarkerIcon,
} from "@/components/ui/marker";

export function MarkerIconDemo() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-12 py-12">
			<Marker>
				<MarkerIcon>
					<GitBranchIcon />
				</MarkerIcon>
				<MarkerContent>Switched to a new branch</MarkerContent>
			</Marker>
			<Marker variant="separator">
				<MarkerIcon>
					<SearchIcon />
				</MarkerIcon>
				<MarkerContent>Explored 4 files</MarkerContent>
			</Marker>
			<Marker className="flex-col">
				<MarkerIcon>
					<BookOpenCheck />
				</MarkerIcon>
				<MarkerContent>Syncing completed</MarkerContent>
			</Marker>
		</div>
	);
}

Turn a marker into a link or button with the render prop on Marker.

View the pull request
"use client";

import { GitBranchIcon, RotateCcwIcon } from "lucide-react";
import { toast } from "sonner";

import {
	Marker,
	MarkerContent,
	MarkerIcon,
} from "@/components/ui/marker";

export function MarkerLinkButton() {
	return (
		<div className="flex w-full max-w-sm flex-col gap-8 py-12">
			<Marker render={<a href="#" />}>
				<MarkerIcon>
					<GitBranchIcon />
				</MarkerIcon>
				<MarkerContent>View the pull request</MarkerContent>
			</Marker>
			<Marker
				render={
					<button
						type="button"
						className="transition-colors hover:text-foreground"
						onClick={() => toast("You clicked the revert button")}
					/>
				}
			>
				<MarkerIcon>
					<RotateCcwIcon />
				</MarkerIcon>
				<MarkerContent>Revert this change</MarkerContent>
			</Marker>
		</div>
	);
}
import { Marker, MarkerContent } from "@/components/ui/marker"

export function MarkerLinkDemo() {
  return (
    <Marker render={<a href="#" />}>
      <MarkerContent>View the pull request</MarkerContent>
    </Marker>
  )
}

API Reference

Marker

The root marker element. The file also exports markerVariants for composing the marker styles into custom components.

PropTypeDefault

MarkerIcon

A decorative icon slot. Hidden from assistive tech with aria-hidden.

PropTypeDefault

MarkerContent

The marker text content.

PropTypeDefault