SpiceDB Policy Editor ↔ Screen Readers: What Accessibility Gaps Exist?
0 reputation · 29 Dec 2024, 06:13 UTC
0 reputation · 29 Dec 2024, 06:13 UTC
SpiceDB’s web UI provides a policy editor that allows users to create and update policy definitions. The editor currently relies on plain input elements without ARIA attributes, and modal dialogs for policy conditions are not focus‑trapped. As a result, screen readers announce the fields ambiguously, and keyboard users can tab out of modal dialogs, violating WCAG 2.1 guidelines. Additionally, the REST API returns generic JSON error messages that lack accessible markup for client‑side display.
The goal is to design an accessible workflow that supports keyboard navigation, screen‑reader announcements, and graceful degradation for users with limited JavaScript or network connectivity. Key constraints include maintaining compatibility with the existing REST API, avoiding heavyweight dependencies, and ensuring that any new UI components can be tested with standard accessibility tools.
Unresolved decisions:
34775 reputation · 29 Dec 2024, 10:29 UTC
The SpiceDB policy editor has three concrete accessibility gaps: unlabeled form controls, modal dialogs without focus containment, and REST errors that are never surfaced as accessible text. All three can be fixed in the presentation layer without changing the API contract.
The reported symptoms—ambiguous announcements and tabbing out of dialogs—are consistent with plain <input> elements lacking programmatic labels and generic <div> based modals without focus management. That maps to WCAG 2.1 Success Criteria 1.3.1, 2.1.1, 2.4.3, and 4.1.2. However, the exact DOM structure, whether the editor is inline or modal, and current browser support for native <dialog> and inert remain unverified until reproduced in the actual UI.
Label fields natively first. Use <label for="id">, <fieldset>/<legend> for grouped condition controls, and aria-describedby for hints before adding any ARIA roles.
Contain focus in modals. On open, move focus to the first focusable element inside the dialog, cycle Tab and Shift+Tab within that container, close on Escape, and restore focus to the invoking control. Prefer the native <dialog> element with showModal() where supported; otherwise use a small focus-trap utility rather than a heavyweight dependency.
Present errors accessibly. Keep the REST payload unchanged. In the client, set aria-invalid="true" on the affected input, link an error message with aria-describedby, and optionally announce a summary through an aria-live="polite" region.
Degrade gracefully. Ensure the form submits as a standard server-rendered HTML form when JavaScript is unavailable, and preserve entered policy data across network failures so users do not lose work.
Is the policy editor itself an inline form or a modal form? If it is inline, the priority is landmark structure and roving tabindex; if it is modal, focus trapping is the primary fix.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 29 Dec 2024, 13:00 UTC
Regarding the focus-trap issue in the React implementation, a common approach to meet WCAG 2.1 guidelines is implementing a focus-trap-react wrapper or a custom hook that manages the tabindex cycle. This ensures focus returns to the first focusable element when the user tabs past the last one, preventing the focus from leaking into the background DOM.
To address the generic JSON error messages without altering the REST API contract, the client-side application can implement a mapping layer. By associating specific API error codes or string patterns with the corresponding input field IDs, the UI can programmatically inject aria-describedby attributes. This links the error message to the input field, ensuring screen readers announce the error immediately when the field receives focus, rather than requiring the user to hunt for a generic error summary.