UX/UI Cataloging Framework
Two things must happen for every UI element you log: describe it precisely enough that someone could redraw it without seeing it, and explain why it works using an actual mechanism — not "this is intuitive" or "this feels good," which say nothing. Use the psychology/UX glossary at the bottom to name the real mechanism.
The bar is "someone could rebuild this from your notes alone." Not "a design student could
recognize this app from your notes" — an actual rebuild. That means preferring real extracted
values (hex colors, px spacing, exact font sizes, exact animation durations/easing) over
adjectives ("bouncy," "tight spacing") whenever the value is extractable. See
research-playbook.md for the technique (inspecting computed CSS via the JS tool) that makes
this possible instead of eyeballing screenshots. Where a value genuinely isn't extractable
(a native-app-only gesture with no web equivalent to inspect), a precise qualitative
description is the fallback — but reach for the real number first.
Mobile is the primary target. Set the browser to a mobile viewport before you start observing any screen (see the playbook for how) — these products are designed thumb-first, and desktop web often hides, collapses, or redesigns the interactions that actually define the product (bottom tab bars, swipe gestures, thumb-zone button placement, full-bleed media). Note explicitly if a mobile web view still diverges from what the native app looks like (e.g. an "open in app" banner replacing a feature) — that's a real gap to flag, not something to paper over, but mobile web is still much closer to the real product than desktop.
What to catalog, at two levels
Level 1 — Screen inventory
For every major screen (home feed, post detail, profile, composer, search/explore, notifications, messages, settings), log:
- Layout structure — nav placement (top/bottom/side), content hierarchy, information density, how much of the viewport is chrome vs content
- Entry/exit transition — how you arrive at this screen and how you leave it (push, modal sheet, cross-fade, tab switch)
- Loading state — spinner, skeleton screens (and their shape — do they mimic the real content layout?), progressive image loading (blur-up, low-res placeholder)
- Empty state — what shows when there's nothing to display, and what it nudges the user toward
- Error/offline state
Level 2 — Component/interaction catalog
For every interactive element (buttons, gestures, indicators), log a row like this:
| Field | What to capture |
|---|---|
| Element | The specific control (e.g. "like button," "pull-to-refresh," "story ring") |
| Location/context | Where it appears and in what states it's visible |
| Visual states | Default / hover / pressed / disabled / loading — what changes in each |
| Trigger | Tap, long-press, double-tap, swipe direction, drag, hold-and-drag |
| Exact values | Pull real numbers via computed-CSS inspection (see the playbook): hex/rgb |
| color, padding/margin in px, border-radius, font-family/weight/size/line-height, box-shadow, | |
| icon stroke width. This is what separates a rebuildable spec from a description. | |
| Motion spec | What animates (scale, opacity, position, color). Prefer the exact duration and |
timing-function pulled from the element's CSS transition/animation properties or a |
|
matching @keyframes rule (see the playbook) over guessing. Only fall back to a qualitative |
|
| description ("overshoots slightly then settles — spring physics, not linear") when the | |
| interaction is a native-app gesture with no inspectable CSS behind it. | |
| Feedback | Haptic buzz, sound, visual confirmation (checkmark, color fill, particle burst) |
| Why it works | The named mechanism (see glossary) — be specific about what behavior it's |
| reinforcing or what cognitive load it's reducing | |
| Accessibility | Screen-reader label, whether reduced-motion disables it, touch target size |
Animations to always check (the ones people miss)
- Pull-to-refresh — elastic resistance curve, release threshold, spinner/icon morph
- Infinite scroll load-more — skeleton rows fading in, or content just appearing (jank vs smooth insertion)
- Like/heart burst — scale-up-and-fade particle effect, color fill animation, double-tap overlay heart (large, brief, center-of-image)
- Optimistic UI updates — does a comment/like appear instantly before server confirmation, and what happens visually if it fails (silent revert vs error toast)?
- Page/screen transitions — push (slide from right) vs modal (slide from bottom) vs cross-fade vs tab switch (instant vs animated indicator slide)
- Skeleton loading shimmer — direction and speed of the shimmer sweep
- Pull-down-to-dismiss modals — rubber-banding, dismiss velocity threshold
- Story progress bar — segment fill timing, pause-on-hold, tap-to-skip zones
- Notification badge — pop-in animation, count increment (does the number animate or snap?)
- Toast/snackbar — entry direction, auto-dismiss timing, swipe-to-dismiss
- Button press states — scale-down-on-press (how much, e.g. ~96%), color darken
- Swipe gestures on list items — swipe-to-reply, swipe-to-dismiss, reveal-action-buttons
- Tab bar icon transitions — outline-to-filled icon swap, color transition, badge dot
- Carousel/gallery swipe — paging snap behavior, dot indicator animation, parallax if any
- Video autoplay-on-scroll — the intersection threshold that triggers autoplay, default mute state, the mute-toggle affordance, and what happens on scroll-away (pause vs pip-to-corner)
- Long-press context menus — background blur/dim, menu spring-in, haptic on trigger
"Why it works" glossary — use real mechanisms, not vibes
| Mechanism | What it explains |
|---|---|
| Variable reward schedule (operant conditioning) | Why unpredictable engagement counts / new-content availability on refresh keeps people checking — same mechanism as a slot machine |
| Optimistic UI | Why actions feel instant even over a slow network — the UI updates before the server confirms, removing perceived latency |
| Doherty Threshold (~400ms) | Why any interaction slower than this needs a loading indicator or people perceive the app as broken |
| Fitts's Law | Why frequently-used targets (compose button, like button) are large and placed within easy thumb reach |
| Hick's Law | Why menus and toolbars keep visible options few, pushing rare actions into an overflow/"more" menu |
| Peak–end rule | Why the last moment of a flow (post published, story completed) often gets a distinct celebratory animation — it's what people remember |
| Zeigarnik effect | Why unread badges, incomplete profile meters, and streaks nag at attention — unfinished tasks stay cognitively "open" |
| Social proof | Why like/comment/share counts are prominent — they signal what's worth your attention before you've evaluated it yourself |
| Loss aversion / FOMO | Why streaks, "X people you follow just posted," and ephemeral stories create urgency — the fear of losing something outweighs the promise of gaining it |
| Progressive disclosure | Why composer options (poll, location, alt text) are tucked behind a "+" rather than all shown at once |
| Recognition over recall | Why icons are paired with instantly-recognizable metaphors (heart, speech bubble, arrow) instead of requiring users to remember what a control does |
| Direct manipulation | Why pull-to-refresh/swipe gestures feel more satisfying than a tap-triggered refresh button — the UI response is physically coupled to the gesture |
When you write the "why it works" line for a real element, name the mechanism and connect it to the specific business outcome (time-on-app, posting frequency, return visits) — don't just cite the glossary term and stop.