Microinteraction case studies skill

Detailed design breakdowns of common UI patterns, analyzed through the four-part microinteraction structure: Trigger, Rules, Feedback, and…

by wondelai·MIT license·★ 2,235 Stars on the repo·GitHub ↗

Use now

Files of Microinteraction case studies

wondelai/main1 file
case-studies.md
Show the full text372 lines

Microinteraction Case Studies

Detailed design breakdowns of common UI patterns, analyzed through the four-part microinteraction structure: Trigger, Rules, Feedback, and Loops & Modes. Each case study documents the interaction from first use through edge cases, providing a practical blueprint for implementation.

Table of Contents

  1. Case Study 1: Form Submission
  2. Case Study 2: Toggle / Switch
  3. Case Study 3: Pull-to-Refresh
  4. Case Study 4: Loading States
  5. Case Study 5: Notifications (Toast / Snackbar)
  6. Cross-Cutting Patterns

Case Study 1: Form Submission

A form submission microinteraction covers the moment from when the user taps "Submit" to when they receive confirmation of success or details of failure. It is one of the highest-stakes microinteractions because users have invested time and data.

The Four Parts

Trigger:

  • Manual trigger: "Submit" button (primary action, full-width or prominent)
  • Keyboard trigger: Enter key in last field (convention, not always expected)
  • System trigger: Auto-save draft after 30 seconds of inactivity (background)

Rules:

  1. On trigger, validate all required fields client-side before sending to server
  2. If validation fails, prevent submission and highlight first invalid field
  3. If validation passes, disable submit button and show loading state
  4. Send data to server
  5. On server success (200), show success feedback and redirect or reset form
  6. On server error (4xx/5xx), show error message and preserve all input
  7. On network timeout (>15 seconds), show retry option with preserved input

Feedback:

State Visual Copy Duration
Idle Blue "Submit" button, normal state "Submit" or "Create Account" Persistent
Validating Button briefly disabled "Checking..." 0-500ms
Validation error Red border on invalid fields, scroll to first error "Please enter a valid email" inline Until corrected
Submitting Button shows spinner, text changes "Submitting..." Server response time
Success Green checkmark replaces spinner "Done! Redirecting..." 1-2 seconds
Server error Red banner at top, button re-enabled "Something went wrong. Please try again." Until dismissed
Network error Yellow banner, retry button "Connection lost. Your data is saved locally." Until retry succeeds

Loops & Modes:

  • Auto-save loop: draft saved to local storage every 30 seconds (open loop)
  • Long loop: after 3+ submissions, hide optional tooltips and field hints
  • No modes (single-purpose interaction)
Edge Cases
Edge Case Handling
User double-clicks submit Disable button on first click; debounce server request
User navigates away mid-submission Show "Unsaved changes" dialog; save draft to local storage
Session expires during submission Queue submission; re-authenticate and retry
Very long form (20+ fields) Show progress indicator; validate sections independently
Paste of formatted text Strip formatting; accept plain text only
Autofill conflict Accept autofill values; re-validate on submit
Implementation Notes
Platform Key Detail
Web Use <form> native validation as baseline; enhance with JS. Preserve form data in sessionStorage.
iOS Use UITextFieldDelegate for per-field validation. Keyboard "Return" key should move to next field, not submit.
Android TextInputLayout with setError() for inline validation. Handle back button to save draft.

Case Study 2: Toggle / Switch

A toggle is a binary microinteraction: on or off. Despite its apparent simplicity, a well-designed toggle requires careful attention to state communication, animation timing, and accessibility.

The Four Parts

Trigger:

  • Manual trigger: tap/click anywhere on the toggle (track or thumb)
  • Keyboard trigger: Space bar when toggle is focused
  • Drag trigger: drag thumb from one position to the other
  • System trigger: external state change (admin disables feature remotely)

Rules:

  1. On trigger, immediately start transition animation
  2. If action requires server confirmation, send request in background
  3. Toggling on may trigger additional UI (reveal settings, enable features)
  4. Toggling off may trigger confirmation dialog for destructive changes
  5. If server rejects the change, revert toggle to previous state with error message
  6. Rapid toggling (clicking multiple times fast) should debounce: only the final state is sent

Feedback:

State Thumb Position Track Color Label (if used) Haptic
Off Left Gray (#E5E7EB) "Off" None
Transitioning on Sliding right Transitioning to green -- None
On Right Green (#22C55E) "On" Light tap
Transitioning off Sliding left Transitioning to gray -- None
Disabled Current position Faded (40% opacity) "Unavailable" None
Loading Current position Faded with inline spinner "Updating..." None
Error Reverted position Flash red briefly, return to normal "Failed to update" Error pattern

Loops & Modes:

  • No traditional loop (single action)
  • Long loop: if toggle controls a feature with settings, first 3 toggles might show a tooltip explaining the feature
  • No modes
Animation Specification
Property Value Easing
Thumb position (left to right) 150-200ms ease-in-out
Track color transition 150-200ms ease-in-out (synchronized with thumb)
Thumb shadow on drag 100ms to enlarge shadow ease-out
Revert on error 200ms ease-out with red flash
Accessibility
Requirement Implementation
ARIA role role="switch" with aria-checked="true/false"
Focus indicator 2px blue outline around entire toggle on Tab focus
Keyboard Space bar toggles; no Enter (per switch role spec)
Screen reader "Wi-Fi, switch, on" -- announces label, role, and state
Reduced motion Skip animation; instant state change
Touch target Minimum 44x44pt including padding around toggle
Edge Cases
Edge Case Handling
Toggle + settings reveal Settings panel slides open below toggle; accordion animation 200ms
Toggle with destructive off Confirmation dialog: "Disabling will delete all data. Are you sure?"
Toggle server failure Revert toggle; show inline error for 3 seconds
Rapid toggling Debounce 500ms; only send final state to server
Toggle with dependent toggles Child toggles disable when parent turns off

Case Study 3: Pull-to-Refresh

Pull-to-refresh is a gesture-triggered microinteraction invented by Loren Brichter for Tweetie (acquired by Twitter). It transforms a natural gesture (pulling down on a list) into a data refresh. It is one of the most widely adopted microinteraction patterns in mobile design.

The Four Parts

Trigger:

  • Manual trigger: pull down on a scrollable list past a threshold (~60pt)
  • The trigger is invisible -- no button exists; the gesture is the trigger
  • System fallback: auto-refresh on app foreground after X minutes (system trigger)

Rules:

  1. User must be scrolled to the top of the list for pull to activate
  2. Pulling down below threshold shows visual hint but does not trigger refresh
  3. Pulling past threshold (typically 60-80pt) "locks" the refresh
  4. Releasing after passing threshold triggers the refresh request
  5. Releasing before threshold snaps back with no refresh
  6. While refreshing, spinner remains visible at top; list is still scrollable
  7. On data received, new content animates into list; spinner dismisses
  8. On failure, spinner dismisses; error message appears briefly
  9. Minimum spinner display: 500ms (prevents flash for fast connections)

Feedback:

Pull Distance Visual Feedback Haptic Feedback
0-20pt Slight rubber-band stretch None
20-60pt Spinner icon appears, partially rotated proportional to pull None
60pt (threshold) Spinner completes rotation; visual snap indicating activation Light tap (selection feedback)
60pt+ (past threshold) Spinner remains complete; pull distance continues with resistance None
Release (past threshold) Spinner animates (spinning); list adjusts to accommodate None
Data received Spinner stops; new items slide in from top; spinner area collapses None
Error Spinner stops; brief error text ("Could not refresh"); area collapses Error pattern

Loops & Modes:

  • Auto-refresh loop: if user has not pulled-to-refresh in 5+ minutes and returns to app, auto-refresh fires (system trigger)
  • Long loop: for first 3 uses on a new device, show a subtle "Pull down to refresh" hint text
  • Rate limiting rule: ignore pull-to-refresh if last refresh was < 5 seconds ago
  • No modes
Discoverability Strategy

Pull-to-refresh has zero visible affordance -- it relies entirely on platform convention. For apps where users might not know the gesture:

Strategy Implementation When to Remove
Hint text "Pull down to refresh" text above list, visible at scroll top After 3 successful pull-to-refresh actions
Auto-refresh on first load Show the refresh animation automatically on first visit After first visit only
Visible refresh button Small refresh icon in header as fallback Never (always keep as alternative)
Platform-Specific Implementations
Platform Key Detail
iOS UIRefreshControl -- native component. Spinner is an ActivityIndicator. Threshold is system-defined.
Android SwipeRefreshLayout -- Material Design. Uses circular progress that fills as user pulls.
Web Custom implementation required. Must handle touch events; prevent native browser pull-to-refresh interference. Use overscroll-behavior: contain on scroll container.

Case Study 4: Loading States

Loading is not a single microinteraction but a family of patterns for communicating "the system is working." The design challenge is keeping users informed and engaged during a period they cannot control.

Loading Pattern Selection
Scenario Best Pattern Why
< 300ms No indicator (instant feel) Any indicator would flash distractingly
300ms - 1s Inline spinner Acknowledges loading without drama
1s - 5s Skeleton screen Shows layout immediately; reduces perceived wait
5s - 30s Determinate progress bar Users need to see actual progress
30s+ Progress bar + background option Users should be able to do other things
Unknown duration Indeterminate spinner + status text Transparency: "Processing..." then "Almost done..."
Skeleton Screen Design

Trigger: System trigger -- content request initiated.

Rules:

  1. Show skeleton immediately on navigation (within 100ms)
  2. Skeleton shapes must match the final layout precisely
  3. Use subtle pulse animation on skeleton shapes (opacity 0.3 to 0.6, 1.5s loop)
  4. Load content progressively: text first, then images
  5. Crossfade from skeleton to real content (200ms)
  6. Never show skeleton for content already in cache

Skeleton Visual Specification:

Content Type Skeleton Shape Color Animation
Text line Rounded rectangle, 60-80% width Gray-200 (#E5E7EB) Pulse 0.3-0.6 opacity
Heading Rounded rectangle, 40-50% width, taller Gray-200 Pulse 0.3-0.6 opacity
Avatar Circle, matching avatar size Gray-200 Pulse 0.3-0.6 opacity
Image Rounded rectangle, matching aspect ratio Gray-200 Pulse 0.3-0.6 opacity
Button Rounded rectangle, matching button size Gray-200 Pulse 0.3-0.6 opacity
Progress Bar Design

Trigger: System trigger -- long operation begins.

Rules:

  1. Appear within 200ms of operation start
  2. Progress must be real (based on actual progress, not fake animation)
  3. Never go backward (if real progress reverses, pause at current point)
  4. Final 5% should be server confirmation, not client processing
  5. On completion, bar fills to 100%, brief pause, then success state

Feedback:

Progress State Visual Text
0% Empty bar with subtle background "Starting upload..."
1-99% Bar fills proportionally; color stays blue "Uploading... 47%"
99% Bar nearly full; slight pause "Finalizing..."
100% Bar fills completely; transitions to green "Complete!"
Error at any point Bar turns red; stops at current position "Upload failed at 47%. Retry?"
Cancelled Bar fades out; reset "Upload cancelled."
Loading State Accessibility
Requirement Implementation
Screen reader aria-live="polite" region announces "Loading content" and "Content loaded"
Progress bar role="progressbar" with aria-valuenow, aria-valuemin, aria-valuemax
Reduced motion Replace pulse animation with static gray; replace spinner with "Loading..." text
Timeout If loading exceeds 30 seconds, announce "Still loading. You can continue waiting or try again."

Case Study 5: Notifications (Toast / Snackbar)

Notifications are transient microinteractions that communicate system events without requiring full user attention. They appear, convey a message, and disappear -- but the design details determine whether they are helpful or infuriating.

The Four Parts

Trigger:

  • System trigger: action completes (save, send, delete)
  • System trigger: external event occurs (new message, status change)
  • System trigger: error detected (network loss, permission denied)
  • Manual trigger: user action with reversible outcome (delete triggers "Undo" toast)

Rules:

  1. Appear in a consistent position (bottom-center for mobile, bottom-left or top-right for desktop)
  2. Stack if multiple appear simultaneously (limit to 3 visible; queue additional)
  3. Auto-dismiss after 5-8 seconds for informational; persist for errors until acknowledged
  4. Slide in with animation (300ms); slide out on dismiss (200ms)
  5. Must not cover critical UI elements (primary actions, navigation)
  6. If toast contains an action ("Undo"), the action must be available for the entire display duration
  7. Dismissable via swipe (mobile) or close button (desktop)

Feedback:

Notification Type Background Color Icon Auto-Dismiss Action
Success Green or dark gray Checkmark 5 seconds None or "View"
Info Blue or dark gray Info circle 5 seconds Optional link
Warning Yellow/amber Warning triangle 8 seconds "Fix" or "Dismiss"
Error Red X circle No (persist) "Retry" and "Dismiss"
Undo Dark gray Undo arrow 8 seconds "Undo" (primary)

Loops & Modes:

  • Stacking loop: if user triggers 5 actions rapidly, queue toasts; show max 3 at once
  • Long loop: if same notification appears 3+ times in a session, batch: "3 items saved"
  • Consolidation: "3 files uploaded" instead of three separate "File uploaded" toasts
  • No modes
Toast Layout Specification
┌────────────────────────────────────────────────┐
│  [Icon]  Message text here          [Action] [X]│
│          Secondary text (optional)              │
└────────────────────────────────────────────────┘
Element Specification
Width Min 288px, max 568px (desktop); full-width minus margins (mobile)
Height Min 48px, max 112px (2 lines + action)
Padding 16px horizontal, 12px vertical
Border radius 8px
Shadow Medium elevation (shadow-md)
Position Bottom-center (mobile), bottom-left or top-right (desktop), 16px from edge
Z-index Above all content, below modals and dialogs
Animation Specification
Transition Duration Easing Direction
Enter 300ms ease-out (deceleration) Slide up from below (mobile) or slide in from right (desktop)
Exit (auto-dismiss) 200ms ease-in (acceleration) Slide down or fade out
Exit (swipe dismiss) 150ms ease-out Follow swipe direction
Stack push 200ms ease-in-out Existing toasts shift up to accommodate new one
Accessibility
Requirement Implementation
Screen reader role="status" with aria-live="polite" (info/success); role="alert" with aria-live="assertive" (error)
Focus management Do not steal focus from user's current position; action button reachable via Tab
Keyboard Esc key dismisses; Tab reaches action buttons
Timeout For error toasts, no auto-dismiss; for info toasts, pause timer on hover/focus
Reduced motion Replace slide animation with fade (200ms)
Edge Cases
Edge Case Handling
10 toasts triggered at once Queue: show 3; dismiss oldest first; show queued
Toast covers primary action Reposition toast above the action; or provide alternative placement
User clicks Undo at last second Accept undo if within the timeout window, even if fade-out started
Toast during full-screen mode Overlay on top of full-screen content with higher z-index
Long text content Truncate at 2 lines with "..." and "Show more" link
Network loss while showing "Undo" Queue undo action locally; execute when connection returns

Cross-Cutting Patterns

Patterns That Apply Across All Case Studies
Pattern Application Example
Debouncing Prevent rapid duplicate triggers Double-click submit, rapid toggle, pull-to-refresh spam
Optimistic UI Show result before server confirms Toggle, like, delete with undo
Progressive disclosure Show simple first, details on demand Error summary first, full details expandable
Graceful degradation Work without JavaScript, animation, or haptics Form submits via native HTML; toggle works without animation
Accessibility baseline All patterns must work for all users ARIA roles, keyboard operation, reduced motion, screen reader
State persistence Preserve user work across interruptions Form drafts, scroll position, toggle state
1# Microinteraction Case Studies
2 
3Detailed design breakdowns of common UI patterns, analyzed through the four-part microinteraction structure: Trigger, Rules, Feedback, and Loops & Modes. Each case study documents the interaction from first use through edge cases, providing a practical blueprint for implementation.
4 
5## Table of Contents
61. [Case Study 1: Form Submission](#case-study-1-form-submission)
72. [Case Study 2: Toggle / Switch](#case-study-2-toggle-switch)
83. [Case Study 3: Pull-to-Refresh](#case-study-3-pull-to-refresh)
94. [Case Study 4: Loading States](#case-study-4-loading-states)
105. [Case Study 5: Notifications (Toast / Snackbar)](#case-study-5-notifications-toast-snackbar)
116. [Cross-Cutting Patterns](#cross-cutting-patterns)
12 
13---
14 
15## Case Study 1: Form Submission
16 
17A form submission microinteraction covers the moment from when the user taps "Submit" to when they receive confirmation of success or details of failure. It is one of the highest-stakes microinteractions because users have invested time and data.
18 
19### The Four Parts
20 
21**Trigger:**
22- Manual trigger: "Submit" button (primary action, full-width or prominent)
23- Keyboard trigger: Enter key in last field (convention, not always expected)
24- System trigger: Auto-save draft after 30 seconds of inactivity (background)
25 
26**Rules:**
271. On trigger, validate all required fields client-side before sending to server
282. If validation fails, prevent submission and highlight first invalid field
293. If validation passes, disable submit button and show loading state
304. Send data to server
315. On server success (200), show success feedback and redirect or reset form
326. On server error (4xx/5xx), show error message and preserve all input
337. On network timeout (>15 seconds), show retry option with preserved input
34 
35**Feedback:**
36 
37| State | Visual | Copy | Duration |
38|-------|--------|------|----------|
39| **Idle** | Blue "Submit" button, normal state | "Submit" or "Create Account" | Persistent |
40| **Validating** | Button briefly disabled | "Checking..." | 0-500ms |
41| **Validation error** | Red border on invalid fields, scroll to first error | "Please enter a valid email" inline | Until corrected |
42| **Submitting** | Button shows spinner, text changes | "Submitting..." | Server response time |
43| **Success** | Green checkmark replaces spinner | "Done! Redirecting..." | 1-2 seconds |
44| **Server error** | Red banner at top, button re-enabled | "Something went wrong. Please try again." | Until dismissed |
45| **Network error** | Yellow banner, retry button | "Connection lost. Your data is saved locally." | Until retry succeeds |
46 
47**Loops & Modes:**
48- Auto-save loop: draft saved to local storage every 30 seconds (open loop)
49- Long loop: after 3+ submissions, hide optional tooltips and field hints
50- No modes (single-purpose interaction)
51 
52### Edge Cases
53 
54| Edge Case | Handling |
55|-----------|---------|
56| User double-clicks submit | Disable button on first click; debounce server request |
57| User navigates away mid-submission | Show "Unsaved changes" dialog; save draft to local storage |
58| Session expires during submission | Queue submission; re-authenticate and retry |
59| Very long form (20+ fields) | Show progress indicator; validate sections independently |
60| Paste of formatted text | Strip formatting; accept plain text only |
61| Autofill conflict | Accept autofill values; re-validate on submit |
62 
63### Implementation Notes
64 
65| Platform | Key Detail |
66|----------|-----------|
67| **Web** | Use `<form>` native validation as baseline; enhance with JS. Preserve form data in `sessionStorage`. |
68| **iOS** | Use `UITextFieldDelegate` for per-field validation. Keyboard "Return" key should move to next field, not submit. |
69| **Android** | `TextInputLayout` with `setError()` for inline validation. Handle back button to save draft. |
70 
71---
72 
73## Case Study 2: Toggle / Switch
74 
75A toggle is a binary microinteraction: on or off. Despite its apparent simplicity, a well-designed toggle requires careful attention to state communication, animation timing, and accessibility.
76 
77### The Four Parts
78 
79**Trigger:**
80- Manual trigger: tap/click anywhere on the toggle (track or thumb)
81- Keyboard trigger: Space bar when toggle is focused
82- Drag trigger: drag thumb from one position to the other
83- System trigger: external state change (admin disables feature remotely)
84 
85**Rules:**
861. On trigger, immediately start transition animation
872. If action requires server confirmation, send request in background
883. Toggling on may trigger additional UI (reveal settings, enable features)
894. Toggling off may trigger confirmation dialog for destructive changes
905. If server rejects the change, revert toggle to previous state with error message
916. Rapid toggling (clicking multiple times fast) should debounce: only the final state is sent
92 
93**Feedback:**
94 
95| State | Thumb Position | Track Color | Label (if used) | Haptic |
96|-------|---------------|-------------|-----------------|--------|
97| **Off** | Left | Gray (#E5E7EB) | "Off" | None |
98| **Transitioning on** | Sliding right | Transitioning to green | -- | None |
99| **On** | Right | Green (#22C55E) | "On" | Light tap |
100| **Transitioning off** | Sliding left | Transitioning to gray | -- | None |
101| **Disabled** | Current position | Faded (40% opacity) | "Unavailable" | None |
102| **Loading** | Current position | Faded with inline spinner | "Updating..." | None |
103| **Error** | Reverted position | Flash red briefly, return to normal | "Failed to update" | Error pattern |
104 
105**Loops & Modes:**
106- No traditional loop (single action)
107- Long loop: if toggle controls a feature with settings, first 3 toggles might show a tooltip explaining the feature
108- No modes
109 
110### Animation Specification
111 
112| Property | Value | Easing |
113|----------|-------|--------|
114| Thumb position (left to right) | 150-200ms | ease-in-out |
115| Track color transition | 150-200ms | ease-in-out (synchronized with thumb) |
116| Thumb shadow on drag | 100ms to enlarge shadow | ease-out |
117| Revert on error | 200ms | ease-out with red flash |
118 
119### Accessibility
120 
121| Requirement | Implementation |
122|-------------|---------------|
123| **ARIA role** | `role="switch"` with `aria-checked="true/false"` |
124| **Focus indicator** | 2px blue outline around entire toggle on Tab focus |
125| **Keyboard** | Space bar toggles; no Enter (per switch role spec) |
126| **Screen reader** | "Wi-Fi, switch, on" -- announces label, role, and state |
127| **Reduced motion** | Skip animation; instant state change |
128| **Touch target** | Minimum 44x44pt including padding around toggle |
129 
130### Edge Cases
131 
132| Edge Case | Handling |
133|-----------|---------|
134| Toggle + settings reveal | Settings panel slides open below toggle; accordion animation 200ms |
135| Toggle with destructive off | Confirmation dialog: "Disabling will delete all data. Are you sure?" |
136| Toggle server failure | Revert toggle; show inline error for 3 seconds |
137| Rapid toggling | Debounce 500ms; only send final state to server |
138| Toggle with dependent toggles | Child toggles disable when parent turns off |
139 
140---
141 
142## Case Study 3: Pull-to-Refresh
143 
144Pull-to-refresh is a gesture-triggered microinteraction invented by Loren Brichter for Tweetie (acquired by Twitter). It transforms a natural gesture (pulling down on a list) into a data refresh. It is one of the most widely adopted microinteraction patterns in mobile design.
145 
146### The Four Parts
147 
148**Trigger:**
149- Manual trigger: pull down on a scrollable list past a threshold (~60pt)
150- The trigger is invisible -- no button exists; the gesture is the trigger
151- System fallback: auto-refresh on app foreground after X minutes (system trigger)
152 
153**Rules:**
1541. User must be scrolled to the top of the list for pull to activate
1552. Pulling down below threshold shows visual hint but does not trigger refresh
1563. Pulling past threshold (typically 60-80pt) "locks" the refresh
1574. Releasing after passing threshold triggers the refresh request
1585. Releasing before threshold snaps back with no refresh
1596. While refreshing, spinner remains visible at top; list is still scrollable
1607. On data received, new content animates into list; spinner dismisses
1618. On failure, spinner dismisses; error message appears briefly
1629. Minimum spinner display: 500ms (prevents flash for fast connections)
163 
164**Feedback:**
165 
166| Pull Distance | Visual Feedback | Haptic Feedback |
167|--------------|----------------|-----------------|
168| **0-20pt** | Slight rubber-band stretch | None |
169| **20-60pt** | Spinner icon appears, partially rotated proportional to pull | None |
170| **60pt (threshold)** | Spinner completes rotation; visual snap indicating activation | Light tap (selection feedback) |
171| **60pt+ (past threshold)** | Spinner remains complete; pull distance continues with resistance | None |
172| **Release (past threshold)** | Spinner animates (spinning); list adjusts to accommodate | None |
173| **Data received** | Spinner stops; new items slide in from top; spinner area collapses | None |
174| **Error** | Spinner stops; brief error text ("Could not refresh"); area collapses | Error pattern |
175 
176**Loops & Modes:**
177- Auto-refresh loop: if user has not pulled-to-refresh in 5+ minutes and returns to app, auto-refresh fires (system trigger)
178- Long loop: for first 3 uses on a new device, show a subtle "Pull down to refresh" hint text
179- Rate limiting rule: ignore pull-to-refresh if last refresh was < 5 seconds ago
180- No modes
181 
182### Discoverability Strategy
183 
184Pull-to-refresh has zero visible affordance -- it relies entirely on platform convention. For apps where users might not know the gesture:
185 
186| Strategy | Implementation | When to Remove |
187|----------|---------------|----------------|
188| **Hint text** | "Pull down to refresh" text above list, visible at scroll top | After 3 successful pull-to-refresh actions |
189| **Auto-refresh on first load** | Show the refresh animation automatically on first visit | After first visit only |
190| **Visible refresh button** | Small refresh icon in header as fallback | Never (always keep as alternative) |
191 
192### Platform-Specific Implementations
193 
194| Platform | Key Detail |
195|----------|-----------|
196| **iOS** | `UIRefreshControl` -- native component. Spinner is an `ActivityIndicator`. Threshold is system-defined. |
197| **Android** | `SwipeRefreshLayout` -- Material Design. Uses circular progress that fills as user pulls. |
198| **Web** | Custom implementation required. Must handle touch events; prevent native browser pull-to-refresh interference. Use `overscroll-behavior: contain` on scroll container. |
199 
200---
201 
202## Case Study 4: Loading States
203 
204Loading is not a single microinteraction but a family of patterns for communicating "the system is working." The design challenge is keeping users informed and engaged during a period they cannot control.
205 
206### Loading Pattern Selection
207 
208| Scenario | Best Pattern | Why |
209|----------|-------------|-----|
210| **< 300ms** | No indicator (instant feel) | Any indicator would flash distractingly |
211| **300ms - 1s** | Inline spinner | Acknowledges loading without drama |
212| **1s - 5s** | Skeleton screen | Shows layout immediately; reduces perceived wait |
213| **5s - 30s** | Determinate progress bar | Users need to see actual progress |
214| **30s+** | Progress bar + background option | Users should be able to do other things |
215| **Unknown duration** | Indeterminate spinner + status text | Transparency: "Processing..." then "Almost done..." |
216 
217### Skeleton Screen Design
218 
219**Trigger:** System trigger -- content request initiated.
220 
221**Rules:**
2221. Show skeleton immediately on navigation (within 100ms)
2232. Skeleton shapes must match the final layout precisely
2243. Use subtle pulse animation on skeleton shapes (opacity 0.3 to 0.6, 1.5s loop)
2254. Load content progressively: text first, then images
2265. Crossfade from skeleton to real content (200ms)
2276. Never show skeleton for content already in cache
228 
229**Skeleton Visual Specification:**
230 
231| Content Type | Skeleton Shape | Color | Animation |
232|-------------|---------------|-------|-----------|
233| **Text line** | Rounded rectangle, 60-80% width | Gray-200 (#E5E7EB) | Pulse 0.3-0.6 opacity |
234| **Heading** | Rounded rectangle, 40-50% width, taller | Gray-200 | Pulse 0.3-0.6 opacity |
235| **Avatar** | Circle, matching avatar size | Gray-200 | Pulse 0.3-0.6 opacity |
236| **Image** | Rounded rectangle, matching aspect ratio | Gray-200 | Pulse 0.3-0.6 opacity |
237| **Button** | Rounded rectangle, matching button size | Gray-200 | Pulse 0.3-0.6 opacity |
238 
239### Progress Bar Design
240 
241**Trigger:** System trigger -- long operation begins.
242 
243**Rules:**
2441. Appear within 200ms of operation start
2452. Progress must be real (based on actual progress, not fake animation)
2463. Never go backward (if real progress reverses, pause at current point)
2474. Final 5% should be server confirmation, not client processing
2485. On completion, bar fills to 100%, brief pause, then success state
249 
250**Feedback:**
251 
252| Progress State | Visual | Text |
253|---------------|--------|------|
254| **0%** | Empty bar with subtle background | "Starting upload..." |
255| **1-99%** | Bar fills proportionally; color stays blue | "Uploading... 47%" |
256| **99%** | Bar nearly full; slight pause | "Finalizing..." |
257| **100%** | Bar fills completely; transitions to green | "Complete!" |
258| **Error at any point** | Bar turns red; stops at current position | "Upload failed at 47%. Retry?" |
259| **Cancelled** | Bar fades out; reset | "Upload cancelled." |
260 
261### Loading State Accessibility
262 
263| Requirement | Implementation |
264|-------------|---------------|
265| Screen reader | `aria-live="polite"` region announces "Loading content" and "Content loaded" |
266| Progress bar | `role="progressbar"` with `aria-valuenow`, `aria-valuemin`, `aria-valuemax` |
267| Reduced motion | Replace pulse animation with static gray; replace spinner with "Loading..." text |
268| Timeout | If loading exceeds 30 seconds, announce "Still loading. You can continue waiting or try again." |
269 
270---
271 
272## Case Study 5: Notifications (Toast / Snackbar)
273 
274Notifications are transient microinteractions that communicate system events without requiring full user attention. They appear, convey a message, and disappear -- but the design details determine whether they are helpful or infuriating.
275 
276### The Four Parts
277 
278**Trigger:**
279- System trigger: action completes (save, send, delete)
280- System trigger: external event occurs (new message, status change)
281- System trigger: error detected (network loss, permission denied)
282- Manual trigger: user action with reversible outcome (delete triggers "Undo" toast)
283 
284**Rules:**
2851. Appear in a consistent position (bottom-center for mobile, bottom-left or top-right for desktop)
2862. Stack if multiple appear simultaneously (limit to 3 visible; queue additional)
2873. Auto-dismiss after 5-8 seconds for informational; persist for errors until acknowledged
2884. Slide in with animation (300ms); slide out on dismiss (200ms)
2895. Must not cover critical UI elements (primary actions, navigation)
2906. If toast contains an action ("Undo"), the action must be available for the entire display duration
2917. Dismissable via swipe (mobile) or close button (desktop)
292 
293**Feedback:**
294 
295| Notification Type | Background Color | Icon | Auto-Dismiss | Action |
296|------------------|-----------------|------|-------------|--------|
297| **Success** | Green or dark gray | Checkmark | 5 seconds | None or "View" |
298| **Info** | Blue or dark gray | Info circle | 5 seconds | Optional link |
299| **Warning** | Yellow/amber | Warning triangle | 8 seconds | "Fix" or "Dismiss" |
300| **Error** | Red | X circle | No (persist) | "Retry" and "Dismiss" |
301| **Undo** | Dark gray | Undo arrow | 8 seconds | "Undo" (primary) |
302 
303**Loops & Modes:**
304- Stacking loop: if user triggers 5 actions rapidly, queue toasts; show max 3 at once
305- Long loop: if same notification appears 3+ times in a session, batch: "3 items saved"
306- Consolidation: "3 files uploaded" instead of three separate "File uploaded" toasts
307- No modes
308 
309### Toast Layout Specification
310 
311```
312┌────────────────────────────────────────────────┐
313│ [Icon] Message text here [Action] [X]│
314│ Secondary text (optional) │
315└────────────────────────────────────────────────┘
316```
317 
318| Element | Specification |
319|---------|--------------|
320| Width | Min 288px, max 568px (desktop); full-width minus margins (mobile) |
321| Height | Min 48px, max 112px (2 lines + action) |
322| Padding | 16px horizontal, 12px vertical |
323| Border radius | 8px |
324| Shadow | Medium elevation (shadow-md) |
325| Position | Bottom-center (mobile), bottom-left or top-right (desktop), 16px from edge |
326| Z-index | Above all content, below modals and dialogs |
327 
328### Animation Specification
329 
330| Transition | Duration | Easing | Direction |
331|-----------|----------|--------|-----------|
332| Enter | 300ms | ease-out (deceleration) | Slide up from below (mobile) or slide in from right (desktop) |
333| Exit (auto-dismiss) | 200ms | ease-in (acceleration) | Slide down or fade out |
334| Exit (swipe dismiss) | 150ms | ease-out | Follow swipe direction |
335| Stack push | 200ms | ease-in-out | Existing toasts shift up to accommodate new one |
336 
337### Accessibility
338 
339| Requirement | Implementation |
340|-------------|---------------|
341| Screen reader | `role="status"` with `aria-live="polite"` (info/success); `role="alert"` with `aria-live="assertive"` (error) |
342| Focus management | Do not steal focus from user's current position; action button reachable via Tab |
343| Keyboard | Esc key dismisses; Tab reaches action buttons |
344| Timeout | For error toasts, no auto-dismiss; for info toasts, pause timer on hover/focus |
345| Reduced motion | Replace slide animation with fade (200ms) |
346 
347### Edge Cases
348 
349| Edge Case | Handling |
350|-----------|---------|
351| 10 toasts triggered at once | Queue: show 3; dismiss oldest first; show queued |
352| Toast covers primary action | Reposition toast above the action; or provide alternative placement |
353| User clicks Undo at last second | Accept undo if within the timeout window, even if fade-out started |
354| Toast during full-screen mode | Overlay on top of full-screen content with higher z-index |
355| Long text content | Truncate at 2 lines with "..." and "Show more" link |
356| Network loss while showing "Undo" | Queue undo action locally; execute when connection returns |
357 
358---
359 
360## Cross-Cutting Patterns
361 
362### Patterns That Apply Across All Case Studies
363 
364| Pattern | Application | Example |
365|---------|-------------|---------|
366| **Debouncing** | Prevent rapid duplicate triggers | Double-click submit, rapid toggle, pull-to-refresh spam |
367| **Optimistic UI** | Show result before server confirms | Toggle, like, delete with undo |
368| **Progressive disclosure** | Show simple first, details on demand | Error summary first, full details expandable |
369| **Graceful degradation** | Work without JavaScript, animation, or haptics | Form submits via native HTML; toggle works without animation |
370| **Accessibility baseline** | All patterns must work for all users | ARIA roles, keyboard operation, reduced motion, screen reader |
371| **State persistence** | Preserve user work across interruptions | Form drafts, scroll position, toggle state |
372 

Discussion

Alternatives

ImpeccableUse when the user wants to design, redesign, shape, critique, audit, polish, clarify, distill, harden, optimize, adapt, animate, colorize, extract, or otherwise improve a frontend interface. Covers websites, landing pages, dashboards, product UI, app shells, components, forms, settings, onboarding, and empty states. Handles UX review, visual hierarchy, information architecture, cognitive load, accessibility, performance, responsive behavior, theming, anti-patterns, typography, fonts, spacing, layout, alignment, color, motion, micro-interactions, UX copy, error states, edge cases, i18n, and reusable design systems or tokens. Also use for bland designs that need to become bolder or more delightful, loud designs that should become quieter, live browser iteration on UI elements, or ambitious visual effects that should feel technically extraordinary. Not for backend-only or non-UI tasks.Design & UI · Apache-2.0Apple designApple's approach to interface design and fluid, physical motion, translated for the web. Use when building or reviewing gesture-driven UI, spring animations, drag/swipe/sheet interactions, momentum and interruptible transitions, translucent materials and depth, typography (optical sizing, tracking, leading), reduced-motion, or the design foundations (feedback, spatial consistency, restraint) behind Apple-style interfaces.Design & UI · MITBuilding AnimationsBuild an animation from scratch, making the decisions in the order that determines whether it feels right — should it animate at all, what purpose, which tool, which properties, which curve and duration, how it interrupts, how it exits. Writes the implementation. Use when asked to animate something, add motion, make a component feel alive, or build a transition. For critiquing existing motion use review-animations; for auditing a whole codebase use improve-animations.Design & UI · MITBreakRenders a component you choose in every state and scenario on a temporary page and stress tests it.Design & UI · MIT