Skip to content

fix(ui): make closed sidebars inert and return focus to their toggle - #248

Merged
iamnbutler merged 2 commits into
mainfrom
sidebar-inert
Oct 14, 2026
Merged

iamnbutler merged 2 commits into
mainfrom
sidebar-inert

Conversation

@iamnbutler

Copy link
Copy Markdown
Contributor

Fixes #44.

The shared Sidebar now sets aria-hidden and inert from its open state, so every left and right sidebar consumer gets the pattern the details sidebar used (removed from channel.tsx as redundant). The collapsed desktop left track keeps visibility: visible, so this can't come from CSS.

  • Focus on close: a layout effect in Sidebar hands focus to the control with aria-controls="<sidebar id>" when the sidebar closes with focus inside. The app's left sidebar gets id="sidebar", and the channels and issues/PRs toggles get aria-controls.
  • Resize grip: the grip now stays mounted (display-none) while closed. Before, unmounting it dropped focus to the body before the hand-off.
  • Compact overlay: the overlay's inert effect is now a layout effect, so main is no longer inert when focus moves to the toggle inside it. It also no longer saves and restores an open sidebar's own inert, which used to leave a just-closed overlay sidebar non-inert. Animation and CSS are unchanged.

Verification

bun types and bun run ci pass. Checked with Playwright and Chromium against a built app served by a source host with isolated ACE_HOME, ACE_CONFIG_HOME, ACE_PORT and ACE_KEYCHAIN_SERVICE. The project had two channels.

  • 1280px, collapsed: the aria snapshot has no sidebar controls (no project selector or channel buttons). Shift+Tab from the toggle goes to the nav and skips the sidebar. Clicking a hidden channel button is blocked.
  • 1280px, close with focus inside: closing with focus on a channel button or on the resize grip, using the ace:channels-toggle shortcut path, leaves focus on Toggle channels sidebar.
  • 1280px, reopen: the controls come back and the selected channel tab (alpha) is unchanged. Selecting beta from the reopened sidebar works.
  • 500px overlay: opening makes main inert and the sidebar interactive. Closing with focus inside moves focus to the toggle. Closing by an outside click leaves the sidebar inert/aria-hidden and main not inert. Going back to 1280px keeps the attributes in line with data-left.
  • Details sidebar (1400px): inert/aria-hidden when closed. Closing it from its own Close button leaves focus on Toggle details sidebar.
  • Issues page: closing with focus inside leaves focus on Toggle issues sidebar.

Not checked with a real screen reader. The desktop (Electrobun/WebKit) build was not run.

Built in Ace

No. Made by a Claude Code subagent in a terminal at the maintainer's choice for this session; not an Ace capability gap. Dogfooding: #5.

A collapsed desktop left sidebar kept a visible zero-width grid track, so its
controls stayed focusable and exposed to assistive technology.

Why: packages/ui/src/components/layout/layout.tsx#function Sidebar | a closing sidebar finds its toggle via [aria-controls=<sidebar id>]; consumers must give the sidebar an id and its toggles aria-controls, or focus falls to the body
Why: packages/ui/src/components/layout/layout.tsx#function Layout | the compact overlay effect must stay a layout effect and leave open sidebars' inert alone, or main stays inert when focus moves to the toggle and closed sidebars lose inert on cleanup
@iamnbutler
iamnbutler merged commit feadab1 into main Oct 14, 2026
1 check passed
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.

Hide collapsed sidebar controls from accessibility navigation

1 participant