Patterns
How components fit together into pages. Each pattern names its components and the tokens it uses.
App shell
Section titled “App shell”Sidebaronsurface-200,sidebarwide. It holds the wordmark, the primary nav (Home, Chat, Tasks, Automations, Agents, Knowledge, Usage, then a Workspace group with Settings) and a footer. The footer has setup progress, theme and sign out. The current item sits onsurface-selected, withemerald-deeptext and icon.- Top bar,
topbarhigh: sidebar toggle, breadcrumb, the ⌘K launcher, the notifications bell and help. The launcher is a button shaped like a search field. - Notifications live behind the bell (Tabler
bell), never in the sidebar. The bell carries a countBadgefor unread items. It opens a list with approvals and questions first, each with Approve in its row, then finished and failed tasks. The empty list reads “You are up to date” with “Approvals and finished tasks show up here.” - Content sits on
surface-000, padded by the layout rule, with oneh1. - Between
bp-smandbp-mdthe sidebar becomes a 56px icon rail with tooltips. Belowbp-smit becomes a drawer opened from the top bar. The composer in Chat stays fixed to the bottom on phones.
Navigation
Section titled “Navigation”Tabsswitch between views of the same object, such as a task’s Activity and Result. They use the underline style with anemerald-deepindicator. Arrow keys move between tabs.- Inside one tab, a
SegmentedControlswitches between two ways to show the same content. A task’s Activity tab has Summary (theTimeline) and All events (theEventLog). Breadcrumbsshow the path when a page is more than one level deep: “Tasks / Daily finance digest”. The current page is text, not a link.Paginationfor lists over 50 rows. Infinite scroll appears only in chat history.Menuholds secondary actions. It opens from anActionIconwith the dots icon. Destructive items come last, indanger, after a divider.
Lists and tiles
Section titled “Lists and tiles”- A task, agent or automation is a
Cardtile in an auto-fill grid. That is a grid that fits as many columns as the width allows. The title ish4, with one line ofbody-smmetadata. The statusBadgesits top right and the actions sit bottom right. - A clickable tile is one link. The whole card turns
surface-hoveron hover and scales to 0.98 on press. Secondary actions inside it are real buttons that stop propagation, so a click on them does not open the tile. - A selectable tile is for picking one option, such as a provider or an engine. At rest it shows a
border-strongedge. When selected it shows anemerald-deepedge, asurface-selectedground and the caret in the corner. - Use tables (
Table) for dense data that people compare, such as ledger rows and model lists. The sticky header sits onsurface-200. Numbers use tabular numerals, so the digits line up. Rows turnsurface-hoveron hover. Belowbp-sma table becomes stacked cards, or hides secondary columns behind a “More” disclosure.
Status and progress
Section titled “Status and progress”StatusCaretis the one progress indicator for tasks and automations. Queued iscaret-idle. Preparing and Planning draw the left stroke inink. Working and Checking draw both. Done fillsemerald. Failed swaps to the X indanger. The caret always sits beside its word in aBadge, so the state never depends on colour alone.- Use the
Progressbar for anything with a known fraction, such as budget used or an upload. The track ismistand the fill isemerald-deep, withradius-full, 4px high. A label with the number sits beside it. - Work that runs for seconds shows the lift caret with “Thinking” or “Working…” text (
Loader). Nothing spins.
Feedback
Section titled “Feedback”Notification(toast) appears bottom right, or top centre on phones. It usessurface-100andshadow-md, with a status icon and one line. It closes by itself after 5s, or 10s when it has an action. New toasts stack at the bottom. It hasrole="status".Alertsits inline, above the content it is about, for things that stay: “Task needs approval”, “Provider key expired”. It is asurface-100card with a 4px status edge down the left side. The icon sits in a 32px circle on the status-softtint. It has a title, one line and an optional action.- Use a confirmation
Modalonly for destructive or expensive actions. The title is the question. The body names what is lost. The primary button names the action (“Delete task”). The secondary button is “Cancel”, and it takes focus by default. - Prefer undo to a confirmation where you can. Archive the chat, then show a toast with “Undo”.
Empty, loading, error
Section titled “Empty, loading, error”- Empty (
EmptyState): anicon-lgicon and anh3title that says what would be here. One line ofbodysays how to add it, then one primary button. Centred, withspace-12padding. Never a sad face. - Loading: a
Skeletonin the shape of the content. A card grid gets card skeletons and a table gets row skeletons. The shimmer runs fromsurface-200tosurface-100. Show it only after 300ms, so quick loads do not flash. - Error: an
Alertindangerwith “Try again”. The page keeps whatever did load. One failed request never leaves a blank page.
Overlays
Section titled “Overlays”Modal: centred,radius-xl,shadow-lg, overoverlay. It is at most 560px wide (480px for confirmations), and full-screen belowbp-xs. It holds anh2title, the content, and actions aligned right. Escape and the scrim (the dimmed layer behind it) close it, unless the form has unsaved changes.- A drawer slides in from the right for inspectors, such as task details or tool call output. It is 480px wide, and full width on phones. It uses the same tokens as the modal.
Tooltip:surface-inversewithink-inverse,radius-mdandcaptiontext, after a 400ms delay. Use it for icon-only controls and cut-off text. Never put essential information in a tooltip.- Popovers and menus use
surface-100,border,shadow-smandradius-lg.
Artifacts and the code editor
Section titled “Artifacts and the code editor”- Everything a task produces goes into the Artifacts section of the task’s Result tab (
ArtifactViewer), under the task’s Summary. Each type has a built-in viewer: PDF, Markdown, text and code, CSV, images and HTML. Any other type gets a download card. Download is always there. - When a task works on files in its sandbox, such as code in a repository, the Artifacts section also has the “Open in code editor” button (
CodeEditorButton) above the viewer. A task with no sandbox shows Artifacts only. The code editor is based on Code-OSS, the open-source core of VS Code. It runs with openvscode-server in its own container next to the task’s sandbox and sees the same files. The button and the interface call it “code editor” and never name a product. - It starts on demand. Nothing runs until someone presses the button. The button turns busy with the draw
Loaderand reads “Starting the code editor…”. This can take a few seconds. - It is read only while the task is Working. A “Read only”
Badgewith the lock icon sits next to the button, with one short reason: “You can edit the files when the task stops.” Editing unlocks when the task stops: Done, Failed or Stopped. Nothing else writes to the files then. Edits made after that start a follow-up task, so a finished task is never reopened. - It opens in a new browser tab, on its own origin. It shares no cookies or storage with the Upmo app.
- It stops when idle. After a while with no use, the editor stops and frees the sandbox. The button starts it again.
- User messages sit on the right, in bubbles on
surface-100. A bubble usesradius-lg, with a 4px bottom-right corner. Assistant replies sit on the left, next to the 20px caret avatar. They have no bubble, onlyink-secondaryprose atmeasurewidth. - Tool calls collapse into one group row (“3 tool calls · 2.8 s”) with caret bullets. The row expands to show each call in
code. - The composer is a
Textareain aradius-xlcontainer onsurface-100. It getsshadow-mdwhen focused. It has a knowledgeChiprow, a model picker, attach, mic, and the primary sendActionIcon, which carries the caret. - A metadata row sits under each reply in
body-smink-muted: model, tokens, duration, cost. Copy and Activity appear in it as subtle buttons.
Marketing
Section titled “Marketing”- Familjen Grotesk
herosets the one headline. Manrope sets everything else. Useemeraldsparingly: the caret, the “up”, one primary button per screen. - Sections alternate between
surface-000andsurface-100. The install section sits onsurface-inverse. - The landing page scrolls down, like every other page. Reversed scrolling breaks Home and End, anchor links, trackpad momentum and screen readers. So “up” lives in the content instead. The caret draws upward once on load, and the proof timeline climbs from first step to done.