Skip to content

Add an admin-bar presentation mode to OS Settings and the theme system - #458

Merged
AllTerrainDeveloper merged 1 commit into
trunkfrom
add/admin-bar-mode-setting
Jul 30, 2026
Merged

Add an admin-bar presentation mode to OS Settings and the theme system#458
AllTerrainDeveloper merged 1 commit into
trunkfrom
add/admin-bar-mode-setting

Conversation

@AllTerrainDeveloper

@AllTerrainDeveloper AllTerrainDeveloper commented Jul 30, 2026

Copy link
Copy Markdown
Collaborator

Adds adminBarMode — a Static / Dynamic / Hidden tristate in OS Settings → Appearance, modeled on the existing Window corners control, controlling how the WordPress admin bar presents above the shell.

Screen.Recording.2026-07-30.at.17.36.04.mov
Mode Behavior
Static (default) Pinned above the shell, shell starts below it. Vanilla behavior.
Dynamic Parks off the top edge behind a 4px seam, slides back in when the pointer reaches the top of the viewport or something inside it takes keyboard focus. Shell takes the full viewport.
Hidden Not rendered. Shell takes the full viewport.

How the mode reaches CSS

A desktop-mode-admin-bar-<mode> body class, written twice on purpose:

  • PHP, on admin_body_class — the admin bar paints long before the shell's JS boots, so without this a hidden user would see it flash on every navigation.
  • The shell's apply pass — this is what makes a pick in OS Settings take effect without a reload.

Why transform, and why the hit area is bigger than the seam

dynamic moves the bar with transform rather than repositioning it, because a transformed element keeps hit-testing at its painted position — the parked remainder stops catching the pointer the moment it goes off-screen.

That alone would make the seam and the pointer target the same 4px, which is a miserable thing to aim at. So an invisible #wpadminbar::after extends the hit area 16px below the parked bar — hovering a pseudo-element counts as hovering its originating element, so :hover fires across a 20px band from the top of the viewport while the seam stays a hairline. The zone collapses to 0 once the bar is out, so it can't swallow clicks on windows underneath; it's also what keeps the reveal stable, since post-reveal the pointer is inside the bar's real box.

Both distances are tokens on :root:

Token Default
--desktop-mode-admin-bar-peek 4px (visible seam)
--desktop-mode-admin-bar-reveal-zone 16px (invisible extension)

There's a ceiling on the second one, documented on the token: peek + reveal-zone must stay under the bar's own height (32px, 46px below 783px). Past that, leaving the revealed bar drops the pointer back into the zone, which re-reveals it — an oscillation loop rather than a wider target. Coarse pointers get 10px + 20px and reveal on :active.

Verified against the running WordPress that core ships no bare #wpadminbar::before/::after (278 #wpadminbar rules, none of them that) and that its five overflow: hidden rules are all on descendants, so nothing clips the zone.

hidden is not a one-way door

It removes the admin bar's "Switch to Classic Admin" toggle, but the dock's core rail always carries an Exit Desktop Mode tile hitting the same save-desktop-mode endpoint, and system tiles aren't reachable by itemVisibility (that only filters menu items and desktop icons). The desktop.css comment claiming the admin bar is "the ONLY escape hatch" was already stale; that dependency is now called out in the CSS, the hooks reference, and the section's own helper copy. If system tiles ever become hideable, hidden becomes a trap.

Extensibility

  • ThemesadminBarMode is a recommendedOsSettings key (static|dynamic|hidden), wired through both halves of the enum mirror (desktop_mode_desktop_theme_recommended_os_settings_schema() and src/desktop-themes/recommended.ts). Usual once-per-user contract: it never overwrites a later choice. A theme wanting an edge-to-edge desk recommends dynamic.
  • Plugins — new Stable filter desktop_mode_admin_bar_mode pins the mode per request (kiosk hidden, or forcing static for users who shouldn't lose the toggle). Out-of-enum and non-string returns fail closed to static, deliberately without a (string) cast so an array return can't emit an "Array to string conversion" warning on its way to failing anyway.

Known trade-off

In dynamic mode the top ~20px of the desktop is reveal territory. That's inherent to auto-hide UI (Windows does the same at the bottom edge) and no worse in practice than the old 4px, since hovering brings out a bar that covers 32px regardless. Window drags are naturally immune — setPointerCapture routes events to the dragged window, so #wpadminbar:hover doesn't fire mid-drag.

Docs

hooks-reference.md (new filter entry + the recommendation-schema count), javascript-reference.md (snapshot key, apply-live list, RecommendedOsSettings table), desktop-themes.md (fields table + manifest example).

Testing

npm run build, lint, typecheck, test:js (2538 tests) and the full PHPUnit suite (1687 tests) all pass. The one CSS minify warning is pre-existing in widget-drafts.css, untouched here.

New coverage:

  • tests/vitest/os-settings-admin-bar-mode.test.ts — class exclusivity across modes, switching clears the previous class, default, unknown-value fallback at deserialization (not just paint), snapshot exposure.
  • desktopModeRender.php — body class carries the default and the saved mode, omitted when desktop mode is off, filter override, filter-result validation.
  • osSettings.php — sanitizer round-trip plus the two fallback paths.
  • desktop-themes-recommended.test.ts — every mode accepted, unknown mode drops, updated key-list assertion.

Manual QA

  1. Reload the shell, open OS Settings → Appearance, scroll past Window corners.
  2. Dynamic → seam should stay a hairline, but the bar should come out well before the pointer touches it. Tab into it to confirm keyboard reveal.
  3. Hidden → bar gone, desktop flush to the top; confirm the Exit Desktop Mode dock tile still gets you out.
  4. Hard-reload on each mode — no flash of the bar before the shell boots.
  5. Fullscreen a window in each mode; behavior should be unchanged.

🤖 Generated with Claude Code

https://claude.ai/code/session_015sKW1mu1SGg5k9oSHgxv5s

Open WordPress Playground Preview

Adds `adminBarMode` — a Static / Dynamic / Hidden tristate in
OS Settings → Appearance, modeled on the existing Window corners
control, controlling how the WordPress admin bar presents above the
shell.

- `static`  — pinned above the shell. Vanilla behavior, and the default.
- `dynamic` — parks off the top edge behind a 4px seam and slides back
              in when the pointer reaches the top of the viewport or
              something inside it takes keyboard focus. Classic Windows
              auto-hide taskbar.
- `hidden`  — not rendered at all.

The mode reaches CSS as a `desktop-mode-admin-bar-<mode>` body class,
written twice on purpose: PHP emits it on `admin_body_class` so the
first paint is already correct (the bar has painted long before the
shell's JS boots, so a `hidden` user would otherwise see it flash on
every navigation), and the shell's apply pass re-writes it so a pick
in OS Settings takes effect without a reload.

`dynamic` uses `transform` rather than repositioning, because a
transformed element keeps hit-testing at its painted position — the
parked remainder stops catching the pointer the moment it goes
off-screen. The pointer target is deliberately larger than the visible
seam: an invisible `#wpadminbar::after` extends the hit area 16px below
the parked bar (hovering a pseudo-element counts as hovering its
originating element), giving a 20px band from the top of the viewport
while the seam stays a hairline. The zone collapses to 0 once the bar
is out, so it can't swallow clicks on windows underneath. Both
distances are tokens (`--desktop-mode-admin-bar-peek` and
`--desktop-mode-admin-bar-reveal-zone`) with the oscillation ceiling
documented on the latter.

`hidden` removes the admin bar's "Switch to Classic Admin" toggle, but
is not a one-way door: the dock's core rail always carries an "Exit
Desktop Mode" tile hitting the same endpoint, and system tiles aren't
reachable by `itemVisibility`. That dependency is called out in the
CSS, the hooks reference, and the section's own helper copy.

Surfaced to themes as a `recommendedOsSettings` key, wired through both
halves of the enum mirror, and to plugins as a new `Stable` filter,
`desktop_mode_admin_bar_mode`, for pinning the mode per request (kiosk
`hidden`, or forcing `static` for users who shouldn't lose the toggle).
Out-of-enum and non-string filter returns fail closed to `static`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sKW1mu1SGg5k9oSHgxv5s
@AllTerrainDeveloper
AllTerrainDeveloper merged commit 8514fdb into trunk Jul 30, 2026
5 checks passed
@AllTerrainDeveloper
AllTerrainDeveloper deleted the add/admin-bar-mode-setting branch July 30, 2026 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant