LearnNewsExamplesServices
Frontmatter
id18043
titleTrim the inline tab header: title weight token, size and horizontal padding
stateClosed
labels
enhancementdesignaicore
assigneesneo-fable
createdAtSep 1, 2026, 11:05 PM
updatedAtSep 2, 2026, 12:28 AM
githubUrlhttps://github.com/neomjs/neo/issues/18043
authorneo-fable
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 2, 2026, 12:28 AM

Trim the inline tab header: title weight token, size and horizontal padding

Closed v13.2.0/archive-v13-2-0-chunk-17 enhancementdesignaicore
neo-fable
neo-fable commented on Sep 1, 2026, 11:05 PM

Context

Operator direction 2026-09-01, after the narrow-header finding on the Workstation: rather than an actions overflow, challenge the ui: 'inline' tab header itself — the horizontal padding is too much, the title is too big, and it should not be bold. Users can drag the splitter for the rest.

Live latest-open sweep: checked the latest 20 open issues at 2026-09-01T21:03:06Z, the last 30 A2A messages (all read-states), and the Knowledge Base ticket corpus; no equivalent. #17950 (merged) introduced the inline/standalone variants; #18020 (merged) fixed the drag proxy's density; neither touched title typography.

Body update 2026-09-01T22:20Z (author, PR #18048 round 1): the weight token's fallback row below was wrong as first written — an undefined custom property makes the declaration invalid at computed-value time and the title inherits the document's weight, it does not fall back to anything. The consumption site now carries the fallback explicitly, so the row is true by construction; a fifth engine theme without tab tokens (theme-cyberpunk) is the case that made it matter. Found by Grace.

The Problem

Measured on the Workstation (neo-dark theme, the "Queues" pane, header 180px wide, focus-revealed rail):

Surface Today
inline tab button padding 4px 12px 3px (--tab-button-padding: 4px var(--sem-spacing-small) 3px)
title font size 16px (--tab-button-text-font-size → --sem-typo-label-regular-fontSize → --core-fontsize-body)
title font weight 600 — inherited from --button-text-font-weight (--core-fontweight-semibold), because the tab header stylesheet sets a size token and no weight token
action cluster 5 × 24px + 1px spacer = 121px
what the title gets the tab overflow plugin caps the active tab to the usable 59px → a 36px text box → "Q…"

"Queues" at 16px/600 needs 59px. Any one lever alone does not fit that case; the three together do: at 13px/400 the title needs ~45px, and 8px horizontal padding leaves it 44px. The rail is focus-transient, so this is about the focused state reading well, not about reserving space for it.

The Architectural Reality

  • resources/scss/src/tab/header/Button.scss paints .neo-button-text with font-size: var(--tab-button-text-font-size) only; the weight falls through to the generic button rule (src/button/Base.scss, var(--button-text-font-weight)). Every theme that sets a semibold button weight therefore sets semibold tab titles by accident.
  • The inline variant's padding lives per theme in the neo-tab-container-inline blocks: neo themes 4px var(--sem-spacing-small) 3px, classic themes 7px 10px 6px (resources/scss/theme-*/tab/Container.scss).
  • Emphasis for the active tab already has two carriers that cost no width: the indicator bar (--tab-strip-height) and the Workstation's full-ink pressed color.
  • The active-tab cap is the overflow plugin's contract (src/tab/plugin/Overflow.mjs#applySplit), not a defect; it stays.
  • Five themes build, four declare tab tokens. theme-cyberpunk is a first-class build target with no tab/ directory: --tab-button-text-color and --tab-button-text-font-size are already undefined there and those two properties already inherit. A new tab-level font-weight rule at (0,3,0) outranks the button rule at (0,2,0), so without a fallback an undefined weight token would take away the one title property cyberpunk still got right.

The Fix

  1. Add --tab-button-text-font-weight as the tab title's weight authority: declared in the four engine theme files with today's effective value (var(--button-text-font-weight), by reference), consumed in src/tab/header/Button.scss on .neo-button-text with the button family's weight as the var() fallback. No visual change for ui: null and standalone, in any theme — including one that declares no tab tokens.
  2. In the inline variant blocks (all four engine themes), set the trimmed values: regular weight, a smaller size (neo themes: a new label-small step, --core-fontsize-small → --sem-typo-label-small-*; classic: the existing 11px is already small enough), and 8px horizontal padding (--sem-spacing-xsmall in the neo themes). The label-small step is declared as the full family/size/weight triple like the existing label steps — that is the design-token rule, so the family token is not dead weight.
  3. The Workstation inherits the engine tokens; if its density wants a different step, it sets the token in its own Viewport stylesheet — no engine special-casing.
  4. Screenshot receipts for operator acceptance: the "Queues" header at 180px, focused, before and after; one non-inline tab container to prove byte-identity.

Contract Ledger

Target surface Source of authority Proposed behavior Fallback Docs Evidence
--tab-button-text-font-weight (new token) resources/scss/src/tab/header/Button.scss + the four theme tab/header/Button.scss files sole weight authority for tab titles; inline variant overrides it to regular absent → the button family's weight (--button-text-font-weight) through the consumption-site var() fallback; a theme with no tab tokens (cyberpunk) keeps its titles byte-identical theme token comment component paint spec, incl. a no-tab-tokens theme arm
inline variant padding + size resources/scss/theme-*/tab/Container.scss inline blocks 8px horizontal, one size step smaller none same component paint spec + screenshots

Decision Record impact: none (ADR 0029 does not govern tab typography).

Acceptance Criteria

  • A --tab-button-text-font-weight token exists in all four engine themes and is the only rule deciding a tab title's weight; ui: null and standalone containers render byte-identical to before (computed size, weight, padding compared in test/playwright/component/tab/ContainerUi.spec.mjs), and a theme that declares no tab tokens keeps the button family's weight through the fallback.
  • The inline variant renders titles at regular weight, one size step smaller than today, with 8px horizontal padding, in all four engine themes.
  • On the Workstation, the "Queues" header at its default 180px shows the full title while focused with the engine rail revealed (screenshot receipt before/after).
  • The drag proxy for an inline header (#18020) keeps the same density as the header it left.
  • Operator visual acceptance on the screenshots.

Out of Scope

  • An actions overflow control for narrow headers (rejected for now: the rail is focus-transient and the splitter is the honest fix).
  • The overflow plugin's active-tab cap.
  • The standalone variant's geometry.
  • theme-cyberpunk's missing tab tokens for color and size (pre-existing: those two properties already inherit there today; this ticket only guarantees it loses nothing further).

Avoided Traps

  • Fixing the Workstation only in its own stylesheet — the leak is an engine token gap and every consumer inherits it.
  • Reducing --tab-header-action-size to buy width — 24px is already the minimum honest hit target.
  • Declaring the new token as a literal in the theme files — the identity with the button family would then hold only as of today; by reference it survives a future retune.
  • Consuming the token without a fallback — a theme that never opted into tab tokens would have its titles regress silently, invisible to a four-theme matrix.

Related

Refs #17836 · #17950 (variants) · #18020 (proxy density) · #18039 (the finding's origin)

Origin Session ID: 6197a12f-acf2-478a-b05d-4ece32474259

Retrieval Hint: "inline tab header title weight token font-size padding trim narrow header cyberpunk fallback"

— Mnemosyne (Claude Fable 5.1 · Claude Code) · session 6197a12f-acf2-478a-b05d-4ece32474259 🪢