Skip to content

Components

Topbar

flowchart LR
    subgraph Topbar["Topbar"]
        direction LR
        subgraph Brand["Brand region"]
            B["[Brand mark]<br/>Brand Name<br/>DASHBOARD"]
            Icons["[≑ Fields]&nbsp;&nbsp;[βš™ Correlation]"]
        end
        subgraph Tabs["View tabs"]
            T["[Matrix] [Swimlanes]<br/>(segmented tabs)"]
            Theme["Theme: [β˜€] [☾] [Auto]"]
        end
        KPIs["KPIs Γ— 4"]
        subgraph Right["Filter region"]
            F["Filter + ⚠ toggle"]
            SSE["[SSE Live]"]
        end
    end

Sub-components

Element PrimeNG Component Behavior
Brand mark Custom 32Γ—32 radial-gradient square, border-radius: 9px
Segmented tabs p-selectButton Four options: Matrix / Swimlanes / Feed / Analytics. Active = accent gradient + glow ring. Switches view.
KPI strip Custom 4 counters: services, environments, in-flight (.is-warn), failed (.is-bad). Derived from data.
Filter input pInputText Matrix-only, inline. Filters service rows by name (case-insensitive substring).
Failures toggle p-toggleSwitch Matrix-only, inline pill. .is-on = coral border + switch, hides non-failed rows.
Theme switch p-selectButton 3-state segmented: β˜€ / ☾ / AUTO. Sets data-theme on <html>, persists to localStorage.
Icon buttons β€” Fields (β–¦) Custom Shared (Matrix + Swimlanes). Opens Fields picker popover. Shows accent state + hidden-count badge when any fields are OFF. Tooltip: Fields β€” toggle visible data fields (normal); Fields β€” N field(s) hidden when N > 0.
Icon buttons β€” Columns (⊞) Custom Matrix-only (hidden in Swimlanes). Opens Columns picker popover. Shows accent state + hidden-count badge when any environments are hidden. Tooltip: Columns β€” show/hide environments (normal); Columns β€” N environment(s) hidden when N > 0.
Icon buttons β€” Correlation (⇆) Custom Swimlanes-only. Opens Correlation picker popover.
Icon button β€” Feed dock (btn-feeddock) Custom Shared (all views). Toggles the Deployment Feed Dock open/closed; aria-pressed reflects open state. Disabled (dimmed, non-interactive) while the Feed view itself is active. Tooltip: Deployment feed β€” toggle the live event panel.
Bell toggle (πŸ””) Custom Enables/disables browser notifications. Toggling ON for the first time triggers the browser permission prompt (lazy β€” never on load). Hidden when the Notifications API is unsupported, permission is denied, or the context is insecure. Tooltip: Notifications β€” enable/disable desktop alerts.
Presets (bookmark) Custom Shared (all views). Opens Presets popover. Shows filled badge dot (presets-badge-dot) when at least one preset is saved. Tooltip: Presets β€” save and restore view configurations.
Live indicator Custom Green dot with pulseRing animation (1.8s). Shows SSE connection status.

Tooltip consistency. Every interactive topbar control carries a concise hover title tooltip: view tabs, service filter input, failures-only toggle, theme options, Fields button, Columns button, rate-limit chip, feed dock toggle, bell toggle, and the Live pill.

Hidden-count badge. Fields and Columns buttons share the same badge mechanism: when the hidden count N > 0, the button gains .is-active accent styling and a small filled count badge (.hidden-count-badge) positioned top-right on the icon. When N = 0, the badge is hidden and styling reverts to default.

Topbar must be position: relative; z-index: 30 so popovers render above sibling stacking contexts created by backdrop-filter on the matrix/vis shells.


Matrix Tile

Each cell in the services Γ— environments grid. Tile sizing is content-driven β€” grows/shrinks with toggled fields.

flowchart TB
    subgraph Slot[".slot β€” 3px left accent bar (status-colored)"]
        direction TB
        VerRow[".ver-row β†’ version + actor + time<br/>version&nbsp;&nbsp;&nbsp;@actor&nbsp;&nbsp;3h ago"]
        Attrs[".tile-attrs β†’ packed mid-row<br/>.ta-bl: βŽ‡ ref  sha&nbsp;&nbsp;&nbsp;&nbsp;.ta-br: β†— run #N"]
        Full[".ta-full β†’ full-width tail<br/>N parents"]
        VerRow --> Attrs --> Full
    end

Key Rules

  • Version: single-line, white-space: nowrap, NO truncation, NO ellipsis. May be up to 50 chars. Column expands to fit.
  • Accent bar: 3px left-edge ::before pseudo. Color matches status.
  • Split tiles (states S2–S4): two sections separated by border-top: 1.5px dashed var(--divider-dash). Top = current state. Bottom = last-successful identifier.
  • Bottom-section identifier uses fallback chain: version β†’ sha β†’ ref β†’ run_number.
  • Empty slot: muted "β€”" mark, reduced opacity background, no accent bar.
  • Minimum height: ~56px (bare chrome). No fixed height β€” tile grows with content.

Version Hover Highlight

Hovering any .ver span amber-highlights every tile across the matrix that shares the same version string. Effect: amber background + amber text + glow ring on .ver.highlighted, plus amber glow on .slot.highlighted-slot.

Live-Change Flash (#398)

A live SSE update that changes a slot's effective status (success / in-progress / failure β€” the context statuses pending/queued/waiting/cancelled/rejected never trigger it, per "Deployment statuses & context rendering" above) plays a one-shot accent glow on the affected tile, identified by (service, environment, namespace).

  • Rendered on .slot::after (tile-flash keyframe, toggled by .slot.is-flashing) β€” a separate pseudo-element layer, not the animation shorthand on .slot itself, so the glow composes with the box-state background/border/box-shadow and with breathe (running tiles) instead of overriding them.
  • Fades out over ~1.2s, then clears. One-shot β€” does not loop or persist.
  • Mirrors the Swimlanes tip-card flash (card-flash keyframe, .vis-card.is-flashing, see "Collapse / Expand (#309)" in views.md) for cross-view consistency. No auto-scroll counterpart β€” the Matrix is a grid, not a scrollable lane list.

6 Box States

Every (service, environment) slot resolves to exactly one state based on deployment history. (Ref: SAD Β§7 "6 box states")

Code State Name Condition CSS Class
S1 Success Last deployment succeeded .s-success
S2 Running + Last Successful Deploying now; prev terminal = success .s-run-last
S3 Running + Failed + Last Successful Deploying now; prev terminal = failure; older success exists .s-run-fail-last
S4 Failed + Last Successful Last deployment failed; older success exists .s-fail-last
S5 Running (no prior) Deploying now; no prior successful deployment .s-running-only
S6 Running + Failed (no prior) Deploying now; prev terminal = failure; no success history .s-run-fail-only

Per-State Visual Specification

S1 β€” Success: Full green tile. Version headline + actor + elapsed time. All toggled field attributes render below. Background: emerald-wash gradient. Border: emerald-edge. Accent bar: emerald.

S2 β€” Running + Last: Split tile. Top: amber spinner + running version + meta. Bottom: last-successful identifier (fallback chain). Dashed divider between. Breathe animation (3.6s). Border: amber-edge. Accent bar: amber.

S3 β€” Running + Failed + Last: Split tile. Top: amber spinner + ⚠ "prev. failed" badge β€” NO running version text. Bottom: last-successful identifier. Dashed divider. Breathe animation. Badge: coral bg + coral border pill.

S4 β€” Failed + Last: Split tile. Top: red "FAILED" tag + failed version + meta. Bottom: last-successful identifier. Dashed divider. Background: coral-wash gradient. Border: coral-edge. Accent bar: coral.

S5 β€” Running Only: Full orange tile. Spinner + version (or "Running" label if version empty). No bottom section. Breathe animation. Border: amber-edge. Accent bar: amber.

S6 β€” Running + Failed: Full orange tile. Spinner + ⚠ badge β€” NO running version, NO bottom section. Breathe animation. Badge: coral bg + coral border pill.

Spinner

14Γ—14px circle, 2px border. border-top-color: var(--amber), rest: rgba(245,165,36, 0.18). animation: spin 0.9s linear infinite. Drop-shadow filter for glow.

Warning Badge

Pill shape (999px radius). Coral bg at 15% + coral 45% border. "⚠ prev. failed" text β€” 10.5px uppercase 600-weight Inter.


Swimlane Node Card

DAG nodes in the Swimlanes view. Each node is rendered via an ngx-graph #nodeTemplate custom template. Internal layout uses a 2-column CSS grid.

flowchart TB
    subgraph Card[".vis-card β€” 3px left accent bar (status-colored)"]
        direction TB
        VerRow[".vc-ver-row (colspan=2, full width)<br/>version (left)&nbsp;&nbsp;&nbsp;&nbsp;3h ago (right)"]
        Attrs[".tile-attrs (subgrid 2-col)<br/>col1: βŽ‡ ref&nbsp;&nbsp;&nbsp;&nbsp;col2: β†— run #N @x"]
        EnvRow[".vc-env-row (subgrid 2-col)<br/>sha (bottom-left)&nbsp;&nbsp;&nbsp;&nbsp;environment (bottom-right)"]
        VerRow --> Attrs --> EnvRow
    end

    Grid["Grid: grid-template-columns: auto auto;<br/>column-gap: 20px; row-gap: 2px"]

Key Differences from Matrix Tile

Aspect Matrix Tile Swimlane Node
Primary identifier version (headline, 11px 600) environment (bottom-right, Inter 11px 600)
Version treatment Headline (prominent) Top-left (secondary, 10.5px 500, muted)
Internal layout Flex column 2-column CSS grid (subgrid rows)
Status states 6-state machine (split tiles) + next badge + never-deployed same model β€” effective primary + next badge + never-deployed (see "Deployment statuses & context rendering"; NOT just 3 states)
parrent_deployments Shown as "⟡ N parents" text NOT rendered β€” edges convey parents
Content overflow Column expands horizontally Rows scroll horizontally inside the card
Positioning CSS grid cell (flow) Managed by ngx-graph dagre layout (SVG <g> transform)
Selection Click β†’ history drawer Click β†’ Inspector panel + accent ring

Collapsed Lane Vector

When a swimlane is collapsed, it renders a vector β€” not a new compact component, but the same vis-cards reused in a horizontal chain.

Definition. The vector is the linear chain of vis-cards ending at the service's newest event (tip): - tip = node with max happened_at across all service nodes. - Built by walking backward through parrent_deployments from tip to the root. At a merge (multiple parents), follow the parent with the newest happened_at. - Rendered root→tip, left-to-right, with arrow connectors between consecutive cards. - All other DAG branches are hidden while collapsed. - If tip is isolated (no parents), the vector is that single card.

Visual. Cards are identical to the expanded vis-cards β€” same markup, same status styling (status-accent left bar, glass background, field rendering). Edges between cards are the same status-colored SVG arrows produced by the expanded renderer (not custom arrow connectors or a bespoke flex overlay). The collapsed vector runs through the identical partitionDAGs β†’ rankNodes β†’ assignTracks β†’ position β†’ card β†’ SVG-edge pipeline as the expanded form, restricted to the chain nodes.


Feed Row & Group Roll-up

The atomic rendering unit shared by the Feed view log and the feed dock body β€” one .feed-row per event, laid out on the shared --feed-cols grid (see views.md for the full 14-slot column contract).

  • Row states. .feed-row carries a status class (s-success / s-failure / … β€” the same 8-status set as "Deployment statuses & context rendering" below) that colors its .pip dot. Hover: subtle background tint.
  • Live-ingest flash. A newly-ingested event's row plays a one-shot accent-glow animation (feedFlash, ~0.85s) on first render β€” the Feed-surface counterpart to the Matrix Live-Change Flash (#398): same one-shot, non-looping intent, different trigger (any new event, not only effective-status changes) and different surface (row background tint, not a tile pseudo-element).
  • Group roll-up row (.feed-group-row). Renders the group's newest event through the standard row template; adds a .feed-chevron (β–Έ, rotates 90Β° when expanded) in the leading expander slot, and β€” when the group has more than one event β€” a Γ—N count badge (.feed-count-badge) in the trailing badge slot. The whole row (outside the run link) is clickable to toggle expansion.
  • Group detail (.feed-group-detail). Expanded state reveals every event in the group through the identical row template, at a reduced, dimmed style (smaller font, tinted background) β€” no separate renderer.
  • Flat mode. When the shared grouped/flat toggle (see behavior.md Β§ Interactions) is OFF, both surfaces render one .feed-row per event with no chevron and no badge β€” the group roll-up machinery is bypassed entirely.

Deployment Feed Dock

A fixed glass panel surfacing the live tail of the deployment-event log, visible on every view except the Feed view itself (#397).

  • Position & surface. position: fixed; left/right: 18px; bottom: 44px, z-index: 25 β€” below the history drawer and its overlay (z-index: 40 / 30), above the app content. Same glass treatment as the Feed view shell: translucent --glass background + backdrop-filter: blur(20px) saturate(140%), --glass-edge border, --radius-lg corners. Slides up and fades in via a transform/opacity transition when opened.
  • Header (.feed-dock-head). Live-status dot, title block ("Deployment feed" Β· "last 8 Β· live" subtitle), the shared group/flat toggle (.dock-group-toggle β€” see Feed Row & Group Roll-up), an "Open feed β†’" link that switches to the Feed view tab, and a close (Γ—) button.
  • Body (.feed-dock-body). Up to 8 rows (or groups), newest-first, rendered through Feed Row & Group Roll-up on the same shared column grid as the Feed view.
  • Open/close. Toggled by the topbar feed-toggle icon button (see Topbar β†’ Sub-components) or the dock's own close button. The open/closed preference persists to localStorage and survives reload.
  • Suppression on the Feed view. While the Feed view is the active tab, the dock is hidden (the page IS the full log) and the topbar toggle button is disabled β€” but the persisted open/closed preference is left untouched, so leaving the Feed view restores exactly what the user had before.
  • Live updates. A new SSE event prepends to the dock body (and to whichever group it belongs to) and plays the row flash animation β€” no dock re-open, no reload.

History Drawer

Right-side slide-out panel showing per-slot deployment history. Opened by clicking any Matrix tile.

  • PrimeNG component: p-drawer with position="right", [modal]="true", [dismissible]="true", [closeOnEscape]="true"
  • Width: 440px, right-aligned.
  • Overlay: --drawer-overlay scrim covering viewport. Click to dismiss.
  • Header: breadcrumb (component Β· environment), "history" title, close button (Γ—).
  • Entries: Timeline with colored pip in the status hue (all 8 statuses, not only emerald/amber/coral β€” see "Deployment statuses & context rendering"). Each entry is a full-width card showing ALL 11 domain-model fields as explicit label/value rows β€” NOT mixed-treatment.
  • Rendered fields per entry: version, status chip, ref, sha, run_number, actor, happened_at (elapsed + absolute UTC), parrent_deployments (list of truncated GUIDs), run_url link.
  • Close: Escape key, overlay click, or Γ— button.

Inspector Panel

Persistent right sidebar in Swimlanes view. Updated when a node is selected.

  • Width: 320px, part of the vis-shell grid.
  • Header: breadcrumb (component Β· environment), status chip + version.
  • Body: 2-column .insp-grid β€” ALL 11 domain-model fields as explicit label/value rows. happened_at shows elapsed + absolute UTC. parrent_deployments shows truncated GUIDs as accent-colored chips.
  • Fields render regardless of attribute-picker state.
  • Next group (issue #268): when slot.next is present, after the live fields a dotted separator then next status (chip) Β· next version Β· next run_url.

Deployment statuses & context rendering (issue #268)

Authoritative acceptance spec β€” every change to tiles / cards / history / inspector / legend MUST keep all of the below satisfied. Source of truth for the 8-status model; do not regress.

Status set (8)

Status Class Group Hue token Icon
success s-success effective --emerald βœ“
in-progress s-progress effective --amber spinner
failure s-failure effective --coral βœ•
pending s-pending context (next) --slate β—‹
queued s-queued context (next) --blue ≑
waiting s-waiting context (next) --violet β—·
cancelled s-cancelled context (next) --grey ⊘
rejected s-rejected context (next) --rose βŠ—
  • Effective statuses describe the environment's deployment health β†’ they DRIVE the tile/card colour (the 6 box states above).
  • Context statuses are the next deployment (beyond the live one) β†’ NEVER the tile colour; rendered as a badge/chip.

current vs next (per slot)

  • current = latest EFFECTIVE deployment β†’ tile/card primary (box state + split-bottom).
  • Split-bottom (S2–S4) shows the last-successful identifier via fallback version β†’ sha β†’ ref β†’ run_number (the previous deployment). Required on BOTH matrix tile and swimlane card.
  • next = latest CONTEXT deployment, present only when newer than current β†’ secondary .ctx-badge on its own .ctx-row: icon + status word + version. Rendered on matrix tile AND swimlane card.

Never-deployed slot (no effective baseline)

A slot whose only/latest deployment is a context status with NO prior effective deployment (e.g. first-ever gated/queued deploy). Read model: current is a context status, next absent.

  • Render a NEUTRAL / grey surface (no health colour) + version + meta + a status chip carrying the actual context status (its hue + icon).
  • DISTINCT from EMPTY ("β€”", zero deployment events β†’ slot absent from the row).
  • History = exactly ONE entry (the single deployment).
  • Applies to matrix tile, swimlane card, and inspector.

Surface parity

Matrix tile and swimlane card render the SAME state model: effective primary (6 box states) + next badge + never-deployed neutral. (Supersedes the earlier "Swimlane = 3 simple states" note.)

History drawer

  • All 8 statuses appear as distinct entries β€” pip + status chip in the status hue (not only emerald/amber/coral).
  • The next deployment is the most-recent entry (leads the list).
  • Never-deployed slot β†’ single entry only.

Legend (top-bar, per view)

Per-view content (matrix vs swimlanes), swapped on view change: - Status key — "Environment state" (3 effective) + "Next deployment" (5 context): icon + swatch + meaning. - Field reference — each visible field rendered AS IT APPEARS + its meaning (matrix MATRIX_FIELDS / swimlane SWIMLANE_FIELDS). - Matrix: tile layouts (split / prev. failed / never-deployed / empty). Swimlanes: edges = parent→child + the correlation predicate.


Popovers

On-demand dropdown panels anchored to icon buttons. z-index: 20 inside topbar's stacking context (z-index: 30).

PrimeNG component: p-popover with [dismissable]="true", appendTo="body".

Columns Picker (Matrix only)

Matrix-only. The ⊞ icon button opens this popover; the button and its wrapper div are hidden (display: none) when the Swimlanes view is active.

  • Toggle list: one checkbox row per environment, ordered by the current column order. Checked = visible; unchecked = hidden.
  • Last-visible guard: unchecking is blocked when exactly one environment is visible β€” the toggle click is a no-op, preventing a fully-empty grid.
  • Grid recompute: hiding or showing an environment triggers an immediate matrix re-render β€” the grid recomputes from the visible, ordered environments. No placeholder columns; hidden columns are fully absent from the DOM.
  • "Show all Β· reset order" action: a text-button at the bottom of the popover restores all environments to visible and resets the column order to the default environment order. Clears both localStorage keys.
  • Persistence: hidden set persisted to localStorage key dd:colHidden. Restored on load.

Pattern Filter (services + notifications)

A reusable glob pattern filter widget used at three sites: the topbar Services popover (Matrix + Swimlanes) and the Notification Preferences Popover (service axis + environment axis).

Structure. - Mode segmented control β€” two segments: - Services board: "Show all except" (exclude) / "Show only" (include). - Notification axes: "Watch all except" (exclude) / "Watch only" (include). - Pattern chips β€” one removable chip per active pattern; each chip has a Γ— remove button. - Inline input + autocomplete dropdown β€” freetext entry with a dropdown populated from known service (or environment) names; selecting or confirming adds a chip.

Glob syntax. * = any sequence of characters, ? = any single character. All other characters are literal. Matching is case-insensitive.

Composite service identity (services board + notification service axis). - Each slot is keyed by (namespace, service). Namespaced services have the composite identity namespace/service; null-namespace services use the bare service name. - Autocomplete is populated from these composite identities derived from received data β€” no configuration required. - Pattern matching: - Pattern with / β†’ matched against the full namespace/service string. - Pattern without / β†’ matched against the service segment across all namespaces β€” backward-compatible with all existing saved patterns.

Render-on-collision. In the Matrix and Swimlanes views the namespace/ prefix is shown in the row/lane label only when two or more services share the same name under different namespaces.

Visibility logic. - Exclude mode: an item is visible when it does not match any active pattern (empty pattern list = show all). - Include mode: an item is visible when it matches at least one active pattern (empty pattern list = show all).

Persistence.

Site Keys
Services board (Matrix + Swimlanes) dd:svcFilterMode, dd:svcPatterns
Notification service + environment axes dd.notifPrefs (bundled with other notif prefs)

Source. frontend/dashboard/src/app/shared/pattern-filter/, frontend/dashboard/src/app/core/utils/glob.util.ts.


Fields Picker

  • Shared between views; title and toggle list swap on view switch.
  • Matrix toggles (8): version, run_url, sha, run_number, ref, actor, happened_at, parrent_deployments. Default: all ON.
  • Swimlanes toggles (8): environment, version, run_url, sha, run_number, ref, actor, happened_at. parrent_deployments intentionally absent. Default: all ON.
  • Layout: 2-column CSS grid of p-checkbox ([binary]="true") labels.
  • Toggle ON state: accent border + accent background tint + filled checkbox dot.

Correlation Picker (Swimlanes only)

  • 5 radio options (p-radioButton): same sha, same run_number, same actor, same version, explicit parent.
  • Single-select β€” shared ngModel.
  • Below: time-window p-select with options: 5 min, 1 hr, 1 day, 7 days.
  • Time-window is disabled when explicit parent is selected.

Notification Preferences Popover

Accessible from the bell toggle area when notifications are enabled. Three independent filter axes.

Status filter. One p-checkbox per deployment status (all 8). Checked = notify on that status. Default: all ON.

Service filter. A Pattern Filter widget β€” mode "Watch all except" (exclude) / "Watch only" (include) + pattern chips + autocomplete input. Composite namespace/service matching applies (same rules as the services board). Default: "Watch all except", empty pattern list.

Environment filter. Same Pattern Filter widget, keyed by environment name. Default: "Watch all except", empty pattern list.

Persistence. All three axes persisted to localStorage (key dd.notifPrefs). Restored on init.

Presets Popover

Accessible from the bookmark icon button (btn-presets) in the topbar icon cluster. Shared across all views (Matrix, Swimlanes, Feed, Analytics).

PrimeNG component: p-popover with [dismissable]="true", appendTo="body". Min-width: 300px; anchored right-aligned to the button.

Structure (top-to-bottom):

  1. "Saved" section label β€” uppercase 10.5px muted heading.
  2. Preset list (.preset-list) β€” scrollable column (max-height 220px); one .preset-item row per saved preset. Empty state: italic "No presets saved yet." hint.
  3. Save row (.preset-save-row) β€” name input (.preset-name-input, max 60 chars, JetBrains Mono) + primary "Save" button.
  4. Import row (.preset-io-row) β€” "⬆ Import" button; triggers a hidden <input type="file"> accepting .json.

Preset item row (.preset-item):

Element Description
Name span (.preset-item-name) Truncated monospace label; full name in title tooltip.
Actions cluster (.preset-item-actions) Hidden by default; revealed on hover or when item is-active.

Per-item action buttons (.preset-action-btn). Rendered as icon buttons β€” each action is an icon (no label text) with a tooltip. Actions are hidden by default and revealed on row hover or when the item is .is-active.

Button Icon Action
Apply βœ“ Writes the preset's settings snapshot back to the live UI. Marks item .is-active.
Clone βŠ• Duplicates the preset as <name> (copy), inserts immediately after, marks copy active.
Update β†Ί Overwrites the preset's saved settings with the current live settings after a window.confirm. Name and version unchanged.
Rename ✎ Replaces the name span with an inline text input; commits on Enter / blur; cancels on Escape.
Export ⬇ Downloads the single-preset envelope as dd-preset-<slug>.json.
Delete βœ• .is-danger styling; prompts window.confirm before removing.

Reset all settings button. A text-button below the preset list that resets every captured setting to its framework default after a window.confirm prompt. Clears all localStorage preset-related keys and removes the active-preset tracking state.

Active state (.is-active): accent border + accent background tint (10% opacity). Applied to the last-applied preset row. The row also carries aria-current="true" and an inline "Active" text badge (.preset-active-badge, aria-hidden="true"). Note: saving a new preset does NOT mark it active β€” only Apply sets the active indicator.

Badge dot. The topbar bookmark button shows a filled dot (presets-badge-dot) when the saved list is non-empty; hidden otherwise.


Extension Components

Components specific to the browser extension (issue #301). Reuse status-chip and hist-link tokens/classes from the SPA where noted.

Toolbar Badge

The browser toolbar icon reflecting overall deployment health at a glance.

State Visual Trigger
Idle Base product logo mark, no overlay No in-flight or failed deployments (within watch scope)
In-flight Amber badge overlay with count β‰₯ 1 in-progress slot (status in-progress enabled in filter)
Failed Coral badge overlay with count β‰₯ 1 failure slot (status failure enabled in filter)
  • Base icon: product logo mark (same mark as SPA brand region).
  • Count: per-(serviceΓ—environment)-slot count; integer top-right; hidden when count = 0.
  • Priority: failed state takes precedence over in-flight when both are non-zero.
  • Status filter gate: disabling failure removes coral state; disabling in-progress removes amber.

Notification Toast

Browser notification fired by the background SW on SSE events within watch scope.

  • Trigger: any status transition where (service, environment) matches the watch filter AND the status is enabled in the status filter config.
  • Default: all 8 statuses enabled β†’ toast fires on every transition; narrow via the status filter.
  • Content: service name Β· environment Β· version Β· status label.
  • Link: entire toast links to the CI run URL (run_url); body includes "Open run #NNN" (run_number).
  • Accessibility (in-popup fallback display only): if a future DOM-based toast fallback is added, role="status" (or aria-live="polite") must sit on a non-interactive wrapper element β€” the <a> link must NOT be the live-region host. Does not apply to OS-level browser notifications, which are not DOM elements.

Deployment List Popup Panel

Stateless panel opened by clicking the toolbar icon. Re-fetches GET /api/deployments on open and on storage change. Shows the last N events newest-first; N = popupCount (default 5).

States:

State Shown when
Loading Fetch in progress
Unconfigured No dashboardUrl set
Paused Master Watching switch is OFF
Empty Fetch succeeded; no events match filters
List β‰₯ 1 matching event

Per-row fields:

Field Source field Rendering
Service service Plain text header
Environment environment Plain text
Version version Headline identifier
Status status status-chip (reuses SPA token/class)
Actor actor @ prefix
Elapsed happened_at Relative elapsed ("3h ago")
Timestamp happened_at Absolute UTC below elapsed
Run link run_url / run_number hist-link styled "Open run #NNN" (reuses SPA class)
  • "Open dashboard" link shown whenever a dashboardUrl is configured (footer of panel).
  • Filtered by service+environment watch filter and the status filter.

Extension Config

Extension settings panel (options page or popup settings section).

Master Watching Switch

A prominent enable/pause toggle that gates all extension activity.

  • ON (Watching): SSE connection active; badge updates; notifications fire.
  • OFF (Paused): SSE connection closed; badge cleared; no notifications; filter controls visually dimmed.
  • Persisted to extension storage.

Include/Exclude Watch Filter

Scoped filters controlling which services and environments generate badge updates and notifications.

Control Description
Mode segmented control Two options: "Watch all except" / "Watch only"
Services list Checkbox list of known services; selection is the exclusion or inclusion set per mode
Environments list Checkbox list of known environments; same include/exclude semantics
  • "Watch all except" (default): all services/environments watched; checked items excluded.
  • "Watch only": only checked items watched; unchecked items excluded.
  • Filter controls are dimmed and non-interactive when the master Watching switch is OFF.
  • Persisted to extension storage.

Status Filter

Per-status enable/disable checkboxes controlling which statuses appear in the popup list, trigger notifications, and count toward the badge.

Control Description
Status checkboxes (8) One checkbox per status: pending, queued, waiting, in-progress, success, failure, cancelled, rejected
  • All 8 enabled by default.
  • Disabling failure removes coral badge state; disabling in-progress removes amber.
  • Dimmed and non-interactive when the master Watching switch is OFF.
  • Persisted to storage.sync as statuses[].

Integer control setting the number of events shown in the deployment list popup.

  • Label: "Show last N events".
  • Range: 1–50; default 5.
  • Persisted to storage.sync as popupCount.