Skip to content

MEMBERS-DIRECTORY-001L — Restore People-finder submit focus after search completion #641

Description

@daliu

Parent: #504. Connected release remains owned by #507.

Officer impact: No live officer workflow changes. In the preserved future People finder, a keyboard or screen-reader user who starts a valid search from the name field or Search button will return to that same control after the current search resolves, instead of being stranded after both controls were disabled during loading. The connected interface remains unavailable on production.

Officer documentation: Update SYSTEM_DESIGN.md, IMPLEMENTATION_PLAN.md, SECURITY.md, and only the optional-directory one-sentence text alternative plus one no-terminal source-evidence procedure in docs/officers/EVENTS_SHOP_MEMBERS.md. No Mermaid change because no element, page topology, permission, or data movement changes.

Deployment evidence: None at issue creation. This is source-only keyboard-focus hardening. memberDirectoryAvailability.ts must remain byte-for-byte false; no website, Firebase, provider, account/sign-in, production-data, deployment, or connected-live action is authorized.

Atomic outcome

Restore focus to the exact connected People-finder control that held focus when one current valid search entered its pending state.

Defect

On exact released main 3ca02e19fbe9977d15f602d37b5200956db1f2b3, SearchAttempt natively disables both the name input and Search button while a search is pending. A focused input submitted with Enter or a focused Search button therefore loses keyboard focus. Completion only re-enables those controls and renders result cards, the empty state, or the fixed failure plus Clear; it records no focus destination. Keyboard and screen-reader users can be left on the document body after every completed search.

Invariants and transitions

  • Create a focus intent only after a valid query and request ID admit one search into pending, and only when the active element is the persistent name input or Search button.
  • Record only that exact origin and search-operation identity; no query, name, result, photo, account ID, or service value.
  • Keep the native disabled controls and duplicate-submission gate unchanged during pending.
  • When that exact current operation resolves to result cards, empty results, or fixed unavailable failure, consume the intent and focus the same now-enabled origin after render.
  • Programmatic/outside-focus submission creates no intent and never steals focus.
  • Validation and request-ID construction failure never enter pending; preserve enabled-control and natural-focus behavior.
  • Input editing and Clear remove obsolete intent. Clear keeps its zero-ID/zero-call behavior and focuses the empty name input.
  • App change, admin UID change, unmount, or obsolete operation cannot move focus in another context.
  • Focus creates no ID, search, retry, Clear action, result, audit, service call, or data URL.
  • Existing normalization, result disposal, fixed errors, response bounds, AdminGuard, stale fences, and voluntary-thumbnail behavior remain unchanged.
  • Availability stays false; default route remains inert/disabled/zero-context/zero-call.
  • Name-prefix search plus human comparison of voluntary thumbnails only. No photo query, facial recognition, matching, embedding, similarity, biometrics, totals, export, roster authority, or membership proof.

Exact ownership

  • src/pages/admin/members/AdminMemberDirectory.tsx: only an operation-bound submit-origin focus intent, Search-button ref, cleanup/clear guards, and guarded post-settlement focus handoff inside SearchAttempt.
  • src/pages/admin/members/AdminMemberDirectory.test.tsx: one separately named MEMBERS-DIRECTORY-001L block plus minimum directly affected helpers/assertions.
  • SYSTEM_DESIGN.md: one separately named 001L source-only paragraph.
  • IMPLEMENTATION_PLAN.md: one separately named 001L current-source paragraph.
  • SECURITY.md: one separately named 001L/RISK-042 row immediately after released 001K; preserve active OAUTH-001A2L — Bound Strava activity/statistics JSON and cancel the unread statistics body #616 OAUTH-001A2L/RISK-024 byte-for-byte.
  • docs/officers/EVENTS_SHOP_MEMBERS.md: only the optional-directory one-sentence text alternative and one separately named no-terminal 001L source-evidence procedure; no diagram change.

No CSS: the same native controls and existing focus styles are used.

Required tests

  • Capture trustworthy RED by focusing input or Search, starting a deferred valid search, asserting both disabled, modeling browser disabled-control focus eviction with blur(), settling, and proving old source leaves focus off the origin.
  • Matrix both origins across non-empty, empty, and fixed failure; current settlement restores the same persistent origin, not Clear/results/body.
  • Focus handoff consumes one exact intent and creates no second request, ID, retry, or Clear.
  • Programmatic/outside-focus submission never steals outside focus on settlement.
  • Validation and request-ID construction failure remain enabled/generic/focus-inert beyond natural focus, with no request.
  • Existing Clear behavior still removes query/messages/cards/names/images, focuses input, and creates no new ID/call.
  • App/admin change and unmount make late old resolution/rejection focus-inert.
  • Default unavailable preview remains zero-context/zero-ID/zero-call.
  • Existing response/privacy/disposal/photo/accessibility/mobile/stale tests plus full frontend, TypeScript, lint baseline, build, workflow/security tests, and diff check pass.

Explicit exclusions

Migration and residual risk

No migration. Focus handoff is accessibility behavior, not authorization, provider acknowledgement, audit proof, result correctness, or live evidence. Live #623 remains inert; #507 retains all connection/release gates.

Claim protocol

Assign and post a timestamped CLAIMED marker with exact branch/base before edits. Claim stays active through reviewed merge, exact-main audit, closure, and explicit release.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:adminAdministrative workflowsarea:membershipMembership lifecycle and reconciliationarea:privacyPersonal data, consent, minimization, retention, and privacy operationsarea:webWeb application and hostingbugSomething isn't workingpriority:P1High-priority follow-upsize:SSmall focused issuetype:reliabilityReliability and recoverytype:testingTest infrastructure and quality gates

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions