ZaidanHomeDocsComponentsBlocksChartsTypesetCreate

Command Palette

Search for a command to run...

GitHub
New
Sections
  • Introduction
  • Components
  • Blocks
  • Installation
  • Customization
  • Dark Mode
  • Typeset
  • Zaidan Skills
  • FAQ
  • Roadmap
  • Changelog
Installation
  • Astro
  • Manual
  • Solid Start
  • TanStack Router
  • TanStack Start
  • Vite
Blocks
  • Data Grid
  • Event Calendar
  • Filters
  • Gantt
  • Image Crop
  • Kanban
  • Message Scroller
  • Questionnaire
  • Sortable
Components
  • Accordion
  • Alert
  • Alert Dialog
  • Aspect Ratio
  • Attachment
  • Avatar
  • Badge
  • Breadcrumb
  • Bubble
  • Button
  • Button Group
  • Calendar
  • Card
  • Carousel
  • Chart
  • Checkbox
  • Collapsible
  • Combobox
  • Command
  • Context Menu
  • Dialog
  • Drawer
  • Dropdown Menu
  • Empty
  • Field
  • Hover Card
  • Input
  • Input Group
  • Input OTP
  • Item
  • Kbd
  • Label
  • Marker
  • Menubar
  • Message
  • Native Select
  • Navigation Menu
  • Pagination
  • Popover
  • Progress
  • Radio Group
  • Resizable
  • Scroll Area
  • Select
  • Separator
  • Sheet
  • Sidebar
  • Skeleton
  • Slider
  • Spinner
  • Switch
  • Table
  • Tabs
  • Textarea
  • Toast
  • Toggle
  • Toggle Group
  • Tooltip

Marker

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

Default
A default marker
Marker with an icon
Compacting conversation
Variants
Switched to release-candidate
Worked for 42s
Conversation compacted
Link
View file activity
1
import { Check, Clock3, FileText, GitBranch } from "lucide-solid";
2
3
import { Example, ExampleWrapper } from "@/components/example";
4
import { Marker, MarkerContent, MarkerIcon } from "~/components/ui/marker";
5
import { Spinner } from "~/components/ui/spinner";
6
7
export default function MarkerDemo() {
8
return (
9
<ExampleWrapper>
10
<Example title="Default">
11
<div class="flex w-full flex-col gap-4">
12
<Marker>
13
<MarkerContent>A default marker</MarkerContent>
14
</Marker>
15
<Marker>
16
<MarkerIcon>
17
<FileText />
18
</MarkerIcon>
19
<MarkerContent>Marker with an icon</MarkerContent>
20
</Marker>
21
<Marker role="status">
22
<MarkerIcon>
23
<Spinner />
24
</MarkerIcon>
25
<MarkerContent>Compacting conversation</MarkerContent>
26
</Marker>
27
</div>
28
</Example>
29
<Example title="Variants">
30
<div class="flex w-full flex-col gap-4">
31
<Marker variant="border">
32
<MarkerIcon>
33
<GitBranch />
34
</MarkerIcon>
35
<MarkerContent>Switched to release-candidate</MarkerContent>
36
</Marker>
37
<Marker variant="separator">
38
<MarkerContent>Worked for 42s</MarkerContent>
39
</Marker>
40
<Marker variant="separator">
41
<MarkerIcon>
42
<Check />
43
</MarkerIcon>
44
<MarkerContent>Conversation compacted</MarkerContent>
45
</Marker>
46
</div>
47
</Example>
48
<Example title="Link">
49
<Marker as="a" href="#marker-demo">
50
<MarkerIcon>
51
<Clock3 />
52
</MarkerIcon>
53
<MarkerContent>View file activity</MarkerContent>
54
</Marker>
55
</Example>
56
</ExampleWrapper>
57
);
58
}

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

Installation

pnpm dlx shadcn@latest add @zaidan/marker
npx shadcn@latest add @zaidan/marker
yarn dlx shadcn@latest add @zaidan/marker
bunx --bun shadcn@latest add @zaidan/marker

Usage

1
import { Marker, MarkerContent, MarkerIcon } from "~/components/ui/marker";
1
<Marker>
2
<MarkerIcon>
3
<CheckIcon />
4
</MarkerIcon>
5
<MarkerContent>Explored 4 files</MarkerContent>
6
</Marker>

Composition

Use the following composition to build a marker:

Marker
├── MarkerIcon
└── MarkerContent

Features

  • Inline marker, bordered row, and labeled separator variants.
  • Decorative icon slot that is hidden from assistive tech.
  • Polymorphic root via as for link and button markers.
  • Pairs with the shimmer utility class for streaming status text.
  • Customizable styling through the class prop on every part.

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.
1
import { Marker, MarkerContent } from "~/components/ui/marker";
2
3
export default function MarkerVariants() {
4
return (
5
<div class="flex w-full max-w-sm flex-col gap-8 py-12">
6
<Marker>
7
<MarkerContent>A default marker for inline notes.</MarkerContent>
8
</Marker>
9
<Marker variant="separator">
10
<MarkerContent>A separator marker</MarkerContent>
11
</Marker>
12
<Marker variant="border">
13
<MarkerContent>A border marker for row boundaries.</MarkerContent>
14
</Marker>
15
</div>
16
);
17
}
VariantDescription
defaultAn inline marker for status, notes, and actions.
borderA default marker with a bottom border under the row.
separatorA centered label with divider lines on each side.

Status

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

Compacting conversation
Running tests
1
import { Marker, MarkerContent, MarkerIcon } from "~/components/ui/marker";
2
import { Spinner } from "~/components/ui/spinner";
3
4
export default function MarkerStatus() {
5
return (
6
<div class="flex w-full max-w-sm flex-col gap-8 py-12">
7
<Marker role="status">
8
<MarkerIcon>
9
<Spinner />
10
</MarkerIcon>
11
<MarkerContent>Compacting conversation</MarkerContent>
12
</Marker>
13
<Marker variant="separator" role="status">
14
<MarkerIcon>
15
<Spinner />
16
</MarkerIcon>
17
<MarkerContent>Running tests</MarkerContent>
18
</Marker>
19
</div>
20
);
21
}

Shimmer

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

Thinking...
Reading 4 files
1
import { Marker, MarkerContent } from "~/components/ui/marker";
2
3
export default function MarkerShimmer() {
4
return (
5
<div class="flex w-full max-w-sm flex-col gap-8 py-12">
6
<Marker role="status">
7
<MarkerContent class="shimmer">Thinking...</MarkerContent>
8
</Marker>
9
<Marker variant="separator" role="status">
10
<MarkerContent class="shimmer">Reading 4 files</MarkerContent>
11
</Marker>
12
</div>
13
);
14
}

Separator

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

Today
Worked for 42s
Conversation compacted
1
import { Marker, MarkerContent } from "~/components/ui/marker";
2
3
export default function MarkerSeparator() {
4
return (
5
<div class="flex w-full max-w-sm flex-col gap-8 py-12">
6
<Marker variant="separator">
7
<MarkerContent>Today</MarkerContent>
8
</Marker>
9
<Marker variant="separator">
10
<MarkerContent>Worked for 42s</MarkerContent>
11
</Marker>
12
<Marker variant="separator">
13
<MarkerContent>Conversation compacted</MarkerContent>
14
</Marker>
15
</div>
16
);
17
}

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
1
import { FileText, GitBranch, Search } from "lucide-solid";
2
3
import { Marker, MarkerContent, MarkerIcon } from "~/components/ui/marker";
4
5
export default function MarkerBorder() {
6
return (
7
<div class="flex w-full max-w-sm flex-col gap-3 py-12">
8
<Marker variant="border">
9
<MarkerIcon>
10
<GitBranch />
11
</MarkerIcon>
12
<MarkerContent>Switched to release-candidate</MarkerContent>
13
</Marker>
14
<Marker variant="border">
15
<MarkerIcon>
16
<Search />
17
</MarkerIcon>
18
<MarkerContent>Reviewed 8 related files</MarkerContent>
19
</Marker>
20
<Marker variant="border">
21
<MarkerIcon>
22
<FileText />
23
</MarkerIcon>
24
<MarkerContent>Opened implementation notes</MarkerContent>
25
</Marker>
26
</div>
27
);
28
}

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
1
import { BookOpenCheck, GitBranch, Search } from "lucide-solid";
2
3
import { Marker, MarkerContent, MarkerIcon } from "~/components/ui/marker";
4
5
export default function MarkerIconDemo() {
6
return (
7
<div class="flex w-full max-w-sm flex-col gap-12 py-12">
8
<Marker>
9
<MarkerIcon>
10
<GitBranch />
11
</MarkerIcon>
12
<MarkerContent>Switched to a new branch</MarkerContent>
13
</Marker>
14
<Marker variant="separator">
15
<MarkerIcon>
16
<Search />
17
</MarkerIcon>
18
<MarkerContent>Explored 4 files</MarkerContent>
19
</Marker>
20
<Marker class="flex-col">
21
<MarkerIcon>
22
<BookOpenCheck />
23
</MarkerIcon>
24
<MarkerContent>Syncing completed</MarkerContent>
25
</Marker>
26
</div>
27
);
28
}

Links and Buttons

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

View the pull request
1
import { GitBranch, RotateCcw } from "lucide-solid";
2
import { toast } from "solid-sonner";
3
4
import { Marker, MarkerContent, MarkerIcon } from "~/components/ui/marker";
5
import { Toaster } from "~/components/ui/toast";
6
7
export default function MarkerLinkButton() {
8
return (
9
<>
10
<Toaster />
11
<div class="flex w-full max-w-sm flex-col gap-8 py-12">
12
<Marker as="a" href="#links-and-buttons">
13
<MarkerIcon>
14
<GitBranch />
15
</MarkerIcon>
16
<MarkerContent>View the pull request</MarkerContent>
17
</Marker>
18
<Marker
19
as="button"
20
type="button"
21
class="transition-colors hover:text-foreground"
22
onClick={() => toast("You clicked the revert button")}
23
>
24
<MarkerIcon>
25
<RotateCcw />
26
</MarkerIcon>
27
<MarkerContent>Revert this change</MarkerContent>
28
</Marker>
29
</div>
30
</>
31
);
32
}
1
import { Marker, MarkerContent } from "~/components/ui/marker";
2
3
export function MarkerLinkDemo() {
4
return (
5
<Marker as="a" href="#">
6
<MarkerContent>View the pull request</MarkerContent>
7
</Marker>
8
);
9
}

Accessibility

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.

Status and Progress

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.

1
<Marker role="status">
2
<MarkerIcon>
3
<Spinner />
4
</MarkerIcon>
5
<MarkerContent>Compacting conversation</MarkerContent>
6
</Marker>

Labeled Separators

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.

1
<Marker variant="separator">
2
<MarkerContent>Today</MarkerContent>
3
</Marker>

Note: 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.

Bordered Markers

A bordered marker keeps the same semantics as the default marker. The bottom border is decorative, so choose role="status", as, or no role based on the marker's purpose.

1
<Marker variant="border">
2
<MarkerIcon>
3
<FileTextIcon />
4
</MarkerIcon>
5
<MarkerContent>Opened implementation notes</MarkerContent>
6
</Marker>

Decorative Icons

MarkerIcon is decorative and hidden from assistive tech with aria-hidden, so the adjacent MarkerContent carries the meaning. For an icon-only marker, provide an aria-label or visible text so it is not announced as empty.

1
<Marker aria-label="Synced">
2
<MarkerIcon>
3
<CheckIcon />
4
</MarkerIcon>
5
</Marker>

Interactive Markers

When a marker links or triggers an action, render it as a real <button> or <a> with the as prop so it is focusable and exposes the correct role. The accessible name comes from the marker text.

1
<Marker as="a" href="/files">
2
<MarkerIcon>
3
<FileTextIcon />
4
</MarkerIcon>
5
<MarkerContent>Explored 4 files</MarkerContent>
6
</Marker>

API Reference

Marker

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

PropTypeDefaultDescription
variant"default" | "border" | "separator""default"The marker layout.
asValidComponent"div"Render as a different element, such as a link.
classstring-Additional classes to apply to the root element.

MarkerIcon

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

PropTypeDefaultDescription
classstring-Additional classes to apply to the icon slot.

MarkerContent

The marker text content.

PropTypeDefaultDescription
classstring-Additional classes to apply to the content slot.

On This Page

  • Installation
  • Usage
  • Composition
  • Features
  • Variants
  • Status
  • Shimmer
  • Separator
  • Border
  • With Icon
  • Links and Buttons
  • Accessibility
    • Status and Progress
    • Labeled Separators
    • Bordered Markers
    • Decorative Icons
    • Interactive Markers
  • API Reference
    • Marker
    • MarkerIcon
    • MarkerContent
Built by Kevin Abatan. The source code is available on GitHub.