DurableDashboard.Components.Core (DurableDashboard v0.1.0-rc)

Copy Markdown View Source

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

badge(assigns)

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 to nil.

Slots

  • inner_block (required)

button(assigns)

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 to nil.
  • 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)

card(assigns)

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 to nil.
  • padding (:string) - Defaults to "md". Must be one of "none", "sm", "md", or "lg".
  • Global attributes are accepted.

Slots

  • title
  • action
  • inner_block (required)

code(assigns)

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 to nil.
  • copy (:string) - Defaults to nil.

Slots

  • inner_block (required)

copy_button(assigns)

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 to nil.
  • Global attributes are accepted.

empty_state(assigns)

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 to nil.
  • icon (:string) - Defaults to nil.
  • class (:string) - Defaults to nil.

Slots

  • action

error_state(assigns)

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 to nil.
  • reason (:string) - Defaults to nil.
  • class (:string) - Defaults to nil.

Slots

  • action

field(assigns)

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 to nil.

Slots

  • inner_block (required)

field_list(assigns)

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 to nil.

Slots

  • inner_block (required)

heading(assigns)

Page / section heading.

Examples

<.heading level={1}>Workflows</.heading>
<.heading level={2} subtitle="Past 24 hours">Activity</.heading>

Attributes

  • level (:integer) - Defaults to 1. Must be one of 1, 2, or 3.
  • subtitle (:string) - Defaults to nil.
  • class (:string) - Defaults to nil.

Slots

  • inner_block (required)

icon(assigns)

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.

icon_button(assigns)

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 to nil.
  • Global attributes are accepted. Supports all globals plus: ["disabled", "form", "name", "value", "phx-click", "phx-target", "phx-value-id", "aria-label"].

json(assigns)

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 to nil.
  • bare (:boolean) - Defaults to false.

kbd(assigns)

Renders a keyboard shortcut hint.

Examples

<.kbd>K</.kbd>
<.kbd>Esc</.kbd>

Attributes

  • class (:string) - Defaults to nil.

Slots

  • inner_block (required)

label(assigns)

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 to nil.
  • Global attributes are accepted.

Slots

  • inner_block (required)

local_time(assigns)

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 to nil.

relative_time(assigns)

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 to nil.

skeleton(assigns)

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.

status_pill(assigns)

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 to nil.

toggle_theme()

JS.dispatch/2 shim convenience used by the theme toggle.