# Style guide Cletus is a professional tool for engineers, analysts and shop-floor teams. A plugin should feel like part of it: calm, dense, exact, and never in the way. Review checks this guide. ## 1. Principles - **It just works.** Values that can be computed are computed. Nothing waits for a button press that could have been automatic. - **Model the tool users already know.** A CAD screen behaves like the CAD viewers your users use; a forming screen like the forming tools they use. Keep familiar mouse controls and names. - **Nothing jumps.** No layout shift from messages, panels or loading. - **Professional density.** Small type, tight rows, icons. Never big friendly buttons. - **Simple surface, depth underneath.** Show what most people need; put the rest one click away, not on screen. ## 2. Words - Plain words, short sentences. Write for a manufacturing engineer, not a programmer. - No internal codes, ids, hashes or stack traces in the interface. A technical detail appears only when it adds to the plain sentence, behind "Details". - Errors say what happened and what to do: "The drawing has no tolerance table. Add one, or enter tolerances under Settings." Not "Error 422" or "Something went wrong". - Sentence case for labels and buttons ("Save report", not "Save Report"). - Units always shown beside the value and the input (`10 mm`). - Inexact values carry `~` with the reason on hover. Exact values carry no mark. ## 3. Theme - Use the host's tokens (CSS variables) for every colour. Never hard-code a colour, and never assume the theme is dark. - Cletus has three base themes (Amber, which is dark; Dark; Light) and customer variants. Test all three. - Engineering and data-dense screens set `"theme": "tool"`. Style controls with the semantic tokens: - toggled buttons: `--pressed-fill / -text / -border / -indicator` - primary buttons: `--primary-*` - the active tab: `--tab-indicator` - density: `--tool-font` (12 px), `--tool-row` (22 px), `--tool-pad` (6 px) - The accent colour is for thin indicators and small marks. No large filled accent areas. - One surface per card. No boxes in boxes. - Judge theming by intent (readable, consistent, calm), not by pixels. ## 4. Layout - **One job per region.** - The left rail holds the thing being worked on (a model tree, a document list, jobs). - The right rail holds tools, in one collapsible `SidePanel` that floats over the content and never resizes it. Collapsed, it is a slim icon rail. - The top toolbar holds view controls only. - A tool's sub-tools appear as a small strip at the top of the content only while that tool is active. - A fixed-height status bar shows the selection, progress with cancel, and dismissable failures. Errors never push content around. - Floating cards (properties, details) open only when asked for, are movable and closable, and never open on a click or right-click. - Nothing a dialog opens may land under it. A setting a dialog needs appears inside that dialog. - Settings sit behind a gear at the bottom right, not on screen-switching bars. - Icons on every toolbar button (host `Icon` set), with the name and shortcut in the tooltip. ## 5. Behaviour - **Esc** stops what is running or closes the innermost thing open (a menu, a live measurement, a panel). It never discards saved work. - Every job over a second shows progress, an estimate where possible, and cancel. - Instant values compute on selection with "Computing…" in place. A failure is a muted "unavailable" with the reason on hover, not a red banner. - Selection is easy to clear: empty click, Esc, × on the status-bar chip, right-click → Clear selection. Hover shows exactly what a click will pick. - Right-click shows only a menu. Menus are compact and grouped, like Cletus's own. - A resize changes the aspect only. Never re-fit or re-zoom the user's view. - Anything placed on the content (pins, labels, annotations) has a visible way to remove it. - Files dropped on chat only attach to chat. Your plugin opens a file only when the user chooses "Open in " or drops it on your screen. ## 6. 3D and 2D viewports - Use `sdk_viewport` for backgrounds and selection so every viewport looks the same. - Selection: a soft tint on faces and bodies; the full accent only on selected edges and outlines. Never flood a part in the accent colour. - Offer "Set orbit centre here" (trackpads have no middle button). - Labels stay inside the viewport and hide or point off-screen when their anchor is hidden. Never draw over panels or toolbars. ## 7. Chat tools - One tool, one operation. No hidden retries or fallbacks inside a tool: fail with the reason and the suggested next call, and let the AI decide. - Results are short, factual and stable: the same input gives the same text. - Name tools `_[_]` (`gauge_check_run`). - Descriptions say when to use the tool and when not to. ## 8. Go - `gofmt`, `go vet`, `staticcheck` clean. Standard library first. - Small packages under `internal/`, named for what they do. No `util`, `common` or `helpers`. - Errors wrap with context (`fmt.Errorf("read tolerance table: %w", err)`) inside the worker; the message that reaches the user is a plain sentence. - Every blocking call takes `ctx`. No goroutine without a way to stop it. - Comments say why, not what. Exported names have doc comments. ## 9. TypeScript and Svelte - Svelte 5 runes. An `$effect` never reads and writes the same `$state`. - Strict TypeScript. No `any` without a comment. - Components small and named for what they show. - No network calls; data comes from your worker or published links. ## 10. Tests - Every tool, service method and `ui.*` method has a Go test. - With screens (a later release): every screen feature gets a browser test that checks it changes what the user sees. Don't compare pixels. - Fixtures are synthetic. Reproduce real-world failures with made-up files that have the same shape.