Skip to content

fix: hidden sidebars slide off-screen and take no input - #594

Open
maccavelli wants to merge 1 commit into
macosui:devfrom
maccavelli:fix/hidden-sidebar-off-screen
Open

maccavelli wants to merge 1 commit into
macosui:devfrom
maccavelli:fix/hidden-sidebar-off-screen

Conversation

@maccavelli

Copy link
Copy Markdown

Fixes #593.

A hidden start Sidebar stayed at the window's leading edge beneath the content, still painted,
hit-testable, focusable and in the semantics tree. It showed wherever the content paints no
background. A hidden end Sidebar slid off-screen, but could still take keyboard focus.

What changes (lib/src/layout/window.dart only; no public API change):

  • The start sidebar's AnimatedPositioned gets left: visibleSidebarWidth - _sidebarWidth, so
    hiding slides it off the leading edge, animated with the content, as the end sidebar does.
  • While a sidebar is not shown, its subtree is wrapped in IgnorePointer, ExcludeFocus and
    ExcludeSemantics, keyed on !canShowSidebar and !canShowEndSidebar. At rest, off-screen
    plus the Stack clip already keeps a sidebar out of hit testing and semantics. The wrappers
    also cover the 300 ms toggle slide, while it is still partly visible. For focus, they are the
    only thing that keeps a hidden sidebar out.
  • Version 2.2.4 and a CHANGELOG entry.

Most of the window.dart diff is re-indentation under the new wrappers. With whitespace
hidden, it is +34 −3.

The native visual-effect view follows without any extra wiring: the toggler's setState after
the slide rebuilds TransparentMacOSSidebar at its final position, and resizing or dragging
rebuilds every frame. This was checked on a device, with and without an explicit
VisualEffectSubviewContainerResizeEventRelay, and the two builds measured the same in all 10
captures, so the patch does not add one.

Before / after, toggled off, with the window background transparent and then opaque (the
issue's sample, plus a label naming the build)

In every hidden state, measured on window captures:

  • before: about 5,000 label pixels, and, with a transparent background, the material's colour;
  • after: 0, and the background's colour.

When the sidebar is shown again, its material is back behind it.

Tests (test/layout/window_test.dart, 10 new; the 16 existing ones are unchanged and pass):

  • Start sidebar:
    • shown (on-screen and taking input);
    • hidden by the breakpoint, the toggle (and back on) and a drag-close: off-screen, not
      hit-testable, not focusable, absent from the live semantics tree;
    • mid-slide: not hit-testable and absent from semantics while still partly visible.
  • End sidebar: the same five.
  • Semantics are read with find.semantics.byLabel, which searches the live tree.
    find.bySemanticsLabel still reports a node after ExcludeSemantics starts excluding it.
  • On dev without the change, each of the 8 hidden-state and mid-slide tests fails, and the 2
    shown-state controls pass.
  • Removing any one of the seven changes (left, and each of the three wrappers on each sidebar)
    fails at least one new test, on the assertion that change is responsible for.

Checked locally with Flutter 3.47.2 (stable), macOS 26.6.2, Xcode 27.0:

  • flutter analyze --fatal-infos .: no issues.
  • dart format --set-exit-if-changed on the changed files: clean.
  • dcm analyze --fatal-style . (DCM 1.39.2): no issues.
  • flutter test: all pass except 10 failures that are already on dev without this change. They
    are the "lerps from dark to light" and "lerps from light to dark" tests in
    test/theme/{help_button,icon_button,icon,popup_button,pulldown_button}_theme_test.dart. Tag
    2.2.2 fails the same 10 on this SDK.

Noticed along the way, and not changed here:

  • example/ does not build with Xcode 27: its deployment target is 10.14.6, and Xcode supports
    12.0 and later.
  • On this SDK, dart format would also change two files already on dev:
    lib/src/layout/sidebar/sidebar_items.dart and test/buttons/pulldown_button_test.dart.

Pre-launch Checklist

  • I have incremented the package version as appropriate and updated CHANGELOG.md with my changes
  • I have added/updated relevant documentation (not needed: no API or documented behaviour changes)
  • I have run "optimize/organize imports" on all changed files
  • I have addressed all analyzer warnings as best I could

🤖 Generated with Claude Code

https://claude.ai/code/session_01Qdd4Y9iCLirehsBoNyMp7R

- start sidebar now slides off leading edge (was left at x=0)
- wrap both sidebars in IgnorePointer/ExcludeFocus/ExcludeSemantics when hidden
- update tests for breakpoint, toggle, drag-close, and focus traversal
- bump to 2.2.4

# AI-generated (4 files: +501 -163)
# YAML: 1, Other: 3
@maccavelli

Copy link
Copy Markdown
Author
pr-594-1-before-transparent pr-594-2-after-transparent pr-594-3-before-opaque pr-594-4-after-opaque

This branch has not been deployed

No deployments
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.

A hidden start Sidebar stays on screen and takes input beneath the content; a hidden end Sidebar still takes focus

1 participant