LearnNewsExamplesServices
Frontmatter
id19983
titleOption to reveal a dock pane's focus-gated header actions on hover
stateClosed
labels
enhancementaidashboard
assigneesneo-gemini-julia
createdAtOct 22, 2026, 11:04 AM
updatedAtOct 23, 2026, 12:53 AM
githubUrlhttps://github.com/neomjs/neo/issues/19983
authorneo-opus-ada
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtOct 23, 2026, 12:53 AM
milestonev13.3.1

Option to reveal a dock pane's focus-gated header actions on hover

Closed Backlog/active-chunk-10 enhancementaidashboard
neo-opus-ada
neo-opus-ada commented on Oct 22, 2026, 11:04 AM

Context

Dock pane headers gate their engine actions (lock, reload, pin, pop-out, maximize) and their host actions behind focus. Those actions appear only while the pane contains focus, so a pointer user has to click into a pane before seeing what it offers. This came up in manual testing of apps/workstation (see #19982 step 2). The request is an opt-in that also reveals the gated actions while the pointer is over the pane. Focus stays the default trigger.

The Problem

Focus is the only trigger that reveals the gated actions. That is right for keyboard users and for a quiet header, but it hides the pane's capabilities from a pointer user until they click. There is no configuration that reveals them on hover.

The Architectural Reality

  • src/toolbar/Base.mjs: contextualActionsVisible_ is derived from the focus subject's containsFocus. focusSubjectId resolves the subject; for a tab header that is the TabContainer, i.e. the whole pane. isFocusGatedAction() is showOnFocus === true && pressed !== true. applyContextualActionState() withholds an inactive gated action from the DOM (removeDom, inert, aria-hidden, tabIndex: -1) and publishes one owner update.
  • src/tab/header/Toolbar.mjs: actionDefaults: {showOnFocus: true}.
  • src/dashboard/dock/projection/LayoutAdapter.mjs: projects the engine action set with the focus-gating default, and already threads a hover opt-in for another surface (autoHideRevealOnHover, for auto-hidden rails). That is the precedent for a workspace-level option.
  • src/tab/plugin/Overflow.mjs: withheld actions contribute no extent, so revealing them shrinks the tab strip and re-partitions the tabs. Its comment calls that intended for focus changes.

The Fix

  1. toolbar.Base: add a second reveal trigger. A pointer entering or leaving the focus subject feeds the same contextualActionsVisible gate, so visible = focus OR hover OR pressed. It is off by default, so current behavior is unchanged. For the name, showOnHover (form.field.trigger.Base, default false) is the engine's existing spelling, and showOnFocus was named to match it (#17874).
  2. Dock: a workspace option, threaded through LayoutAdapter to every projected tab header in the style of autoHideRevealOnHover.
  3. Layout stability (required): with hover reveal on, the tab partition must not move when the pointer crosses a pane. Partition against the revealed action extent whenever the option is on, so tabs never jump into or out of the overflow menu under the pointer. Keyboard focus behaves as it does today.

Acceptance Criteria

  • The option is off by default. Existing toolbar, tab and dock specs stay green with no changes.
  • With the option on, the pointer entering a pane reveals its gated actions. Leaving hides them again, unless focus is inside the pane or the action is pressed.
  • With the option on, hovering into and out of a pane leaves its tab partition unchanged (the same visible-header set before, during and after).
  • Unit: the gate's truth table (focus × hover × pressed) on toolbar.Base.
  • E2E: a whitebox Neural Link spec under test/playwright/e2e/workstation/ turns the option on, moves a real pointer across a 12-tab pane, and asserts both the reveal and the stable partition.
  • JSDoc on the new config and workspace option, plus a line in the dock guide.

Contract Ledger

Backfilled by the ticket author during the review of #20011 (the ticket shipped without one).

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
Neo.toolbar.Base#showOnHover_ (new) Fix 1; spelling from Neo.form.field.trigger.Base#showOnHover true: the pointer over the focus subject (focusSubjectId, else parent) also reveals showOnFocus actions. Visible = focus OR hover; a pressed action stays revealed. Default false: focus-only, behavior unchanged. JSDoc HeaderActions.spec.mjs truth table
Neo.dashboard.dock.Workspace#headerActionsShowOnHover_ (new) Fix 2; precedent LayoutAdapter's autoHideRevealOnHover Sets showOnHover on every projected tab header toolbar; a runtime change reaches the live headers. Default false. JSDoc + DockLayoutsFeatures.md WorkstationHeaderActionsHoverNL.spec.mjs
LayoutAdapter.project(model, {headerActionsShowOnHover}) (new option) Fix 2 Sets showOnHover on each projected headerToolbar. Absent: false. One spelling, no alias. JSDoc DockLayoutAdapter.spec.mjs
Neo.tab.plugin.Overflow partition under owner.showOnHover Fix 3 With the option on, partition against the revealed action extent: the same visible-header set before, during and after a hover. Option off: today's behavior, a withheld action contributes no extent. JSDoc Overflow.spec.mjs arm + the e2e above

Out of Scope

  • Changing the default trigger. Focus-only stays the default.
  • Whether Workstation ships with the option on. That is a product call once the option exists.
  • Touch input. It has no hover, so focus remains the trigger there.

Avoided Traps

  • Hover toggling the action cluster in the layout. This repartitions tabs on every pointer pass, so the header flaps under the cursor. A focus-driven repartition was accepted in #18015, but focus changes on a click; hover changes on every pass. That is why the third Fix item is required, not optional.
  • A CSS-only :hover rule. Inactive gated actions are withheld from the DOM (removeDom), not hidden by style, so there is nothing for CSS to reveal. The state has to go through the existing gate.

Related

  • #19982: the bug found in the same testing pass; step 2 is the focus reveal.
  • #17874: introduced showOnFocus and the containsFocus gate. #18015 made inactive actions collapse.
  • autoHideRevealOnHover: the existing hover-option precedent in LayoutAdapter.

Live latest-open sweep: checked latest 20 open issues at 2026-10-22T09:04:47Z; no equivalent found. A2A claim sweep: no overlapping lane-claim. MC sweep: "show focus-gated dock header actions on hover…", 6 results; prior art #17874 / #18015 / #17876, and no decision against a hover trigger. GitHub search "header actions hover" / "showOnFocus" / "contextual actions focus": all closed, none equivalent. Own-assignment sweep: 6 open, none overlapping.

unowned-rationale: an opt-in enhancement queued behind the Workstation bug batch (#19982 and its siblings); no release goal names it yet.

Origin Session ID: 70e59a84-efd6-4e7a-9262-c5478bd314ff Retrieval Hint: "reveal focus-gated dock header actions on hover, showOnFocus, contextualActionsVisible"

tobiu referenced in commit 1f75a8b - "feat(dock): add option to reveal focus-gated header actions on hover (#19983) (#20011) on Oct 23, 2026, 12:53 AM
tobiu closed this issue on Oct 23, 2026, 12:53 AM