fix(web): address Copilot review on the shared JSON editor

- Cap the read-only editor's `maxLines` at 200. Uncapped, Ace renders every
  line of a payload and its viewport virtualization never engages — which
  matters because the Protocol and Network lists are not virtualized and keep
  each entry's payload mounted inside its `Collapse`. 200 is chosen so no real
  payload nests a scrollbar inside its host's while the pathological one stays
  bounded; the StructuredOutputPanel `Large` story now pins both halves (full
  payload in the document, only part of it in the DOM).

- Take a disabled editor out of the tab order and give it `aria-disabled`.
  Ace has no disabled state, so its hidden textarea kept `tabindex="0"` and a
  keyboard user could tab into a field every neighbouring control had dropped
  — landing somewhere that looks editable and swallows what they type. A
  merely read-only editor stays focusable, since a payload has to be
  keyboard-scrollable (WCAG SC 2.1.1).

- Reword a confusing comment in the EditReplayModal test.

The `Disabled` story additionally scopes the axe `color-contrast` rule off:
WCAG 1.4.3 exempts inactive components, and axe cannot see that the dimmed
gutter belongs to one because the disabled state lives on Ace's hidden
textarea. Scoped to that one story so the rule still covers everything else.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UL9retfvAXRgvi6EWk4SY4
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-27 02:44:21 -04:00
commit c9fb461bf0

View file

@ -100,8 +100,9 @@ describe("EditReplayModal", () => {
expect(onSend).not.toHaveBeenCalled();
});
// The draft belongs to the sitting the user opened it in. Reopening must show
// the entry's params again, not whatever they typed and abandoned last time.
// The draft belongs to the one opening of the modal it was typed in.
// Reopening must show the entry's params again, not whatever was typed and
// abandoned last time.
it("reseeds from the entry when reopened", async () => {
const { rerender } = renderWithMantine(
<EditReplayModal {...baseProps} params={{ name: "echo" }} />,