Original task: Make admin pop-ups close with Escape and trap keyboard
focus (#185).
Changes
- artifacts/tx-os/src/pages/admin.tsx
- UserGroupsEditor and its inner "Review changes" pop-up no longer
use the hand-rolled fixed-inset overlay. Both now use the in-house
Radix-based Dialog (Dialog/DialogContent/DialogHeader/DialogTitle/
DialogDescription/DialogFooter) so Escape closes only the topmost
dialog, Tab/Shift+Tab is trapped, and the close button + aria-modal
semantics come for free.
- Removed the manual `keydown` Escape useEffect that was previously
needed for the Review pop-up.
- Preserved all existing data-testids (edit-user-save,
edit-user-review-dialog, edit-user-review-back, etc.) plus added
a new edit-user-dialog testid for the editor shell.
- Kept the original glass-panel look by passing border-0 / shadow-none
and rounded-3xl through DialogContent's className.
- Focus return: Radix's automatic restoration is unreliable for
nested dialogs. Added two explicit hops:
- The Review dialog uses onCloseAutoFocus to refocus the Save
button via a saveBtnRef.
- The editor dialog captures whatever was focused when it first
rendered (the pencil icon) into triggerElementRef, and
onCloseAutoFocus refocuses it. Verified the pencil button is
what the test sees.
Tests
- artifacts/tx-os/tests/admin-user-edit-review.spec.mjs
- New test "Escape closes topmost dialog; Tab keeps focus inside;
focus returns to opener" runs in both en and ar:
- Esc closes only the Review (editor stays open) and focus
returns to the Save button.
- Tab x15 and Shift+Tab x5 keep document.activeElement inside
the editor dialog.
- Esc on the editor closes it and returns focus to the pencil.
- All 4 specs in this file pass (~58s).
No deviations from the task; scope intentionally limited to the user
editor + Review pop-up. The same pattern in the Groups/Roles/Apps
editors was filed as follow-up #266.
Replit-Task-Id: fc613d10-06d0-460f-b1a4-0a65ff021d4a