Tabs: what does not fit goes behind a menu (#84)

Concepts gains the tab row; Architecture loses the 90 px floor, which is gone,
and names TabStrip/tabRow in the file tree. Counter 790.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
DeveloperandClaude Opus 5 committed 2026-09-13 22:06:59 +02:00
1 parent 7ed7bc85b5
commit aa47bdd0b8
3 files changed
+17 -5

No files matched your search

+8 -3
@@ -23,8 +23,12 @@
measures from it — only what is drawn is shortened — and a subclass that puts something else
inside the control takes its room off `labelSlot()`, so a long value is cut rather than run
underneath the chevron. Given a `width`, a button is exactly that wide and truncates instead:
the Behavior, Texture, Animation and Container pickers keep their size whatever they show; the tab
bar uses 90 px as a floor. A button that can draw its label bold — on an accent fill: primary,
the Behavior, Texture, Animation and Container pickers keep their size whatever they show. The
tab row has no floor at all: it is label-wide at half the theme padding, and `TabStrip` drops
what does not fit into an overflow menu rather than letting it spill (the rule is
`tabRowLayout` in `editor/tabRow.ts`, so it is checkable without a browser; `__gm.tabRow()`
reports what is in the row and what went away).
A button that can draw its label bold — on an accent fill: primary,
danger, a toggled tab — is measured bold, or a dialog's `Delete` comes out as `Del…`.
The padding is an inset rather than a claim, so a 24 px icon button spends it on the glyph
instead of truncating it away; a button that switches between label forms (`↺` and `↺ ▾`) asks
@@ -56,7 +60,8 @@ src/viewport/ view (transforms), items (what to draw), symbols (how to
src/editor/ App → Editor (layout + ticker), PlaySession (the run), ProjectSession (load/create),
EditorRun (run in editor), state, actions, shortcuts, debugHook, autosave,
fileImport (drop/paste) → textureImport / fontImport,
framing (fit/marquee/snap maths), AssetTabEditor (the shared shell of the asset tabs)
framing (fit/marquee/snap maths), AssetTabEditor (the shared shell of the asset tabs),
TabStrip + tabRow (the tab row and what it does when the tabs outgrow it)
src/editor/viewport/ WorldViewport base + SceneViewport/GameViewport — editing tools, hence not in src/viewport/
src/editor/inspector/ Inspector panel, host (what a section builds into), field factory, previewHandlers (scrub → preview → command), valueSpecs
(where a value lives — shared with the List tab),
+7
@@ -43,6 +43,13 @@ from texture* and *Delete…*. In
**Scene objects** it offers *Select asset*, *Add collider*, *Create container*, *Unpack
container*, *Unparent*, *Expand all* / *Collapse all* and *Remove*.
**The tab row.** The centre column carries one button per tab. When the column is too narrow to
hold them all — a small window, or the side panels dragged wide — the ones that do not fit move
behind a `»` button at the end of the row, which lists them by name; picking one opens it and
brings it into the row. The tab you are editing is always in the row: if it has to, the row gives
up every other tab to keep it there. Nothing is ever drawn past the column's edge, where it would
sit under the inspector and take clicks meant for it.
**The console.** Under whichever centre tab is showing sits the **Console** panel, always
visible and resized by the divider above it — dragged all the way shut it keeps its own header
to be dragged open by. It mirrors everything that reaches the browser console: a `Log` node's
+2 -2
@@ -12,7 +12,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs
# code is lost (tail's is reported), so a red run reads as green
npm run build # writes dist/ and regenerates index.html
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
node tools/seed-e2e.mjs && node tools/e2e.mjs # 785 editor checks, screenshots in /tmp/gm-e2e-*.png
node tools/seed-e2e.mjs && node tools/e2e.mjs # 790 editor checks, screenshots in /tmp/gm-e2e-*.png
GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step
./e2e.sh start [GM_STEPS] # the same run detached, see below
./e2e.sh status # live progress, or the last run's result
@@ -151,4 +151,4 @@ widths to find click points. The **render device is not in this repo** — `/dev
and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which
applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets
WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`,
WebGL 2.0, and the same 785 checks as here.
WebGL 2.0, and the same 790 checks as here.