Skip to content

header consolidation

github-actions[bot] edited this page Sep 20, 2026 · 1 revision

Header Consolidation

How every right-side workspace view was brought under one shared header standard. Companion to ui-design-guidelines.md.

The standard

One component renders every header: WorkspaceViewHeader (frontend/src/components/workflow/WorkspaceViewHeader.tsx).

  • Leading icon in an h-9 w-9 tile (h-4 glyph), sized to span the title + subtitle block. Custom elements (the hub's entity avatar) render as-is at the same footprint.
  • Title text-sm font-semibold, subtitle text-xs text-muted-foreground, rendered by the header itself — views never override the sizes.
  • Optional inline context (counts, timestamps, badges) next to the title, and a full-width below row (stats strips, pills).
  • Actions on the right, rendered with the shared pair below.
  • Tabs, when a view has them, belong to the header via its tabs prop and render pinned to its bottom edge. Pickers and dropdowns live in the content, never in the header row.
  • Per-tab extras via tabActions render left of the base pair; to change the pair itself per tab (Ask AI message, refresh handler), compute actions from the active tab instead.
  • bare variant for views whose shell owns the row (Costs, Execution Logs via InspectorShell) — visually identical, no duplicate border. sticky variant for scroll views (triggers).

Plan and Report are the only views without a header: they are canvas overlays, not titled views.

The action pair

Every header ends in the same two icons: Ask AI left, refresh right, via WorkspaceViewActions. The order is a product rule, not a habit — Ask AI is always the left icon and refresh the right one so the pair is predictable wherever it appears.

  • AskAIButton sends one pre-written message to chat. Icon-only in headers: it expands on hover/focus to reveal the label, and sends on a two-click arm/confirm (a single click next to Refresh used to burn a chat turn on misclicks). After a successful send it briefly shows "Sent!".
  • WorkspaceViewIconButton is the shared refresh button (spinning state while refreshing). Every view that loads data has one.

One function to chat

All right-pane sends converge on sendWorkspacePaneMessageToChat (frontend/src/utils/workspacePaneChat.ts): the only public entry point. It takes a message plus one destination key (automation path, tab id, or Crew project), resolves the right conversation, opens the left chat, queues behind a running turn through the same durable chat queue, and restores a stuck session. Callers are one-liners:

Sender File
Ask AI buttons (everywhere) AskAIButton.tsx
Crew views WorkWorkspacePane.tsx (adds the project id, same function)
Reports dashboard widgets reportWidgets/useReportChat.ts
Human decisions (Report + Pulse) utils/reportHumanInputChat.ts
Pulse manual review PulseWorkspace.tsx
Capabilities panel WorkflowCapabilitiesPanel.tsx

The only sender outside it is the main chat composer in ChatArea.tsx, which owns the queue itself. Product surfaces with their own chat lane (Crew) route through AskAIButton's onAsk prop and still land in the same function. New "send to chat" buttons need nothing else.

Ask AI copy

Ask AI messages are user-visible, so they are plain business words: no tool names, skill paths, or config keys. Builder messages use the workspaceAskAI marker blocks (utils/askAIMessage.ts) — a visible summary plus hidden builder instructions — with one message per view in WORKSPACE_ASK_AI_MESSAGE (workspaceAskAI.ts). The map is exhaustive over registered views, so a new view cannot silently ship without one. Views with distinct tabs (Integrations, Knowledge) follow the active tab instead of the view. Crew messages stay plain strings sent to the project chat.

What was migrated

  • All Builder inspectors and Setup sections, the automation hub, and every Crew pane render the shared header with the standard pair.
  • The execution-logs run dropdown moved out of the header into a content row; the live-browser session picker sits below the header.
  • Files tree and file content share the same header; Costs and Logs use the bare variant inside their shell.
  • Knowledge became one umbrella view with three tabs (Learnings, Knowledge Base, Database), each with its own Ask AI message.
  • Pulse gained the shared refresh button; triggers use the sticky variant.
  • Toolbars use open/close groups (WorkspaceToolbarGroup), never dropdowns: primary icons stay visible, Ops and Setup collapse into single-open groups that follow the active view.

Verification

  • npx vitest run (frontend; only pre-existing peer-owned provider / session-restore failures remain)
  • npx tsc -b, npx eslint on touched files
  • Header adoption is pinned by the per-view header tests; Ask AI copy by the workspaceAskAI marker-block tests.

Clone this wiki locally