-
Notifications
You must be signed in to change notification settings - Fork 2
ui design guidelines
How settings and workspace views in AgentWorks (Builder automations and Crew
projects) are built. New views follow this page; existing views converge to
it. See setup-consolidation.md for the consolidation that established it.
Every workspace view renders one WorkspaceViewHeader
(frontend/src/components/workflow/WorkspaceViewHeader.tsx).
Plan and Report are the only views without one (canvas overlays,
not titled views). See header-consolidation.md for the migration
that established this.
- Leading icon in an
h-9 w-9tile (h-4glyph), sized to span the title + subtitle block. - Title
text-sm font-semibold, subtitletext-xs text-muted-foreground, both rendered by the header — views never override the sizes. Optional inlinecontext(counts, badges) sits next to the title; a full-widthbelowrow holds stats or pills. - Actions on the right: Ask AI left, refresh right, via
WorkspaceViewActions. The order is a product rule. Per-tab extras (tabActions) render left of the pair; pickers and dropdowns live in the content, never in the header row. - Tabs, when a view has them, belong to the header via its
tabsprop ({ value, onChange, options, ariaLabel }), rendered by the sharedWorkspaceViewTabspinned to the header's bottom edge. Tabs may carry icons and counts. Never build a second tab row. -
barevariant when the shell owns the row (Costs, Execution Logs),stickyfor scroll views — both visually identical to the standard.
One function sends every right-pane message to chat:
sendWorkspacePaneMessageToChat
(frontend/src/utils/workspacePaneChat.ts). It resolves the
conversation (automation, tab, or Crew project), opens the left chat,
queues behind a running turn, and restores stuck sessions. Every Ask
AI button, report widget, human-decision card, and Pulse action
funnels through it; new senders need only call it. Product surfaces
with their own lane (Crew) route through AskAIButton's onAsk prop
and still land in the same function.
- The header button is
AskAIButton(icon-only, expands on hover, two-click arm/confirm, "Sent!" acknowledgement), paired with the sharedWorkspaceViewIconButtonrefresh. - Ask AI copy is user-visible plain words: no tool names, skill paths,
or config keys. Builder messages use the
workspaceAskAImarker blocks (visible summary + hidden builder instructions), one per view inWORKSPACE_ASK_AI_MESSAGE, exhaustive over registered views so a new view cannot ship without one. Views with distinct tabs follow the active tab. Crew messages stay plain strings sent to the project chat.
Toolbars use open/close groups (WorkspaceToolbarGroup), never dropdown
menus: primary icon buttons stay visible, Ops and Setup collapse into
labeled groups that follow the active view. Group buttons are icon-only
with tooltips (aria-label + title), in a fixed order — Setup runs
Identity → Integrations → Playbooks.
The chat/workspace split has one decision point per surface: Builder
uses resolveWorkspaceLayout
(frontend/src/components/workflow/workspaceLayoutResolver.ts), Crew
uses resolveWorkSurfaceLayout
(frontend/src/products/work/workSurfaceLayoutResolver.ts). Each is a
pure function of its flags (visibility, focus, preview tier, split
ratio) returning every pane class, the grid style, and the mount
branches — call sites render from it and never branch on the flags
themselves. Truth-table unit tests pin every combination, so a new
flag or mode cannot silently break an old one.
- Panes stay mounted; states toggle visibility and width only. Never swap display modes or layout engines between states.
- Visibility restores its own display: a flex pane hidden below md
comes back as
hidden md:flex, nevermd:block. Responsive variants win over base utilities, somd:blockwould overrideflex, collapseflex-1scroll regions to content height, and freeze pane scrolling with no error. - Scroll invariant: every
overflow-y-autokeeps a definite-height ancestor chain in all modes (see Scroll). - Narrow viewports stay single-pane:
focusedPanepicks which pane owns the content row below md; at md+ both panes show as the normal split.
Tab content is built from the shared SettingsCard
(frontend/src/components/ui/SettingsCard.tsx), matching the shared
knowledge-bases design:
- Header row: leading icon (
h-4 w-4 text-primary),text-sm font-semiboldtitle, optional muted count pill (SettingsCount, e.g. "3 attached"), optional right-side action. - A muted plain-words explainer under the header.
- Content below, separated by the card's own spacing.
- Empty states use the dashed box (
SettingsEmpty); loading states use a muted spinner or status line; errors use the destructive banner (border-destructive/30 bg-destructive/10 text-destructive).
Cards stack with space-y-4. Do not nest cards inside cards, and do not
repeat the tab title as an in-content heading — the shared header already
titles the view.
Setup → Integrations carries a Connect tab (tab value cli) on Crew
projects and Builder automations, both rendering one shared
CliMcpSetupPanel
(frontend/src/components/integrations/CliMcpSetupPanel.tsx). The tab
points at the installation's API origin on both hosted and local installs.
- Lead with AI agent connection over HTTP MCP. Claude Code and Codex get direct registration commands; ChatGPT and Cowork get the same URL or a Cowork plugin. No CLI binary or pasted token is needed.
- Browser OAuth handles consent. List connected clients with a Revoke action.
- Hosted apps need a public HTTPS URL. A local AI agent may use a configured loopback HTTP URL from the same computer.
Users & access is a workspace view (WorkflowAccessView via
WorkspaceViewHost), not a top-menu entry: it follows the shared
header and cards rules like any other view, and is gated on
multi-user mode with admin/owner checks for management actions.
Personal access tokens are managed from the account menu
(AccountControl → AccessTokensDialog), never the top bar.
Build every form from the kit (frontend/src/components/ui/):
-
Input,Textarea,Label,Button(+ variants),Checkbox,Switch/ToggleRow,SecretField,Badge,ConfirmationDialog. - Surfaces and text use theme tokens only:
border-border,bg-card,bg-muted,text-foreground,text-muted-foreground,text-primary,hover:bg-muted. Status states use the semantic tokens —warning(needs attention: running, missed, partly paused),info(waiting),success(enabled, healthy),destructive(errors) — with alpha modifiers for tints (e.g.border-warning/30 bg-warning/10 text-warning, paralleling the destructive banner). No hardcoded gray/amber/red/blue/green/purple palettes — the one exception is a documented semantic state color (e.g. the amber bot-enabled toggle, whose meaning is spelled out in the adjacent copy). - Native elements stay only where the kit has no equivalent and the adoption test records the exception: radios and single selects.
- Primary
Buttonfor the page's main save;outline/ghostsmfor secondary actions;ghosticon(h-7 w-7) for row actions withtitletooltips. - Pills are kit
Badge(default/secondary/outline), not hand-rolled spans — exceptSettingsCountfor card-header counts. - Counts read as plain words: "3 attached", "2 saved", "0 attached".
Destructive removes use ConfirmationDialog with requireText: the user
types the object's name to confirm (GitHub-style). Copy states what is
removed and that it cannot be undone.
All identity badges render through EntityIdentityIcon (WorkflowIcon
for automations). An icon value is an emoji/short glyph or an uploaded
image stored as a downscaled (~128px) data URL, edited through the shared
IconUploadField (emoji field + Upload + Remove). Server validation
(agent_go/pkg/workflowtypes/icons.go) accepts both shapes; prompts and
tool results redact image bytes to "(custom uploaded image)".
One scroll surface per pane: the tab container owns overflow-y-auto and
embedded panels join it with manageOwnScroll={false}. Never nest a
self-scrolling panel inside a scrolling container. Refresh remounts the
active tab (a nonce key), since every tab loads on mount.
Plain business words everywhere the user reads: "apps", "passwords and keys", "folders", "bots". Workflow nouns for automations, project nouns for Crew. No jargon, no config keys, no emoji as icons.
Auto-synced from docs/ on main. Edit there, not here.