diff --git a/tests/test_shell_js.py b/tests/test_shell_js.py index 3ab963b9..84a1811f 100644 --- a/tests/test_shell_js.py +++ b/tests/test_shell_js.py @@ -736,6 +736,11 @@ def test_pane_manager_split_engine() -> None: assert 'setAttribute("role", "separator")' in pane assert "setPointerCapture" in pane and "_ratioBounds(node)" in pane assert '"aria-valuenow"' in pane and "ArrowRight" in pane + # the ARIA range mirrors the REAL clamp (_ratioBounds per handle in the + # _applyLayout loop) — never a hard-coded constant + assert "this._ratioBounds(h.node)" in pane + assert '"aria-valuemin"' in pane and '"aria-valuemax"' in pane + assert 'setAttribute("aria-valuemin", "10")' not in pane # limits: cell minimums + cap (the old ui/static ceiling, kept) assert "SPLIT_MAX_CELLS = 6" in pane assert "SPLIT_MIN_W = 200" in pane and "SPLIT_MIN_H = 150" in pane diff --git a/turnstone/shared_static/pane.js b/turnstone/shared_static/pane.js index 2619c7eb..9d301abc 100644 --- a/turnstone/shared_static/pane.js +++ b/turnstone/shared_static/pane.js @@ -806,6 +806,21 @@ export class PaneManager { el.style.top = h.y * 100 + "%"; if (h.node.dir === "row") el.style.height = h.span * 100 + "%"; else el.style.width = h.span * 100 + "%"; + // The ARIA range is the REAL clamp (_ratioBounds: the cell minimums + // against this split's OWN px region — nested splits sit tighter than + // any constant; the old hard-coded 10–90 misreported it to AT). It + // refreshes with every drag/keyboard/structure pass through here; a + // bare window resize can stale it until the next interaction (no + // resize listener by design — % insets make resizes free), which is + // still strictly truer than a constant. The max>=min guard covers a + // host shrunk below two minimums, where the bounds legitimately cross. + const b = this._ratioBounds(h.node); + const lo = Math.round(b.min * 100); + el.setAttribute("aria-valuemin", String(lo)); + el.setAttribute( + "aria-valuemax", + String(Math.max(lo, Math.round(b.max * 100))), + ); el.setAttribute("aria-valuenow", String(Math.round(h.node.ratio * 100))); } } @@ -916,9 +931,8 @@ export class PaneManager { "aria-orientation", node.dir === "row" ? "vertical" : "horizontal", ); - el.setAttribute("aria-valuemin", "10"); - el.setAttribute("aria-valuemax", "90"); - el.setAttribute("aria-valuenow", String(Math.round(node.ratio * 100))); + // aria-valuenow/min/max are written by _applyLayout's handle loop (the + // single writer) — the range comes from _ratioBounds, not a constant. el.setAttribute( "aria-label", node.dir === "row"