Skip to content

Commit a1b2590

Browse files
committed
feat(dashboard): pulse brand mark, live ⌘K palette, topbar toolbar, wider inspector
Sidebar - Replace the tinted "monitor tile + dot" brand with a pulse mark: a muted oscilloscope baseline + one indigo beat with a led-dot blip at its apex (the worker heartbeat made literal). Drops the branded tint so indigo stays earned by the live signal; rebalances the wordmark (lowercase mono "console"). Command palette (⌘K) - Wire the palette into Layouts.app (it was built but never mounted, so ⌘K and the "Jump to…" button did nothing). Thread `durable` through all 7 LiveViews so it can query. - Rewrite it to search the console's nouns, grouped: Go to (pages, incl. the previously-missing Executions), Workflows (live list_workflows), Recent runs (latest executions). Live data is snapshotted on open and filtered in-memory per keystroke. Selected row wears the indigo live rail + a ↵ hint; nav wraps across groups. Topbar - Rework the right cluster into a toolbar: compact ⌘K trigger (width hugs content — no dead gap, single ⌘K chip), hairline divider, then a meta group with the running version, a GitHub link, and the theme toggle (ghost icon controls). Add a `github` brand icon to Core.icon. Step inspector - Widen the shared StepDetail panel cap max-w-4xl -> max-w-5xl. Make the I/O JSON boxes fill their column (w-full) and collapse to a single full-width column when only one side has data, so a cron step's output isn't penned into a half-panel beside an empty "No input" cell. DESIGN.md updated for each (brand mark, live-rail list, palette pattern, topbar toolbar, brand-icon viewBox rule, StepDetail I/O layout). Bundled app.css rebuilt.
1 parent 0170bef commit a1b2590

15 files changed

Lines changed: 468 additions & 145 deletions

File tree

durable_dashboard/DESIGN.md

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,20 @@ its own `Phoenix.LiveComponent` module under
353353
Nav is split into two intent groups under quiet mono eyebrows —
354354
**Observe** (Overview, Workflows, Executions) and **Operate** (Inputs,
355355
Schedules, Settings) — so the destinations read as an IA, not a flat list.
356-
Brand lockup is the **monitor tile + heartbeat** (a pulsing `led-dot` in a
357-
primary-tinted square): the recurring "the engine is alive and durable"
358-
mark, echoed by the `connected` heartbeat in the footer.
359-
- Topbar: 56 h, breadcrumbs left; the command-palette trigger ("Jump to…",
360-
⌘K) + theme toggle right.
356+
Brand lockup is the **pulse mark**: a muted oscilloscope baseline carrying
357+
one indigo beat, with a pulsing `led-dot` riding the beat's apex (the live
358+
blip). It makes the worker heartbeat literal — "the engine is alive and
359+
durable" — and is echoed by the `connected` heartbeat in the footer. No
360+
tinted box: color stays earned by the live signal, never spent on a branded
361+
surface (§1, §6 live rail). The wordmark is `Durable` (text-sm semibold)
362+
over a lowercase mono `console` caption.
363+
- Topbar: 56 h, breadcrumbs left; the command toolbar right. The toolbar is
364+
the **⌘K trigger** (bordered chip, width hugs `search · "Jump to…" · ⌘K`
365+
no dead gap, one `⌘K` chip) then a hairline divider and a **meta group**:
366+
running `version` (mono, from `Application.spec(:durable, :vsn)`), a
367+
**GitHub** link, and the **theme** toggle. The trigger keeps the bordered
368+
surface (primary action); the meta controls are **ghost** (icon-only, no
369+
border) so the trigger reads as the one thing to reach for.
361370
- Main: `max-w-[1400px]` to keep line lengths readable on ultrawide monitors.
362371

363372
#### The live rail (signature)
@@ -367,6 +376,8 @@ console: *now / live / you are here*. It is not generic chrome. It appears as:
367376

368377
- the **active nav rail** — a short `h-4 w-0.5` indigo bar on the left edge
369378
of the current nav item;
379+
- the **selected row** in the ⌘K palette — the same `h-4 w-0.5` bar on the
380+
row you're about to jump to (selection *is* "where you're going next");
370381
- the **running edge** in the workflow graph (`.flow-edge-running`);
371382
- the **"now" line** / in-flight bars in the Timeline.
372383

@@ -388,6 +399,28 @@ Subtitle = relative time, scope context, or counts. Never marketing copy.
388399

389400
`<.tabs>` from `Components.Workflow.Tabs`. No ad-hoc nav strips.
390401

402+
### Command palette (⌘K)
403+
404+
`Components.Command.CommandPalette` — rendered **once** by `Layouts.app`
405+
(needs `base_path` + `durable`), opened by ⌘K or the topbar "Jump to…"
406+
trigger. It is the canonical global jumper (§9) and follows Linear's
407+
command-palette discipline (§1).
408+
409+
- **Searches the console's nouns, grouped** under `<.label>` section
410+
headers: **Go to** (page routes), **Workflows** (live definitions →
411+
their executions), **Recent runs** (latest executions → run detail).
412+
Grouping carries result *type*, so rows don't need per-row type chips.
413+
- **Snapshot on open, filter in memory.** Live data
414+
(`Durable.Query.list_workflows` + recent executions) is fetched once on
415+
`palette:open` and filtered client-of-the-LC-side on each keystroke —
416+
typing never hits the database. Degrades to page routes when `durable`
417+
is `nil`.
418+
- **Selection wears the live rail** (the indigo bar, see signature above)
419+
plus a `` hint that appears only on the selected row. Keyboard nav
420+
wraps across groups via a single flat selection index; hover selects.
421+
- Row meta is restrained: workflow rows show run count + last-status
422+
pill, run rows show short id + status pill. Numbers are `text-numeric`.
423+
391424
### List / table row
392425

393426
- 36–40 h tall, hairline divider between rows.
@@ -430,8 +463,10 @@ event), so a step reads identically wherever it's opened. Composition:
430463

431464
- **Stat strip** — a compact horizontal header (`started · completed ·
432465
duration · attempt`), never a tall field column that leaves dead space.
433-
- **Input / Output**`<.json>` boxes sized `w-fit max-w-full` so a small
434-
payload doesn't render a giant empty box.
466+
- **Input / Output** — a two-column grid where each `<.json>` box fills its
467+
column (`w-full`). The grid drops to **one full-width column when only one
468+
side has data** (e.g. a cron step with no input) so the present payload
469+
spans the panel instead of being penned into a half beside an empty cell.
435470
- **Error** — destructive-tinted `<.json>`, only when the step failed.
436471
- **Logs** — the shared `<LogLine.row>` list; empty falls back to a
437472
"No logs captured" note rather than a blank box.
@@ -468,8 +503,17 @@ For every list LV:
468503
- React side: `lucide-react`, imported per icon.
469504
- Default size: `size-4` (16 px). Larger only inside icon-bg pills, where
470505
`size-5` is OK.
506+
- **Brand logos** (e.g. `github`) live in the `core.ex` set like any icon,
507+
but may keep their native `viewBox` (the GitHub mark is `0 0 24 24`) — the
508+
viewBox sizes the coordinate space, not the render size, so it still scales
509+
to `size-4`. Heroicons-style functional glyphs stay `0 0 20 20`.
471510
- **Forbidden:** inline `<svg>` with hard-coded paths in component files
472-
outside `core.ex` and the curated lucide imports.
511+
outside `core.ex` and the curated lucide imports. **One sanctioned
512+
exception:** the sidebar **pulse mark** (the brand lockup in
513+
`Sidebar.brand/1`) — a one-off identity glyph, not reusable iconography, so
514+
it lives inline rather than in `core.ex`. Its two paths use
515+
`stroke="currentColor"` with `text-*` token classes (muted baseline, primary
516+
beat); no other bespoke SVG is allowed.
473517

474518
## 8. Density
475519

0 commit comments

Comments
 (0)