Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

10 — Interaction Specification (Search Module)

Interaction-level contract for search: state transitions, timing, motion, input handling. Shared interaction/motion conventions from 00-shared/08_Interaction_&_Motion.md; this file is module-specific.


1. Interaction states (per 06 §2)

StateTriggerVisualExit
idleno querylanding (07 §6)type → typing
typingkeystroke while composingbar spinner off; no networkdebounce expiry → loading
loadingdebounce fire / submit / page fetch / retryprevious results dimmed; bar spinner; first query → skeleton (07 §4)response → success/empty/error
success200 with datagrouped tiles; new groups animate inscroll → loading(page); type → typing; tap → navigate
empty200 with data: []AppEmptyState (06 §2.4)clear → idle; type → typing
errornetwork/401/403/429/5xxAppErrorState (06 §2.5)retry → loading; back → previous
permissiondirect deep link without search perm (permissions.constants.ts:93)permission state (06 §2.6)n/a

2. Debounce interaction (exact timing)

  1. Keystroke → SearchBarField restarts a 300 ms Timer.
  2. Composition end (IME) starts the timer (CJK-safe).
  3. Timer fires → SearchCubit.queryChanged → stale-guard token++ → loading → repository call (13 §3).
  4. Any earlier in-flight response whose token is stale is dropped.
  5. Empty input cancels the timer immediately (no request, 08 §1.2).

3. Query transitions

FromToBehavior
q=A (results shown)q=Bkeep A results visible while B loads; replace on B success — never blank the list (06 §2.2)
aggregate viewsee-all type=XentityType=X set, page 1, list collapses to one group; back restores previous query + type
see-allbackrestore aggregate view from cubit state (no refetch needed if unchanged)
paginationappendpage+1 appended; no scroll jump; scroll position preserved

4. Navigation interactions

  • Tap tile → owner-module detail route (Students /students/:id, etc.) — SearchModule only supplies the pointer (entityId, entityType, search.service.ts:11-12).
  • Back from detail → results preserved as-is (cubit state survives).
  • Deep link /search?q=… (forward-looking): prefill bar, run query.

5. Motion & animation (tokens from 00-shared/08)

InteractionMotion
Focus into barunderline grow m-fast (150 ms)
New group appearsfade + 4 px rise m-base (250 ms)
Group removalfade out 150 ms, list reflows
Row tapstandard ripple; navigation slide m-base
Clear (✕)bar resets to idle m-fast; landing fade-in m-base
Error stateshake m-fast on retry failure (match auth module convention)

6. Input handling rules

  • textInputAction.search submits; Esc (desktop) clears; / (desktop) focuses bar (06 §6).
  • No IME debounce while composing (08 §1.5).
  • Focus: bar auto-focused on /search entry; cleared on navigation.

7. Offline / degraded interaction

  • Offline → banner + last results retained (if any) + retry on restore (00-shared/10 §2).
  • Server-side fallback (search.service.ts:35-41) is invisible to the user; client does not show a "degraded" state (order may differ — fallback has no textScore sort, search-index.repository.ts:49).

8. Analytics events (proposed)

search.bar.focus, search.bar.submit, search.bar.clear, search.landing.chip.tap, search.results.shown(count), search.results.empty, search.result.tap(entityType), search.seeall.tap(type), search.page.next, search.error.{server,offline,retry}. All (proposed) — SDK open (00-shared/12 A4).