Concrete interactions per screen: gestures, focus, feedback, dialogs, motion, loading,
and offline behaviour. Motion tokens per 00-shared/08 , interaction baseline per
00-shared/10 . All client design is (proposed) unless marked.
Interaction Spec
Row tap push S2 (phone); select in master-detail pane (≥ 840 dp) without pushing; hover highlight on desktop
Pull-to-refresh RefreshIndicator; bypasses cache; resets to page 1; error → snackbar with Retry
Infinite scroll trigger at 80% viewport; fetch page+1 when hasNext; bottom spinner; dedupe by _id; failure → inline retry row (keep loaded items)
Search debounce 300 ms; client filter (proposed); clears on X; no results → empty state with "Clear filters"
Filter chips multi-select type chips; building chips derived; chip tap toggles (not navigate); selected chips show removal ×
FAB "New room" — visible only with rooms.create; tap → push /rooms/new
Row menu (proposed) delete shortcut (gated rooms.delete) → S4 dialog
Loading 6 skeleton RoomCards, staggered m-fast fade-in
Feedback mutations from S2/S4 reflected: row removed + count badge decrement; snackbar shown by originating screen
Motion: card entrance fade/slide 8 dp m-fast; refresh spinner standard; empty-state
m-base fade (00-shared/08 ).
Interaction Spec
Back pop to S1 (list state preserved incl. filters)
Edit gated rooms.update; push /rooms/:id/edit prefilled
Delete gated rooms.delete; opens S4 dialog (never inline)
Menu ⋮ → "Copy code" (clipboard + snackbar "Code copied"); future "QR code" (forward-looking)
Facilities first 2 chips + "+n" button; tap → expand full list (AnimatedSize, m-fast); collapse back
Stale detail if list refresh shows the room was deleted (404) → pop + snackbar "Room no longer exists"
Offline cached doc + banner; actions (edit/delete) disabled until online
Availability (planned) section with skeleton; empty state "No upcoming bookings"; row tap → booking detail (planned)
Interaction Spec
Save (AppBar action) validates → submit; spinner in place of icon; disabled while submitting
Keyboard Enter advances field; F3 numeric; save action (proposed) from keyboard on F6
Code field uppercase transform + trim on input; async uniqueness check (300 ms debounce) → ✓/✗; on create only (edit: warning (proposed), server check (planned))
Type dropdown modal/AppDropdown; selection closes and applies immediately; default classroom
Facilities chip input type + Enter/, → chip; backspace on empty → remove last chip; × removes; duplicates ignored; max 12 then input disabled with hint
Discard dirty + back → dialog [Keep editing][Discard]; discard pops without saving
Submit results 201/200 → pop + snackbar; 409 → inline error + scroll-to-field; 400 → field errors + focus first invalid; offline → block + banner (draft kept)
Concurrent edit (proposed) server version bump (base.repository.ts:57-66); client conflict dialog on stale-base submit (planned)
Motion: field error → m-fast shake on the offending field; snackbar m-base slide.
Interaction Spec
Open from S2 menu or S1 row menu (gated rooms.delete)
Confirm text field must equal room.name (case-sensitive) to enable Delete; mismatch → button disabled; match → enabled
Submit button spinner; fields disabled; no dismiss on tap-out while submitting
Success dialog closes; if on S2 → pop to S1; row removed; snackbar "Room deleted"
404 dialog closes; snackbar "Room not found — it may already be deleted"
Network fail dialog stays; snackbar "Couldn't delete — Retry"
Cancel / tap-out closes; analytics rooms.delete.cancel
In-use warning (proposed) copy "This room may be referenced by timetables or bookings" — server in-use guard (planned) (OQ-4)
Action Optimistic? Loading UI Success Failure
List load / load-more no skeletons / bottom row cards retry row / snackbar
Detail load no skeleton profile error state + Retry
Create / update no (server authoritative)button spinner pop + snackbar inline errors / snackbar
Delete no dialog spinner pop + snackbar snackbar
Copy code yes (clipboard) — snackbar "Copied" —
Reads: last-good cache + AppOfflineBanner (no module offline queue — reference data).
Writes: blocked with inline banner "You're offline"; draft preserved in cubit memory.
Reconnect: banner clears; user re-triggers (pull-to-refresh / re-submit).
Motion Token Use
Entrance m-fastcards, detail fade, chips
Feedback m-fastpress states, error shake
Transitions m-baseroute push/pop, snackbar
Expansion m-basefacilities expand/collapse (AnimatedSize)