refactor(markdown-editor): drop the toolbar roving-focus childList observation

The roving-tabindex MutationObserver watched childList:true/subtree:true, justified
by a comment claiming "the table control swaps button↔menu". Verified against the
source: the toolbar's item set is static (every control renders unconditionally;
state only drives pressed/disabled props), and each menu keeps its `data-toolbar-item`
trigger in the bar while swapping its content in a Radix body portal — outside the
observed subtree. So childList observed nothing. Keep only the load-bearing
attributeFilter:['disabled'] + subtree (a disabled toggle changes the roving set),
and correct the comment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Sergey Kozyrenko
2026-07-07 21:24:33 +07:00
co-authored by Claude Opus 4.8
parent 2835fd3302
commit 2b7931732a
@@ -75,10 +75,11 @@ function useHorizontalWheelScroll(ref: React.RefObject<HTMLDivElement | null>) {
}
// WAI-ARIA toolbar pattern: one Tab stop for the whole bar, Arrow/Home/End move between controls. Managed
// imperatively on `[data-toolbar-item]` so each control stays a dumb button; the set changes (the table
// control swaps button↔menu, controls disable) so a MutationObserver re-seeds the single tab stop. When a
// popover/dropdown is open its focus lives in a body portal outside the bar, so activeElement isn't an item
// and Arrow keys fall through to that menu instead of being hijacked here.
// imperatively on `[data-toolbar-item]` so each control stays a dumb button. The item set is static, but a
// control's `disabled` toggling changes which items are in the roving set, so a MutationObserver on the
// `disabled` attribute re-seeds the single tab stop (menus swap their content in a body portal, not here, so
// no childList watch is needed). When a popover/dropdown is open its focus lives in that portal outside the
// bar, so activeElement isn't an item and Arrow keys fall through to the menu instead of being hijacked here.
function useToolbarRovingFocus(ref: React.RefObject<HTMLDivElement | null>) {
useEffect(() => {
const toolbar = ref.current;
@@ -104,7 +105,7 @@ function useToolbarRovingFocus(ref: React.RefObject<HTMLDivElement | null>) {
seedTabStop();
const observer = new MutationObserver(seedTabStop);
observer.observe(toolbar, { attributeFilter: ['disabled'], childList: true, subtree: true });
observer.observe(toolbar, { attributeFilter: ['disabled'], subtree: true });
const handleKeyDown = (event: KeyboardEvent) => {
if (!['ArrowLeft', 'ArrowRight', 'End', 'Home'].includes(event.key)) {