Make sidebar Search and resizing accessible - #4601
Conversation
|
Here's a visual recap of what changed: Open the full interactive recap |
There was a problem hiding this comment.
Builder reviewed your changes and found 2 potential issues 🟡
Review Details
Code Review Summary
PR #4601 routes sidebar Search through the shared command picker, adds accessible names for icon-only controls, makes the desktop resize divider keyboard-operable, and aligns the shared picker with the dialog stacking layer so it remains above mobile navigation drawers. The overall approach is sound: it removes the hidden inline-search state, reuses the existing search surface, exposes separator value semantics, and keeps pointer and keyboard resizing on the same callback. The shared z-index change is covered by updated core tests and is appropriate for the toolkit dialog stack.
Risk assessment: Standard. The key concerns are edge cases at the boundaries between focus management, navigation/unmounting, and RTL layout direction:
- 🟡 MEDIUM: Mobile search-result navigation can unmount the stored trigger before the focus-restoration frame runs, leaving focus on the body instead of a live navigation control.
- 🟡 MEDIUM: In RTL, keyboard ArrowLeft/ArrowRight resizing is opposite to the physical direction of pointer dragging on the sidebar's
end-0divider.
The implementation has good localized labeling and bounded Home/End semantics. Focus and RTL behavior should be corrected before approval.
🧪 Browser testing: Could not verify — the dev server was healthy, but Chrome automation tools were unavailable across all 17 planned test cases and retries.
| useEffect(() => { | ||
| if (cmdkOpen || !commandTrigger.current) return; | ||
| const trigger = commandTrigger.current; | ||
| commandTrigger.current = null; | ||
| const frame = window.requestAnimationFrame(() => { | ||
| if (trigger.isConnected) trigger.focus(); |
There was a problem hiding this comment.
🟡 Preserve focus when mobile navigation unmounts the trigger
When Search is opened from the mobile drawer and a result is selected, the picker closes while navigation also causes the drawer (and its trigger) to unmount. The scheduled callback then sees trigger.isConnected === false, so focus is left on the body/removed focus scope. Restore focus to a still-mounted navigation target or coordinate drawer closure and picker dismissal so keyboard users retain a valid focus destination.
Additional Info
Reported by 1 of 2 parallel review agents; matches the PR's mobile drawer focus-risk area.
| onKeyDown={(event) => { | ||
| let nextWidth: number; | ||
| switch (event.key) { | ||
| case "ArrowLeft": | ||
| nextWidth = width - 10; | ||
| break; | ||
| case "ArrowRight": | ||
| nextWidth = width + 10; | ||
| break; | ||
| case "Home": | ||
| if (minWidth === undefined) return; | ||
| nextWidth = minWidth; | ||
| break; | ||
| case "End": | ||
| if (maxWidth === undefined) return; | ||
| nextWidth = maxWidth; | ||
| break; | ||
| default: | ||
| return; | ||
| } | ||
| event.preventDefault(); | ||
| onResize(nextWidth); |
There was a problem hiding this comment.
🟡 Keep keyboard resize direction consistent in RTL
The keyboard handler always makes ArrowLeft decrease width and ArrowRight increase it. In the supported RTL layout, this sidebar's end-0 divider is on the physical left edge, so pointer-dragging left increases width while ArrowLeft decreases it. Derive the arrow delta from document direction (or use logical inline-direction semantics) so keyboard and pointer resizing agree.
Additional Info
Reported by 1 of 2 parallel review agents; independently confirmed against the RTL layout and pointer handler.

Problem
People using Content's collapsed sidebar cannot reliably start a search: the Search button toggles an inline filter that is hidden in that layout. The icon-only New Page and Settings controls also lack accessible names, and changing the sidebar width requires a pointer.
Approach
Search now opens the existing command picker on the first click or keyboard activation. Dismissing it returns focus to the control that opened it. Reusing that picker gives collapsed, expanded, and mobile navigation the same search entry point and removes the sidebar's separate filter state.
This covers the sidebar controls work (SB-01–03). Richer search filters and results remain separately scoped. Creation and Retry behavior, deletion, Trash, unpin semantics, and personal ordering are outside this change.
What changed
Verification
Interface checks exercised runtime commit
c774d3eaa. The subsequent documentation update and head1052cd39fpreserve that behavior: the latest repair removes a redundant overlay color class while retaining the same inline background color. Existing interface evidence is retained; the implementation owner reran the 13 command-menu tests, including the rendered background assertion, plus the raw-color guard, formatting, and diff checks. All passed. Broader local builds and checks below precede this narrow repair.tsxsubprocess invocation. No guard or baseline was weakened.1052cd39f: Security guards now passes after removal of the redundant overlay color class. Other checks are still queued or running; a fully green CI result is not yet established.Review focus
This PR is open for review and awaits approval from Steve. Remaining CI checks must pass before merge.