Repository navigation
fix(frontend): drop the last native dialogs in API key and users flows - #1361
Conversation
When the clipboard write fails on the one-time "API Key Created" modal, the app popped a browser-native alert(). Native dialogs cannot be styled, are blocked in some embedded contexts, and sit outside the modal's focus handling. The modal now shows an inline role="alert" message under the key and selects the key text, so Ctrl+C / Cmd+C copies it without leaving the modal. A later successful copy hides the message again. Refs LeanerCloud#705 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
setupUserHandlers still wired #bulk-group-btn to a native prompt() asking for a group ID. That button is not in index.html: the production toolbar adds users to a group through #bulk-group-select. The handler was the last native prompt() in the app, so it is removed and the test now asserts a stray legacy button stays inert and never opens a native prompt. Refs LeanerCloud#705 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The "API Key Created" dialog shows a curl example in a <pre class="code-example">, but .code-example had no CSS rule. A <pre> never wraps by default, so the one-line command ran past the modal's right edge and was clipped at "https:/", hiding the endpoint part. Add a .modal-content .code-example rule in modals.css next to the other modal styles: it wraps (white-space: pre-wrap; overflow-wrap: anywhere) so the whole command is visible without scrolling sideways, and gets the same code-block look as the existing .code-block snippet (monospace, light background, border, padding, radius). Stylesheet only, no inline styles, so the CSP is unaffected. The Playwright spec checks at 1440x900 and 390x844 that the rendered command text ends inside the modal's right edge and that neither the block nor the modal scrolls sideways. Both checks fail without the rule. Refs LeanerCloud#705 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reached
This review includes 6 billable files and costs up to $1.50. Or wait 59 minutes for your next included review. View limit details
Comment |
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): APPROVE Blocking:
|
|
Local verification at
|
|
Marked ready and merged by IAmJSD's agent, at IAmJSD's request (IAmJSD reviewed the before/after screenshots; cristim is traveling), after the independent review and local verification above, all at |
Most of this issue was already fixed on main by #763 (
23603381): the shared confirm dialog focuses Cancel for destructive actions, hasaria-labelledby/aria-describedby, handles Shift+Tab, and the nativeconfirm()/prompt()calls in navigation, bulk add-to-group and registration reject use the styled dialog. This PR removes the two native dialogs that were left (analert()when copying a new API key fails, and aprompt()wired to a bulk "Add to group" button that no longer exists) and fixes the clipped curl example in the same API Key Created modal.Closes #705
What changed
ddd3cbd0,frontend/src/apikeys.ts: the one-time "API Key Created" modal gets an inline<p id="apikey-copy-error" class="field-error" role="alert">. On a clipboard failure it shows "Could not copy automatically. The key is selected: press Ctrl+C (Cmd+C on Mac) to copy it." and selects the key text, instead ofalert(). A later successful copy hides the message.99fa40e1,frontend/src/users/handlers.ts: removes the dead#bulk-group-btnprompt()handler and its unused import. That button is not inindex.html; bulk add-to-group goes through the existing#bulk-group-selectdropdown. The test now asserts a stray legacy button stays inert and never opens a native prompt.870a02d3,frontend/src/styles/modals.css: the curl example in the same modal (<pre class="code-example">) had no CSS rule, so the one-line command ran past the modal's right edge and was clipped at "https:/". A new.modal-content .code-examplerule wraps it (white-space: pre-wrap; overflow-wrap: anywhere) and gives it the look of the existing.code-blocksnippet (monospace, light background, border, padding, radius,max-width: 100%,border-box). Stylesheet only, so the CSP is unaffected.__tests__/apikeys.test.tsand__tests__/users.test.ts, and newtests-e2e/apikey-copy-failure.spec.ts.Why this approach
An inline message inside the modal works better than a toast here: the modal is a require-ack focus trap over a backdrop, and selecting the key gives a one-keystroke fallback without leaving it. It reuses the existing
.field-errorstyle. For theprompt(), the button exists only in a jest fixture, and #763 already called it dead code left for cleanup; removing it is smaller and more honest than building a styled group picker for a button nobody can click.Screenshots
Before is main (
a14dc8f2), after is this branch. Both are headless Chromium at 1440x900 against the repo's mocked e2e API.alert()(the white banner at the top is drawn by the screenshot script to show the alert text, since native dialogs don't appear in page screenshots). After, no native dialog: a red inline message under the key says copying failed and the key is already selected. These two shots were taken before the curl commit, so they still show the clipped curl line.Verification
Run on this branch's head
870a02d3on top of maina14dc8f2:anywarnings). Typecheck and build pass.--randomize,apikeyspasses;users.test.tsfails 26-27 tests under seed -397418023, and the untouched base file fails 27 under the same seed, so that order dependence predates this branch.e2e-local.sh: 160 passed. The newapikey-copy-failure.spec.tsrejects the clipboard and asserts the inlinerole="alert"error, the selected key text and no native dialog; two more tests check at 1440x900 and 390x844 that the rendered curl text ends inside the modal's right edge and that neither the block nor the modal scrolls sideways. Both curl tests fail with the rule removed (text right edge 1097 vs modal 970 at 1440x900; 627 vs 390 at 390x844).scripts/test-git-secrets-allowlist.sh: 137 pass, 0 fail.alert(),confirm()orprompt()calls remain infrontend/srcoutside tests.Notes for review
openModal" suggestion forconfirmDialog.ts. It already has its own working focus trap, Escape handling, focus restore and ARIA, so a refactor would change no behavior.Overlaps
ladder.ts,settings.ts,dashboard.ts,auth.ts). No other branch touchesapikeys.tsorusers/handlers.ts. Those PRs will be opened alongside this one and merged in sequence, with conflicts resolved on the later branch.Note for the UI owner
This changes UI code that @cristim owns. IAmJSD reviewed the before/after screenshots and asked for it to be merged; any design point you disagree with can be a follow-up.
🤖 Generated with Claude Code