Frontend design system
Use frontend/src/components/ui.rs and the tokens in frontend/styles.css when composing controls. Icons come from the Rust lepticons Lucide library, behind ui::Icon; category features keep the dependency scoped to application controls. No emoji or font-dependent glyphs for action icons.
Modalowns focus, dismissal, header and size. Compose its scrolling content withDialogBody,FormSection,FormField,CheckboxFieldandFormNotice. Put its final actions inDialogActions, outside the scrolling body. Describe sections in sentence case; keep helper text next to its field. Group related controls withFormField group=truerather than placing multiple controls inside a label.- Use standard
Buttonvariants andInlineActions. UseIconButtonfor compact actions with an accessible label.Iconrenders decorative 20px SVGs in the current theme color; the parent control supplies meaning. Top-bar actions retain desktop text. Action tooltips appear after 200ms on hover and immediately on keyboard focus, escape clipping, and disappear on Escape, pointer activation, scrolling or cleanup. DisclosurePanelretains mounted content when collapsed. Live tool calls share counts in first-use order; approval requests force the relevant group open. Thinking retains its separate text and token summary.ToolPanelowns headings, ordering/minimize actions, dock widths and full-height resize boundaries. Handles sit inside the panel edge independently of content wrappers. Feature panes provide content.FilesPanelcomposes Explorer/Changes selection insideSearchPane, which switches between mounted file views and results.LayoutStateowns limits and fitting;LayoutActionssaves preferences and widths through user-scoped database settings, with serialized writes and account-generation guards. Browser events belong toPanelResizer; local/remote feature operations still use existing Workspace and ProjectGit facades.- Phone tool sheets use the available width and retain desktop preferences. Collapsing panels and switching file views preserves their mounted state. Editor uses remaining width; each adjacent tool window has the same resize behavior and keyboard support.
- The composer uses a shared browser sizing primitive, grows up to 80% of its pane while reserving transcript/chrome space, and shrinks on programmatic draft changes. Whole-pane drops and paste/picker input all call
Composer::import, preserving validation and project/session/account guards.
Existing shared CSS classes remain supported while components migrate. Colors, spacing, typography, radii, dialog sizes and control height come from theme/design tokens. Avoid adding private control styles to individual dialogs or panes.
Reasoning, run context and tools use DisclosurePanel for left-aligned headers, down/up caret controls and retained collapsed content. Transcript entries do not shrink when history exceeds the viewport; the stream scrolls while each header keeps its natural height. Active reasoning adds its timing, token estimate and spinner to the shared header.
PanelToolbar groups contextual information and actions beneath the single ToolPanel heading; feature panes do not repeat their panel or selected-view titles. Explorer and Changes share file-row spacing, icons and selection treatment.
BranchPicker uses the shared dropdown for branch selection and New branch action in Changes and the footer. Keep the picker mounted across status refreshes; update status badges separately and discover branches on branch/scope changes or explicit menu opening. GitActions owns discovery, checkout and prompt scope, using ProjectGit adapters and guarding late results by project, account and host revision.
Dropdown owns the Recent-style menu surface, viewport fitting, focus, keyboard navigation and dismissal. DropdownSelect builds value choices on it. Recent projects, chat models and approval modes, Git branches, wizard choices and settings selectors share those primitives; use SegmentedControl for compact mutually exclusive view/mode switches. PanelSearchRow gives Files, Sessions and Find in file the same input and inline-action layout. Editor gutters fit the file’s largest line number and stay pinned while source scrolls horizontally; Inline uses old/new numbers and Split numbers each side. Split panes share horizontal and vertical scroll positions and the same content width. Edit’s text viewport sits beside its gutter, with syntax paint clipped above the horizontal scrollbar so paint never covers themed tracks or thumbs.
Panel headings always show Minimize directly; only panels with other actions show an overflow menu. ActionMenu groups secondary actions behind a right-aligned Lucide ellipsis and reuses Dropdown. Keep it inline with the row’s label or view switcher, reserving space by allowing long labels to truncate rather than wrapping the menu onto its own row. Files creation actions share the Explorer/Changes toolbar and appear only in Explorer. Keep primary actions such as Send, Stop, Save and Cancel visible. Menu items use explicit labels and existing feature callbacks; dialog handlers outlive the temporary menu surface.
Dock title bars use the shared ToolPanel heading spacing and typography. Each shared vertical boundary has one trailing grip. Resizing changes the fixed dock on the outer side of the flexible editor or Chat, so the seam follows the pointer after reordering. Only the dragged grip highlights. Server rows preserve the server name before provider metadata when space is limited.
Terminal is a full-width bottom dock, controlled from the status bar and available only with a project. Its top-edge separator resizes the database-backed height without consuming editor width. Account actions live in the shared username dropdown.
Chat uses compact, labeled icon controls beside the composer. Enter sends or queues, Ctrl/⌘+Enter steers an active run, and Escape stops it. Attach images lives in the Chat panel menu; paste/drop use the same image import path. Status telemetry stays on one line, with secondary fields hidden in narrower panes.