Skip to content
ThorbisInterface Guidelines (opens in a new tab)
Resources

UI

Any screen.

SKILL.md.agents/skills/thorbis-ui/

Follow the skill selection policy and shared Linear baseline. For mobile-app work, the Native contract (D-025) is required.

Scope and required context
Linear baseline: This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the Thorbis × Linear pattern matrix only when the owning pattern is ambiguous.
Mobile platform gate (D-025): Every mobile-app task requires the Native contract, HIG-001–HIG-022, and relevant live Apple Human Interface Guidelines (opens in a new tab). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Craft for the operating system for the trades. Linear’s grammar. Our words. Tokens only.

This is its own skill. Drop it at .agents/skills/ui.md. Pick this file. Do not average it with the others.

Live: https://design.thorbis.com/skills/ui

Rules is what we ship. Research is the homework. `DESIGN.md` is the constitution. `AGENTS.md` is the contract.

This skill holds: D-003 (no raw visual values), D-004 (interactive controls use the kit), D-016 (prefer a mark), D-017 (a radius is a curve you can see), D-018 (a fill is one mix; no solid colored side rail), D-019 (reserve the space), D-020 (outline at rest, fill when this is the place), D-021 (overlay is a mix), D-023 (role owns prominence; the group owns geometry), D-024 (attention orders media). The picture: figure and ground, proximity, the inverted L as composition.

Homework: Byron Wade, no borders on the page; a 1px rim on the field; one pour. Steve Schoger, start with too much space; remove until one more useful row fits. Rauno Freiberg, a sheet grows from the row that opened it. shadcn is the kit; we dress it. Grammar, not costume.

For inventing a new surface so it belongs, use Product. For shell geometry use Linear baseline. For iOS, Android, or desktop use Native. For marketing and video use Cinematic. For motion, color, or type, open those skills after this one.

References: open one only when the task needs it.

  • Cloudflare forms: form kind, labels, field width, errors beside the field, and commit names.
  • Shopify Polaris: collections, filters, saved views, bulk actions, multi-edit, record structure, and save state.
  • Vercel + Geist: choosing a primitive by role, semantic tokens, empty and loading states.

thorbis-ui-SKILL.md

First

Answer these, in order, before you draw.

  1. Who is holding the device, and what just interrupted them? Dispatcher at 7 a.m. Tech in a crawlspace. Owner closing the books.
  2. Which profile? Workbench, Guided, Evidence, or Showcase. One. Do not mix.
  3. What already exists? Native control, then the kit, then last a new primitive. D-004. D-007.
  4. What is the one action on this view? Dispatch. Arrive. Save invoice. Everything else is quieter.

Do not offer a menu of looks. Make the call. Write the interface.

Profiles

ProfileWhereDensityMotion
WorkbenchBoard, books, AdminHigh. Keyboard.Press only.
GuidedArrive, estimate, portalOne action.Rare; follow Motion.
EvidenceInvoice, report, auditPaper.None.
ShowcaseMarketing, first-runProduct is the picture.Delight only here.

A dispatch board is not a landing page. If the surface is Showcase, stop and open Cinematic.

Stack

tokens → primitives → components → patterns → pages

Pages fill patterns. They do not invent buttons.

  1. Tokens own color, type, space, radius, shadow, motion. No hex in JSX. No text-white. D-003.
  2. Primitives are the kit. Copy shadcn in, dress with tokens. Base UI when a primitive is missing. We own the styles.
  3. Components are stable combinations: SearchField, DataTable, EmptyState, CommandMenu.
  4. Patterns are List, Record, Settings, Evidence, Guided, Board, Inbox, Search, Canvas.
  5. Pages put trade data in a pattern. A durable job is a route. A collect-payment is a modal. Linear baseline owns that call.

Search the registry before you create. A new primitive is design-system work, not a feature shortcut. D-006. D-007.

Surfaces

Dark is the default product. Light is a retune, not an invert.

TokenDarkLightJob
bgnear-black voidcreamCanvas. Never a working surface.
panel#171717paper whiteThe sheet. The job lives here.
fieldone step darkerwarm wellInputs, wells, icon circles.
fgcream #f7f4eewarm inkTitles, active, commits.
bodycool greywarm greySentences.
markerquieter greyquieter greyChrome, captions.
accentelectric bluesame blueBrand, focus, the live row.
  • The sheet is brighter than chrome. They meet by tone. Regions have no borders as separators.
  • A rounded figure that must be found has a 1px rim that follows the radius. Overflow clips content, not the stroke. Never an inset box-shadow as the outer edge of an overflowing box. Canvas-on-canvas without that rim is a defect. D-017.
  • A field is a well: one step darker than its parent, inset, 1px rim.
  • A commit is ink: type-color fill, inverse type, 10px radius, 1px rim.
  • Same fill as the parent is illegal. If you cannot see the control, change the fill, not the stroke.
  • Chips are pills. Icon-only is a circle. Sheets are 14px.
  • Photos get a 1px rim that follows the radius, plus the same short lift.
  • Nested radii stay concentric: inner = outer − padding.
  • Depth is a whisper: 1px drop. The rim is a border. Not a card stack.
  • Menu and place marks may carry a quiet extra (olive, forest, pumpkin, burnt, mixed accent). The word stays type-color. Color.
  • A fill is one mix. Never a gradient, mesh, or fade unless the brief names that wash. Never a solid colored border on the leading or trailing edge. Live is a word, a mark, or accent on the thing. D-018.

Numbers live in Color.

Controls

KindShapeTypeVisual height
Icon-onlycircle16px mark28px
Chrome wordnone13 / 500~28px
Chip / pillpill13 / 500~28px
Fieldwell, 10px14 / 400Shared control density
Commitink, 10px14 / 500Shared control density
Isolated mobilewell or ink16+44px
Sheet14px,,

Use the compact or comfortable density defined in `DESIGN.md`. The field and its actions share height and type size; weight and surface still express their roles. On mobile or a coarse pointer, use the touch size and at least 16px input type.

Desktop hit 40. Touch 44. Isolated mobile 44. Hit areas never overlap. If it looks tappable, the whole chip has to take the tap.

Prefer a mark. Add a word only when the action would be guessed wrong without it. D-016.

For action-neighborhood geometry and prominence, follow `DESIGN.md` D-023.

  • Chrome is icon-only: search, theme, command, close, back, overflow. Accessible name. Title on a mouse. Regular at rest. Fill when this is the place. Directional marks flip in RTL. D-020.
  • A commit keeps a word when it is destructive, when two commits sit together, when the mark is not a household verb, or when it is the one Guided action. Save invoice. Cancel job. Arrive.
  • A value chip stays a word. Leak is not an icon.
  • Labels persist. Placeholders are emptiness (Mike Reyes), not the label (Enter name).
  • Help sits under the field. An error takes its place. Not a toast.
  • Loading morphs the mark and turns. If a word is there, the word stays. Do not swap Save for a spinner. Dispatching twice creates two trucks.
  • Hover is color only. No wash behind a nav word. Gate it: (hover: hover) and (pointer: fine).
  • Focus is visible and is not selection. Accent ring. Keyboard works everywhere.
  • ⌘K is instant. Do not animate it.
  • If it lifts, you can press it.
  • Two rimmed controls keep 12px. Field to commit is 12px. A name field kissing Dispatch reads as one mashed control in the van.
  • Overlay is a mix, not a blur. A popover grows from its trigger. A menu fades. D-021.
  • A full-width commit sits in the sheet’s pad, not flush to the viewport.
  • Media has an aspect-ratio. A horizontal list shows 16–32px of the next item. Fade a list that continues. D-019.
  • For media delivery order, follow `DESIGN.md` D-024.
  • Destructive money is a modal. Voiding an invoice is money. Do not confirm “Mark arrived.”

Type and words

Inter Variable for UI. Geist Mono for code, the shop's printed number, and money. Details in Type. Chrome is 13. Content is 14.

OursNot
JobTicket, case, request
StopAppointment slot
TechAgent, resource, user
TruckVehicle asset
BoardKanban, pipeline
SheetModal, drawer, card
DispatchAssign, allocate
ArriveCheck in, clock

Street first. 114 Oak, then the leak. Not JOB-1842 as the title. Status is a word: Open. En route. On site. Not a green blob.

Sentence case. When a control has a word, it names the action: Save invoice, not Continue. Prefer a mark. Empty names the one action. Errors name the problem and the exit.

Picture

One focus. The sheet is figure. Chrome is ground.

Every view has one thing they came to do, and one place the eye should land.

  • Workbench: the selected row, the record title, the field they are in.
  • Guided: the step. Then the commit.
  • Evidence: the number.
  • Showcase: the object. Cinematic.

If two things shout, neither is read. Size, position, and weight do the shouting. Color last. Accent is the live thing, not the layout.

LawMeansIn Thorbis
Figure and groundWork on a quieter fieldSheet on canvas. Canvas is never the work.
Negative spaceEmpty is structureTight inside a group. Generous between groups. Measure 65–75ch.
HierarchySize, then position, then weight32 title. 16 section. 14 body. 13 chrome. No kicker.
ProximityClose means relatedLabel, field, help. Not a card per field.
SimilaritySame look, same kindOne commit shape. One well. One chip.
ContinuityThe eye follows a lineInverted L. Sidebar, location, sheet. Do not break it with a second header.
AlignmentEdges agreeType, fields, commits share a start. Do not mix center and start on one sheet.
ContrastDifference is the signalWell vs sheet. Ink vs quiet. Live row vs the rest.
BalanceWeight, not decorationA long list is the weight. Chrome stays quiet so it can carry it.

Golden ratio is not a layout tool here. Thirds are for Showcase and video. A dispatch list is a column, not a poster.

Read top-left to the sheet. F-pattern on a list. Z-pattern only on Guided and Ask, where there is one title and one commit.

  • Street first in the row. Time is a column. Status is a word on the end.
  • The primary action sits with the work, not in a dashboard of equal buttons.
  • More space above a heading than below it. The heading belongs to what follows.

Do not place a commit on a thirds intersection to “feel cinematic.” That is Showcase. On a board it is costume.

Rest, sink, lift, overlay. Four, not five. The sheet is planar. A field sinks. A commit lifts. A menu overlays. Hover is none of these. If it lifts, you can press it. A drop shadow on a heading is a lie.

Media has an aspect-ratio before it loads. A skeleton matches the hole. A horizontal list shows 16–32px of the next item so it does not read as the end. Where a list continues, fade the edge. D-019. A van photo that pops in after the row has already been read shoves the next job. Delivery order follows `DESIGN.md` D-024.

A mix, not a blur. The board behind Collect payment stays sharp and one step dimmer. A popover grows from its trigger. D-021.

Floor

  • Body contrast APCA |Lc| ≥ 75. Fix with lightness, not hue. Color.
  • Chrome is 13. Content is 14. Measure 65–75ch. Headings balance. Body pretty.
  • Hover gated. 100dvh. viewport-fit=cover. Tap highlight off.
  • Inputs on a phone are 16px or larger. Never user-scalable=no.
  • States exist: hover, disabled, loading, error, empty, permission, destructive. D-009.
  • Real trade data. Not Acme. Not Lorem.
  • Desktop 40. Touch 44. Destructive money is a modal.
  • Light and dark are both first-class. Theme still sticks.

Never

  • A second visual language on one product
  • A line around a region as a separator
  • A radius whose corners disappear
  • An inset box-shadow as the outer edge of a clipped radius
  • Canvas-on-canvas without a rim
  • A wash behind a nav word
  • Card-of-cards as the page
  • A second header invented by the page
  • Animation on a shortcut
  • Marketing copy on a board
  • A desktop drawer used as a page
  • A nested overlay
  • Hex, text-white, or a raw shadow in product code
  • A word on a button a mark would have made obvious
  • Icon-only chrome with no accessible name
  • A gradient, mesh, or fade across a surface, unless the brief named that wash
  • A solid colored border on the leading or trailing edge of a row, a card, a quote, a callout, or a sheet
  • A blurred overlay
  • A scroller that hides the next item
  • Layout shift from a photo without an aspect-ratio
  • A thirds grid on a workbench
  • Filling negative space because it looked empty
  • A second focal point “for balance”

Done

Name the profile, the one action, and the token or primitive you used. Name anything you refused.

Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

A control keeps its meaning through every state

Owning skill: ui.

A button that changes width, a field that loses input, or a dialog that loses focus breaks the task even when the resting design looks precise.

Review the approved primitive as a sequence: resting, focused, activated, pending, resolved, and recovered. Keep the action label and footprint stable, associate errors with their fields, and preserve a visible keyboard path.

Thorbis example: Save estimate remains Save estimate while its state mark changes. A validation error keeps the entered values, explains the repair beside the field, and moves focus only when the interaction calls for it.

Verify: Test Tab, Shift-Tab, Enter, Escape where applicable, paste, invalid input, rapid activation, and a slow response. Repeat at 390px, in both themes, with zoom and reduced motion.

Do not import: No hand-built duplicate primitive, hidden label, disabled browser zoom, or borrowed shadow-only outer edge that violates D-017.

Evidence: Web Interface Guidelines (opens in a new tab); Invisible Details (opens in a new tab); components.build (opens in a new tab); Details that make interfaces feel better (opens in a new tab). Source access limits.

All 26 sources and review limits.

All skills

The bundle includes every skill. Use Resources to choose the smallest context for a task.

Loading search…

Loading search. You can close this message and keep reading.