Marker
A transcript divider or inline status marker for chat UIs.
Installation
Included in poetry-ui — available as
poetry_marker
the moment you've installed Poetry,
with no per-component step. To own the source and edit it, copy it into your app:
bin/rails g poetry:add marker
Default
Open Default standalone
Assistant is thinking
<%= poetry_marker(class: "w-full max-w-md") { "Assistant is thinking" } %>
Border
Open Border standalone
Switched to release-candidate
Reviewed 8 related files
Opened implementation notes
<%# Upstream marker-border: an activity run of bordered rows, each with
a decorative icon. %>
<div class="flex w-full max-w-sm flex-col gap-3">
<%= poetry_marker(variant: :border) do |marker| %>
<% marker.with_icon(name: :"git-branch") %>
Switched to release-candidate
<% end %>
<%= poetry_marker(variant: :border) do |marker| %>
<% marker.with_icon(name: :search) %>
Reviewed 8 related files
<% end %>
<%= poetry_marker(variant: :border) do |marker| %>
<% marker.with_icon(name: :"file-text") %>
Opened implementation notes
<% end %>
</div>
Links and buttons
Open Links and buttons standalone
<%# Upstream marker-link-button: a marker can BE a link or a button -
tag: renders the root as <a>/<button>, the label stays the marker
content (the dictionary underlines link markers on hover). %>
<div class="flex w-full max-w-sm flex-col gap-8">
<%= poetry_marker(tag: :a, href: "#links-and-buttons") do |marker| %>
<% marker.with_icon(name: :"git-branch") %>
View the pull request
<% end %>
<%= poetry_marker(tag: :button, type: :button, class: "cursor-pointer transition-colors hover:text-foreground") do |marker| %>
<% marker.with_icon(name: :"rotate-ccw") %>
Revert this change
<% end %>
</div>
Separator
Open Separator standalone
Today
Worked for 42s
Conversation compacted
<%# Upstream marker-separator: the transcript-divider run - date break,
duration note, compaction notice. %>
<div class="flex w-full max-w-sm flex-col gap-8">
<%= poetry_marker(variant: :separator) { "Today" } %>
<%= poetry_marker(variant: :separator) { "Worked for 42s" } %>
<%= poetry_marker(variant: :separator) { "Conversation compacted" } %>
</div>
Shimmer
Open Shimmer standalone
Composing a reply…
<%= poetry_marker(announce: :status, class: "w-full max-w-md") do %>
<span class="shimmer">Composing a reply…</span>
<% end %>
Status
Open Status standalone
Compacting conversation
Running tests
<%# Upstream marker-status: in-flight lines with a Spinner riding the
block icon slot. The aria-hidden icon cell hides the Spinner's own
status role - the marker root (announce: :status) does the
announcing. %>
<div class="flex w-full max-w-sm flex-col gap-8">
<%= poetry_marker(announce: :status) do |marker| %>
<% marker.with_icon { poetry_spinner } %>
Compacting conversation
<% end %>
<%= poetry_marker(variant: :separator, announce: :status) do |marker| %>
<% marker.with_icon { poetry_spinner } %>
Running tests
<% end %>
</div>
Variants
Open Variants standalone
A default marker for inline notes.
A separator marker
A border marker for row boundaries.
<%# The three variants side by side - default (inline note), separator
(flanking rules), and border (row boundary). %>
<div class="flex w-full max-w-sm flex-col gap-8">
<%= poetry_marker { "A default marker for inline notes." } %>
<%= poetry_marker(variant: :separator) { "A separator marker" } %>
<%= poetry_marker(variant: :border) { "A border marker for row boundaries." } %>
</div>
With icon
Open With icon standalone
Generating a summary
<%= poetry_marker(class: "w-full max-w-md") do |marker| %>
<% marker.with_icon(name: :sparkles) %>
Generating a summary
<% end %>
API
Poetry::Ui::Marker::Component — options are
constructor keywords (the poetry_* helper forwards them);
slots are composed inside the block. Generated from the gem's source documentation.
| Option | Type | Details | Description |
|---|---|---|---|
| variant: | Symbol | one of: default, separator, border; defaults to :default |
The divider treatment - :separator for date/section breaks, :border for a full-width rule under pinned headers. |
| announce: | Symbol | one of: none, status; defaults to :none |
Makes the marker a live status region (role=status) for the one in-flight marker; static dividers never announce. |
| tag: | Symbol | defaults to :div |
The root element's tag. |
Slots
| Writer | Description |
|---|---|
| with_icon | Optional leading visual: name: renders an icon glyph; a block carries other media (a Spinner mid-run). Either way it sits in an aria-hidden cell and stays decorative - the marker root does the announcing. |
Styling
Every part carries a stable data-slot attribute — target
[data-slot=…] from your own CSS to restyle it. State rides
data attributes on the parts below. This contract is verified against rendered DOM in CI.
| Part | Description |
|---|---|
| [data-slot=marker] | The divider/status root - the label is real announced content (role=status when announce: :status; never role=separator) |
| [data-slot=marker-icon] | Decorative icon wrapper (aria-hidden always) |
| [data-slot=marker-content] | The label span - the marker text itself |
State attributes
| Part | Attribute | Condition | Values |
|---|---|---|---|
| marker | data-variant | always - the resolved variant | default · separator · border |