LearnNewsExamplesServices
Frontmatter
id17963
titleDock pane header actions wear stock button chrome — a design pass for the four themes
stateClosed
labels
enhancementdesignaicore
assigneesneo-gpt-emmy
createdAtAug 31, 2026, 7:43 PM
updatedAtAug 31, 2026, 11:15 PM
githubUrlhttps://github.com/neomjs/neo/issues/17963
authorneo-opus-vega
commentsCount2
parentIssue13158
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 31, 2026, 11:15 PM

Dock pane header actions wear stock button chrome — a design pass for the four themes

Closed v13.2.0/archive-v13-2-0-chunk-17 enhancementdesignaicore
neo-opus-vega
neo-opus-vega commented on Aug 31, 2026, 7:43 PM

Context

The pane-header action family under epic #13158 shipped its semantics this cycle — close, pin, maximize (#17952/#17953) and the overflow-as-first-action (#17960) — and #17956 shipped the ui: 'inline' | 'standalone' container variants with per-theme sheets. What never shipped, and was never ticketed, is the visual design of the actions themselves plus the theme values the inline variant reserved room for. The reference bar is the Qt-parity pane header: a compact cluster of flat monochrome glyphs sharing the strip's band, close at the corner — not a row of standalone buttons.

The Problem

Measured at Engine dev@9954179bb7 (post all four family merges):

  • The only action-specific CSS in the entire tree is the focus-gating carrier (.neo-toolbar-action-context-inactive, resources/scss/src/toolbar/Base.scss). Every projected header action renders as a stock neo-button in whatever the active theme's default button chrome is — in the neo themes that is a large filled rounded button, visually dominating the header band it sits in. Witnessed in the dock-maximize component fixture (neo-theme-neo-dark: filled square buttons for close/maximize) and in apps/workstation (the #17960 overflow control renders as a generic bordered button on the "Priority Alert Observatory" pane).
  • The inline gradient hook has no values. #17950 froze --tab-header-inline-background-image, consumed as background-image: var(--tab-header-inline-background-image, none) on .neo-tab-container-inline > .neo-tab-header-toolbar (resources/scss/src/tab/Container.scss:6) — and no theme value layer sets it, so the none default renders everywhere. The hook satisfied its ticket's ACs; the design (a subtle band gradient for dense pane headers) was deliberately left to a values pass that has no ticket.
  • apps/workstation never enables the engine actions. The engine's own showcase inherits the inline chrome (six inline containers render today) but projects no close/pin/maximize — so the chrome this ticket designs has no living witness in a public app until the flags turn on there.

The Architectural Reality

  • Action items are addressable: every projected action carries cls: 'neo-toolbar-action' and isToolbarAction: true (src/toolbar/Base.mjs:373,391); contributions add isToolbarActionContribution (#17960). The chrome selector is therefore .neo-tab-header-toolbar .neo-toolbar-action (scoped to tab headers so ordinary toolbars keep their button chrome), with the gating carrier already handling shown/hidden interactivity.
  • The four theme value layers exist and already carry tab sheets (resources/scss/theme-{light,dark,neo-light,neo-dark}/tab/Container.scss, extended by #17956) — the values land beside the variant styling they complete.
  • The engine set is focus-gated by default; whatever hover/rest states the design chooses must keep the gated state's geometry-preserving discipline (the carrier toggles interactivity, not layout).

The Fix

One SCSS-plus-witness pass, no JS behavior changes:

  1. Action glyph chrome for .neo-tab-header-toolbar .neo-toolbar-action in the structural sheet (compact hit target, transparent rest background, glyph-first) with per-theme values in all four theme layers (glyph color, hover/active surfaces, close-affordance accent if the theme language wants one). The Qt-parity read: actions share the header band, they do not sit on it as buttons.
  2. Inline gradient values: set --tab-header-inline-background-image in the two neo themes (the dense-pane band the hook was frozen for); the classic themes may opt for none deliberately — a written choice, not an accident of the default.
  3. apps/workstation enables enableDockCloseAction, enableDockPinAction, enableDockMaximizeAction — the engine's showcase becomes the living witness for the chrome across both neo themes and exercises the full frozen ordering: [overflow] → [engine set, focus-gated] → [close, always last].

Contract Ledger

Target Surface Source of Authority Behavior Fallback Docs Evidence
.neo-tab-header-toolbar .neo-toolbar-action src/toolbar/Base.mjs action marker + tab-header scope compact glyph-first chrome only inside tab headers; ordinary toolbars stay unchanged existing stock button chrome outside the selector structural SCSS intent comment selector-contract spec + per-theme visual receipt
--tab-header-inline-background-image #17950 / merged #17956 hook real band gradient in both neo themes classic themes explicitly declare none per-theme inline-variant comment computed-style assertion in all four themes
Workstation enableDockCloseAction / enableDockPinAction / enableDockMaximizeAction dashboard.dock.Workspace public configs showcase projects the frozen engine action set and ordering flags remain opt-in elsewhere Workstation config rationale dense-tour + action-order/focus-gating witness
gated action state neo-toolbar-action-context-inactive carrier geometry preserved; quiet and non-interactive under the new chrome existing hidden-carrier semantics no new public docs focused/unfocused rect stability + visual receipt

The ledger changes visual/value and host opt-in surfaces only. It does not reopen action semantics. Classic-theme none is an explicit value, not reliance on the structural fallback.

Acceptance Criteria

  • Header actions in tab headers render glyph-first compact chrome, visually distinct from standalone buttons, in all four themes (visual evidence beat per the epic's closure-gate discipline: recorded comparison or screenshot pair per theme).
  • Ordinary (non-tab-header) toolbars keep today's action rendering byte-identically — the chrome is scoped to .neo-tab-header-toolbar (regression spec on the cls contract).
  • The two neo themes set a real --tab-header-inline-background-image value; the classic themes' choice is written in their sheets as a deliberate line (value or documented none).
  • apps/workstation projects close, pin and maximize; the dense tour still passes; the focus-gating carrier's geometry-preserving behavior is unchanged (no layout shift when actions gate in/out).
  • The gated (context-inactive) state remains visually quiet under the new chrome in all four themes.

Out of Scope

  • Any action semantics, ordering, or gating behavior — all frozen and shipped by the family leaves.
  • Redesigning the two ui variants themselves (#17956 owns that shape); this ticket only supplies the values and the action chrome those variants were built to host.
  • The private consumer workspaces — they inherit whatever the themes ship.

Related

Parent: #13158. Completes the design half of: #17950/#17956 (variants + hook), #17952 (pin), #17953 (maximize), #17960 (overflow-as-action). Reference precedent for gated-state mechanics: resources/scss/src/toolbar/Base.scss.

Origin Session ID: 914dffcd-0057-46a5-a0c6-9ca807fd5c91

Retrieval Hint: "dock header action glyph chrome four themes gradient values workstation witness"

— Vega (Fable 5, Claude Code) 🌿

tobiu cross-referenced by PR #17975 on Aug 31, 2026, 10:03 PM