LearnNewsExamplesServices
Frontmatter
id18095
titleThe inline tab header band stays a gradient in the neo themes
stateClosed
labels
enhancementaicore
assigneesneo-opus-vega
createdAtSep 2, 2026, 4:02 PM
updatedAtSep 2, 2026, 4:39 PM
githubUrlhttps://github.com/neomjs/neo/issues/18095
authorneo-opus-vega
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 2, 2026, 4:39 PM

The inline tab header band stays a gradient in the neo themes

Closed v13.2.0/archive-v13-2-0-chunk-18 enhancementaicore
neo-opus-vega
neo-opus-vega commented on Sep 2, 2026, 4:02 PM

Context

The ui: 'inline' design pass for dock tab headers (#17950 variants, #17963 header actions, #18043 title weight and trim, #18048) left one value untouched: the header's band. theme-neo-dark/tab/Container.scss:10-14 and its neo-light twin value --tab-header-inline-background-image as a 180° gradient from --sem-color-surface-neutral-highlighted to --sem-color-surface-neutral-default — in neo-dark that resolves to gray-800 #292D28 → gray-900 #0E0F0D, an olive-tinted ramp; in neo-light to white → #fafafa. src/tab/Container.scss:1-7 paints it (&.neo-tab-container-inline > .neo-tab-header-toolbar { background-image: var(--tab-header-inline-background-image, none) }), and the header owns nothing else: src/tab/header/Toolbar.scss:2 is background-color: transparent, no border, no color token.

The operator (2026-09-02) saw the ramp on a consumer's dock panes and named it as not fitting the app; he had assumed the inline pass flattened it. It did — for one app. resources/scss/src/apps/workstation/Viewport.scss:74-84 re-values the hook with the Workstation's own two panel colors and explains why: "The neo themes value this hook with a neutral olive ramp; painted over this instrument's blue-slate panel it read as a foreign surface" — then sets the header's background-color longhand and a border-bottom line separately (:196-204), noting the shorthand fights the engine rule. The flagship app rejects the default; every other host inherits it.

Sibling, same family (defaults lag the apps' overrides): #18080 — the engine's default reveal chrome vanishes on a dark ground while the Workstation and the cockpit override it.

The Problem

The default should be the good default. A consumer that adopts enableDock*Action and ui: 'inline' gets the engine's density and action chrome for free, then still has to discover one token to stop the band reading as a gradient over its surfaces — and has NO token at all for the header's own color or its separating line, because the inline header carries neither. The Workstation's answer (its own palette + longhand background + border) is the shape the theme should offer as its baseline: a flat header surface and a hairline, valued from semantic tokens, with the gradient hook kept for consumers who want one.

The Architectural Reality

  • resources/scss/theme-neo-dark/tab/Container.scss:1-14 and resources/scss/theme-neo-light/tab/Container.scss:10-14 — the inline band token; the same sheets already carry the inline density tier (--tab-button-height: var(--sem-height-large) etc.).
  • resources/scss/src/tab/Container.scss:1-7 — the variant selector that paints the band; the comment there names it "the public inline-header hook".
  • resources/scss/src/tab/header/Toolbar.scss:2 — the toolbar's own paint is transparent; actions (:12-49) keep their tokens.
  • resources/scss/theme-neo-dark/design-tokens/Semantic.scss:18,31,32 — --sem-color-border-default: var(--gray-700), --sem-color-surface-neutral-default: var(--gray-900), --sem-color-surface-neutral-highlighted: var(--gray-800); neo-light :18,31,32 — gray-200, gray-50, white.
  • resources/scss/src/apps/workstation/Viewport.scss:70-84, 196-204 — the Workstation's override (its own palette; stays).
  • buildScripts/util/check-theme-coverage.mjs — values must land in BOTH neo themes.
  • Screenshots that contain an inline header: test/playwright/e2e/dashboard/DockPinCollapseNL.spec.mjs:281-315 (eight darwin reveal-pin-<theme>-{enabled,disabled}.png, re-recorded by PR #18090 for #18089 today); test/playwright/visual/PreviewLanguageVisual.spec.mjs:115,131 (to be checked at implementation).

The Fix

  1. Both neo themes (tab/Container.scss, same block that owns the inline tokens): --tab-header-inline-background-image: none (the hook stays a public token — consumers who want a gradient keep valuing it); add --tab-header-inline-background-color: var(--sem-color-surface-neutral-highlighted) and --tab-header-inline-box-shadow: inset 0 -1px 0 var(--sem-color-border-default).
  2. src/tab/Container.scss inline rule paints the header from those tokens with transparent fallbacks, so the legacy themes and every other host stay byte-identical: background-color: var(--tab-header-inline-background-color, transparent), the existing background-image hook, and the hairline as box-shadow: var(--tab-header-inline-box-shadow, none) — one whole-value token (a colour-inside-a-fixed-shadow fallback still computes to a transparent shadow STRING on the legacy themes, not none), an inset shadow, NOT border-bottom, so the header's box does not grow by a pixel under the zero-gap geometry (#18015) and no height-asserting spec moves.
  3. Workstation: its override keeps winning on its own palette; the comment that calls the theme value an olive ramp is corrected to name the new baseline.
  4. Witness: a component paint spec in the DockRailTabPaint idiom (computed styles on a rendered inline header, both neo themes, with a control): the inline header's background-image is none, its background-color equals the resolved --sem-color-surface-neutral-highlighted, the inset line is present — and a standalone (ui: null) header keeps its established paint. Red-first on dev: the computed background-image is the gradient.
  5. Baselines: the eight DockPinCollapseNL reveal-pin PNGs show the inline header and change with the band. They are re-recorded in this PR after #18090 merges (sequencing: #18090 first, then this), or, if this lands first, #18090's images are re-recorded once more — either way one recording against the final band.

Acceptance Criteria

  • AC-1 theme-neo-dark and theme-neo-light tab/Container.scss value --tab-header-inline-background-image: none, --tab-header-inline-background-color and --tab-header-inline-box-shadow from semantic tokens; check-theme-coverage stays green.
  • AC-2 src/tab/Container.scss paints the inline header's color and inset hairline from the tokens with transparent fallbacks; theme-dark, theme-light, theme-cyberpunk compile to unchanged inline-header paint (no tokens → transparent/none).
  • AC-3 Component paint witness, both neo themes: background-image none, background-color = resolved --sem-color-surface-neutral-highlighted, hairline present as the inset shadow; standalone header control unchanged; red-first on dev.
  • AC-4 The Workstation's inline headers are byte-identical before/after (its override wins); its comment names the new baseline.
  • AC-5 DockPinCollapseNL reveal-pin baselines recorded against the flat band in the order stated in Fix 5; PreviewLanguageVisual checked and re-recorded only if an inline header is in frame.
  • AC-6 components + unit/dashboard suites green at head.

Out of Scope

  • Brand or overlay themes (a token-only theme riding another theme's sheets) — the primitive a consumer brand theme needs; ideation-sandbox material, not this leaf.
  • #18080 (default reveal chrome on a dark ground) — sibling, separate.
  • The legacy theme-dark / theme-light — they carry no inline tokens and keep their paint.
  • Promoting the Workstation palette itself into a theme.

Avoided Traps

  • border-bottom for the hairline — grows the header box by 1 px under the zero-gap geometry and moves every height-asserting spec; the inset box-shadow paints the same line at zero layout cost.
  • background shorthand — its implicit background-image: none fights the higher-specificity engine rule (the Workstation learned this at Viewport.scss:196-204); longhands only.
  • Removing the gradient hook — consumers (the Workstation included) value it; the default becomes none, the token stays public.
  • Re-recording baselines before #18090 lands — two PRs racing on the same eight PNGs; sequence, record once.

Related

Live latest-open sweep: checked the latest 20 open issues at 2026-09-02T14:00Z; no equivalent found. A2A claim sweep (last 30 messages, all read-states): no overlapping [lane-claim].

Origin Session ID: 87c91db1-7fcd-4987-9932-2bf78d3dda25

Retrieval Hint: "inline tab header band gradient neo theme flat surface hairline token"

tobiu referenced in commit 4e0e9dd - "feat(tab): the inline header paints a flat surface with a hairline in the neo themes (#18095) (#18097)" on Sep 2, 2026, 4:39 PM
tobiu closed this issue on Sep 2, 2026, 4:39 PM
tobiu referenced in commit 20dab0c - "fix(tab): every theme states the inline header's paint, because a fallback is not a reset (#18141) (#18144) on Sep 3, 2026, 12:49 AM