Stateless function components used across the dashboard.
Stateful pieces (filter bars, paginated tables, palettes) live as
Phoenix.LiveComponent modules elsewhere. Anything visual, parameterized,
and stateless lives here so it can be composed without :id ceremony.
Summary
Functions
A small label tag.
A button with kind variants.
A surface container with optional header.
Renders code in monospace. Use for IDs, JSON snippets, durations.
A small clipboard button. Copies text to the clipboard via the global
delegated listener (assets/src/hooks/copy.ts, wired in main.ts) and
flashes a check for ~1.4 s. No phx-hook/id needed — it's plain markup
carrying data-copy. Drop it beside any copy-worthy value (JSON box, id
chip, config value).
Centered empty-state placeholder.
Centered error placeholder with semantic destructive styling and an
optional retry action. Distinct from <.empty_state> so operators
immediately see the difference between "nothing here yet" and
"something is broken."
One key/value detail row, rendered as a <dt>/<dd> grid cell pair.
Grid container for <.field> rows: a two-column auto / 1fr <dl> with a
tight, even rhythm and baseline-aligned cells. The single source of truth
for "aligned key/value metadata table".
Page / section heading.
Renders an inline SVG icon. The available set is curated; add new icons by
extending the ~H clause below with a new pattern match.
A square button containing only an icon. For toolbar-style controls (theme toggle, pagination chevrons, sheet-close, table actions).
Renders a decoded term (map / list / scalar from JSONB) as pretty-printed,
syntax-highlighted JSON. Keys, strings, numbers, booleans and null are
colored via design tokens. Reuse anywhere JSON is shown — logs, I/O, the
step inspector — instead of a plain <pre> dump.
Renders a keyboard shortcut hint.
A small uppercase, letter-spaced field label — the standard treatment for
key names, section headers, and metadata keys so a label reads as a label,
not a value. Centralizes the font-mono uppercase tracking-… idiom used
across the inspector, logs, and detail panels.
Renders an absolute timestamp in the viewer's local timezone.
Renders a relative time like "2m ago" (past) or "in 2h" (future), with a hover tooltip showing the absolute moment in the viewer's local timezone.
Animated placeholder. Use to indicate that a section is loading without collapsing layout. Composable: stack multiple skeletons of varying widths to mimic the shape of the eventual content.
A status pill for workflow / step states. Uses semantic colors and an LED pulse for active states.
JS.dispatch/2 shim convenience used by the theme toggle.
Functions
A small label tag.
Examples
<.badge>default</.badge>
<.badge kind="success">running</.badge>Attributes
kind(:string) - Defaults to"default". Must be one of"default","primary","success","warning","destructive","info", or"muted".class(:string) - Defaults tonil.
Slots
inner_block(required)
A button with kind variants.
Examples
<.button>Default</.button>
<.button kind="primary" type="submit">Save</.button>
<.button kind="ghost" phx-click="cancel">Cancel</.button>Attributes
kind(:string) - Defaults to"secondary". Must be one of"primary","secondary","ghost","destructive", or"link".size(:string) - Defaults to"md". Must be one of"sm","md", or"lg".type(:string) - Defaults to"button".class(:string) - Defaults tonil.- Global attributes are accepted. Supports all globals plus:
["disabled", "form", "name", "value", "phx-click", "phx-target", "phx-value-id", "href", "patch", "navigate"].
Slots
inner_block(required)
A surface container with optional header.
Examples
<.card>
Content
</.card>
<.card>
<:title>Section</:title>
<:action><.button kind="ghost">View all</.button></:action>
Content
</.card>Attributes
class(:string) - Defaults tonil.padding(:string) - Defaults to"md". Must be one of"none","sm","md", or"lg".- Global attributes are accepted.
Slots
titleactioninner_block(required)
Renders code in monospace. Use for IDs, JSON snippets, durations.
Examples
<.code>{exec.id}</.code>
<.code class="text-info">{job.queue}</.code>Attributes
class(:string) - Defaults tonil.copy(:string) - Defaults tonil.
Slots
inner_block(required)
A small clipboard button. Copies text to the clipboard via the global
delegated listener (assets/src/hooks/copy.ts, wired in main.ts) and
flashes a check for ~1.4 s. No phx-hook/id needed — it's plain markup
carrying data-copy. Drop it beside any copy-worthy value (JSON box, id
chip, config value).
<.copy_button text={@workflow.id} label="Copy execution id" />Attributes
text(:string) (required)label(:string) - Defaults to"Copy".class(:any) - Defaults tonil.- Global attributes are accepted.
Centered empty-state placeholder.
Examples
<.empty_state title="No workflows yet" />
<.empty_state title="No results" description="Try adjusting filters." />Attributes
title(:string) (required)description(:string) - Defaults tonil.icon(:string) - Defaults tonil.class(:string) - Defaults tonil.
Slots
action
Centered error placeholder with semantic destructive styling and an
optional retry action. Distinct from <.empty_state> so operators
immediately see the difference between "nothing here yet" and
"something is broken."
Examples
<.error_state title="Failed to load workflows" />
<.error_state title="..." description="..." reason="DBConnection timeout">
<:action><.button kind="ghost" phx-click="retry">Retry</.button></:action>
</.error_state>Attributes
title(:string) (required)description(:string) - Defaults tonil.reason(:string) - Defaults tonil.class(:string) - Defaults tonil.
Slots
action
One key/value detail row, rendered as a <dt>/<dd> grid cell pair.
Place several inside <.field_list> (or any display: grid <dl> with two
columns + items-baseline). The label column auto-sizes to the widest key,
so labels hug their values and every value shares one left edge — no ragged
fixed-width gutter.
Examples
<.field_list>
<.field key="level">info</.field>
<.field key="source">logger</.field>
</.field_list>Attributes
key(:string) (required)class(:any) - Defaults tonil.
Slots
inner_block(required)
Grid container for <.field> rows: a two-column auto / 1fr <dl> with a
tight, even rhythm and baseline-aligned cells. The single source of truth
for "aligned key/value metadata table".
Examples
<.field_list>
<.field key="level">info</.field>
<.field key="time">{ts}</.field>
</.field_list>Attributes
class(:any) - Defaults tonil.
Slots
inner_block(required)
Page / section heading.
Examples
<.heading level={1}>Workflows</.heading>
<.heading level={2} subtitle="Past 24 hours">Activity</.heading>Attributes
level(:integer) - Defaults to1. Must be one of1,2, or3.subtitle(:string) - Defaults tonil.class(:string) - Defaults tonil.
Slots
inner_block(required)
Renders an inline SVG icon. The available set is curated; add new icons by
extending the ~H clause below with a new pattern match.
Examples
<.icon name="check" />
<.icon name="x-mark" class="size-5" />Attributes
name(:string) (required)class(:string) - Defaults to"size-4".- Global attributes are accepted.
A square button containing only an icon. For toolbar-style controls (theme toggle, pagination chevrons, sheet-close, table actions).
Variants: default (bordered card surface) | ghost (no border, hover |
bg only). Sizes: sm (28h) | md (32h). |
See DESIGN.md §5 (component primitives) and §8 (density).
Examples
<.icon_button icon="x-mark" aria-label="Close" phx-click="close" />
<.icon_button kind="ghost" size="sm" icon="chevron-right" aria-label="Next" />Attributes
icon(:string) (required)kind(:string) - Defaults to"default". Must be one of"default", or"ghost".size(:string) - Defaults to"md". Must be one of"sm", or"md".type(:string) - Defaults to"button".class(:string) - Defaults tonil.- Global attributes are accepted. Supports all globals plus:
["disabled", "form", "name", "value", "phx-click", "phx-target", "phx-value-id", "aria-label"].
Renders a decoded term (map / list / scalar from JSONB) as pretty-printed,
syntax-highlighted JSON. Keys, strings, numbers, booleans and null are
colored via design tokens. Reuse anywhere JSON is shown — logs, I/O, the
step inspector — instead of a plain <pre> dump.
<.json value={@step.input} />Pass raw: false-style scalars freely; non-JSON terms fall back to
inspect/1.
Attributes
value(:any) (required)class(:string) - Defaults tonil.bare(:boolean) - Defaults tofalse.
Renders a keyboard shortcut hint.
Examples
<.kbd>⌘K</.kbd>
<.kbd>Esc</.kbd>Attributes
class(:string) - Defaults tonil.
Slots
inner_block(required)
A small uppercase, letter-spaced field label — the standard treatment for
key names, section headers, and metadata keys so a label reads as a label,
not a value. Centralizes the font-mono uppercase tracking-… idiom used
across the inspector, logs, and detail panels.
Examples
<.label>level</.label>
<.label class="text-destructive">error</.label>Attributes
class(:any) - Defaults tonil.- Global attributes are accepted.
Slots
inner_block(required)
Renders an absolute timestamp in the viewer's local timezone.
The server only knows UTC, so a raw ISO string is ambiguous to read. This
emits a <time> carrying the UTC ISO (plus a UTC-formatted fallback as its
text, so it's legible without JS); the client localizes it to the browser's
timezone — see assets/src/hooks/local_time.ts. Use this for any absolute
time the user reads; use relative_time for "2m ago" durations.
format is "time" (time of day), "datetime" (date + time), or "date".
Examples
<.local_time at={step.completed_at} format="time" />
<.local_time at={log["timestamp"]} format="datetime" class="text-muted-foreground" />Attributes
at(:any) (required)format(:string) - Defaults to"datetime". Must be one of"time","datetime", or"date".class(:any) - Defaults tonil.
Renders a relative time like "2m ago" (past) or "in 2h" (future), with a hover tooltip showing the absolute moment in the viewer's local timezone.
Emits a <time data-ts data-rel>; the client localizes only the tooltip and
leaves the relative text alone (assets/src/hooks/local_time.ts). The
pre-JS title is a UTC fallback so it's still legible. Use this for "ago" /
"in" durations; use local_time when the user needs the exact moment inline.
Examples
<.relative_time at={execution.inserted_at} />
<.relative_time at={schedule.next_run_at} />Attributes
at(:any) (required)class(:string) - Defaults tonil.
Animated placeholder. Use to indicate that a section is loading without collapsing layout. Composable: stack multiple skeletons of varying widths to mimic the shape of the eventual content.
Examples
<.skeleton class="h-4 w-32" />
<.skeleton class="h-8 w-full" />
<.skeleton variant="circle" class="size-8" />Attributes
class(:string) - Defaults to"h-4 w-full".variant(:string) - Defaults to"default". Must be one of"default","circle", or"pill".- Global attributes are accepted.
A status pill for workflow / step states. Uses semantic colors and an LED pulse for active states.
Examples
<.status_pill status={:running} />
<.status_pill status="completed" />Attributes
status(:any) (required)class(:string) - Defaults tonil.
JS.dispatch/2 shim convenience used by the theme toggle.