Skip to content

fix(dock): make every dock scrollable, keep system tiles pinned#264

Merged
epeicher merged 2 commits into
trunkfrom
fix/dock-scroll-with-pinned-system-tiles
May 21, 2026
Merged

fix(dock): make every dock scrollable, keep system tiles pinned#264
epeicher merged 2 commits into
trunkfrom
fix/dock-scroll-with-pinned-system-tiles

Conversation

@epeicher
Copy link
Copy Markdown
Collaborator

@epeicher epeicher commented May 21, 2026

Summary

Sites with many CPTs + plugins routinely produce more menu tiles than fit the viewport. With a vertical dock (Classic layout's left side bar) the bottom tiles + system cluster get clipped off the bottom of the screen; with a horizontal dock (Unified / Spatial layouts) the trailing tiles get clipped off the right edge. Either way the user can't reach them.

This PR introduces an inner __scroll / __pinned wrapper pair on every dock so the menu area can scroll while the system tiles stay pinned at the trailing edge.

  • .desktop-mode-dock__scroll — scrollable; hosts menu tiles + the inline core/plugin separator. Scrollbar is hidden visually (scrollbar-width: none + WebKit pseudo) so the rail keeps its macOS look. Mouse wheel, touchpad, touch, and keyboard focus-into-view all work.
  • .desktop-mode-dock__pinned — sized to content; hosts the system separator + system tiles. Always visible at the trailing edge, regardless of scroll position.

Vertical placements (left / right) flow the wrappers as columns: __scroll takes the available height and scrolls vertically, __pinned sits at the bottom edge. The bottom placement flows them as rows: __scroll takes the available width and scrolls horizontally, __pinned sits at the trailing edge. The bottom pill's padding shifts from 8px 12px to 4px 12px 8px so __scroll has 4px internal top padding for badge clearance (the tile's badge sits at top: -3px); net vertical chrome is unchanged.

Drag-to-reorder, replaceItems, appendSystemItem, and removeSystemItem route through new itemHost / systemHost fields so the same code paths serve both shapes.

CleanShot.2026-05-21.at.18.54.11.mp4

Fixes #251.

Re: the second part of the issue ("optionally display the label next to the icon"). Intentionally not implemented. The dock is designed as a macOS-style icon strip; adding labels turns it into a sidebar (i.e. the native WP admin menu) and roughly quadruples its width, undoing the "more room for content" benefit of the desktop chrome. It also doesn't fit the bottom dock. If we want this it should ship as a separate `DockRailRenderer` (the extensibility point already exists in `src/dock-rail/`), not as a toggle on the default renderer.

Test plan

To reproduce overflow: a site with 25+ CPTs / plugin menus. Each layout exposes a different rail shape.

  • Left dock (Classic layout) — OS Settings → Desktop layout → Classic. Mouse-wheel / trackpad scroll over the side bar; menu area scrolls vertically, system tiles (Recycle Bin / OS Settings / Bug Report / Exit) stay pinned at the bottom of the rail.
  • Right dock — no built-in UI for this; from the console after switching to Classic, run `wp.desktop.sideDock?.setOrientation('right')` to flip the side bar to the right edge. Same behaviour, mirrored.
  • Bottom dock (Unified layout) — OS Settings → Desktop layout → Unified. Mouse-wheel / trackpad-horizontal-scroll over the dock pill; menu tiles scroll horizontally, system tiles stay pinned at the trailing edge. Badges on tiles are not clipped.
  • Bottom dock (Spatial layout) — same as Unified but with core menu items emitted as wallpaper icons; the bottom pill hosts only plugin menus. Horizontal scroll + pinned trailing cluster still behave correctly.
  • Classic with overflow on BOTH rails — left dock has many CPTs and bottom dock has many plugin menus; both rails scroll independently, both keep their pinned clusters.
  • Drag-to-reorder a menu tile inside the scrollable area on each layout.
  • Plugin activate / deactivate while the dock is scrolled — live refresh repaints menu tiles, system tiles unaffected, no stale separators.
  • Low-cap user (Subscriber role: no menu items, only system tiles) — no stray separator hairline next to the system cluster.
  • No visible scrollbar on any dock at any time.
Open WordPress Playground Preview

When the admin menu has more tiles than fit the viewport — common
with many CPTs + plugins — the later menu tiles plus the system
tiles (Recycle Bin, OS Settings, Exit, …) were clipped off the
bottom of the screen with no way to reach them.

Vertical placements (left/right) now build two inner wrappers in
the constructor:
  - `__scroll`  — flex: 1, scrollable, hosts menu tiles + the inline
                  core/plugin separator
  - `__pinned`  — sized to content, hosts the system separator + the
                  system tiles, always visible at the bottom

The system tiles stay reachable regardless of scroll position; the
menu area absorbs the overflow. Scrollbar is hidden visually
(`scrollbar-width: none` + `::-webkit-scrollbar { display: none }`)
so the rail keeps its clean macOS look. Mouse wheel, touchpad,
touch, and keyboard focus-into-view all work.

The bottom dock keeps its flat structure — no wrappers, no inner
scroll. Drag-to-reorder, `replaceItems`, `appendSystemItem`, and
`removeSystemItem` now route through `itemHost` / `systemHost`
fields so the same code paths serve both shapes.

Fixes #251
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 21, 2026

✅ WordPress Plugin Check Report

✅ Status: Passed

📊 Report

All checks passed! No errors or warnings found.


🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

The vertical-dock fix solved the "many CPTs" overflow for left and
right placements, but the bottom dock (Unified / Spatial layouts)
had the same problem horizontally — when the menu tiles' total
width exceeded the pill's `max-width: calc(100% - 32px)`, the
trailing tiles were clipped with no way to reach them.

Drop the bottom-dock special case in the constructor so every
orientation builds the same `__scroll` / `__pinned` wrappers. The
bottom-dock CSS lays them out horizontally:
  - `__scroll`  — `flex: 1 1 auto; min-width: 0`, hosts menu tiles,
                  scrolls horizontally with hidden scrollbar
  - `__pinned`  — `flex-shrink: 0`, hosts the system separator +
                  system tiles, anchored to the trailing edge

Pill padding shifts from `8px 12px` to `4px 12px 8px` to give
`__scroll` 4px of internal top padding for badge clearance
(`overflow-y: hidden` would otherwise crop the tile's
`top: -3px` badge). Net vertical chrome is unchanged — tile sits
8px from both pill edges, same as before.

With wrappers always on, the `insertMenuChild` helper's
"same-host" branch is dead code; collapsed to a plain appendChild.
The dock-decoration-hooks test that asserted "filter-wrapped tile
is a direct child of the dock" updated to the new structure —
the documented contract is unchanged ("wrap, don't replace"),
only the implementation detail of WHERE the wrapped element
lands moved.
@epeicher epeicher changed the title fix(dock): make vertical dock scrollable, keep system tiles pinned fix(dock): make every dock scrollable, keep system tiles pinned May 21, 2026
@epeicher epeicher enabled auto-merge (squash) May 21, 2026 16:57
@epeicher epeicher merged commit 5f9505b into trunk May 21, 2026
5 checks passed
@epeicher epeicher deleted the fix/dock-scroll-with-pinned-system-tiles branch May 21, 2026 17:03
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.

Dock on the left not scrollable

1 participant