Android: the motion half of the native-feel pass, judged on the device #213

Open
opened 2026-08-24 07:50:52 +00:00 by logan · 0 comments
Collaborator

Report

Split out of #54, which asked for two things and shipped one. The tap
highlight is gone and the surfaces that lost their only touch feedback
have a press state (PR to follow). What #54 also asked for and this
carries is the other half of its title: "add native-feeling motion"
"small, smooth animations and press states" and, in its Direction,
"press states (a quick scale/opacity on active), view transitions
between screens".

Findings

  • Motion here is a device judgement, and no tier in this repo can
    make it.
    Two of the app's card grids carry the comment
    transitions removed — software rendering repaints per frame
    (artists-view, genres-view), so this codebase already has a
    measured statement that transitions on a list cost something real on
    the renderer it ships on. Adding them back — anywhere — needs the
    same measurement on the reference device (Chrome 113, 424x439), not
    a preference. 58 transition: declarations exist elsewhere, so this
    is not a blanket ban; it is that nobody has measured these
    surfaces.
  • The press states themselves are done and are deliberately
    instant
    , in both directions. A transition on the way in reads as
    lag on the one piece of feedback a tap has; a fade on the way out is
    the pleasant half and is exactly what wants measuring. CSS can
    express that asymmetry (transition on the base rule, transition: none in the :active rule), so this is a decision rather than a
    limitation.
  • A view transition is a shell change, not a stylesheet one.
    index.ts keeps every primary view mounted and toggles a
    .view-hidden class, precisely so scrollTop survives a
    navigation — so a cross-fade or slide has to happen between two
    elements that are both in the DOM, and it interacts with the history
    stack (popstate replays a navigation with _isBack, and a
    transition that plays "forwards" on a back press is worse than
    none). It also has to answer prefers-reduced-motion, which in this
    app outranks an app setting.
  • The View Transitions API is Chrome 111 for same-document
    transitions, so the reference device does have it — worth knowing
    before hand-rolling one, and worth checking against the paint
    containment on .main-panel that #60 measured.

Direction

Take it on a device, not in a browser: measure a candidate (the press
fade first, since it is the cheapest and the most-touched surface) at
424x439 on the reference phone, keep it only if it does not cost frames
on a scroll, and gate every one of them behind prefers-reduced-motion: reduce. If the answer turns out to be "the renderer cannot afford it",
that is a perfectly good outcome and belongs written down here — it is
the same shape as the two card grids' comment, made once for the whole
app instead of twice in passing.

**Report** Split out of #54, which asked for two things and shipped one. The tap highlight is gone and the surfaces that lost their only touch feedback have a press state (PR to follow). What #54 also asked for and this carries is the other half of its title: *"add native-feeling motion"* — "small, smooth animations and press states" and, in its Direction, "press states (a quick scale/opacity on active), view transitions between screens". **Findings** - **Motion here is a device judgement, and no tier in this repo can make it.** Two of the app's card grids carry the comment `transitions removed — software rendering repaints per frame` (`artists-view`, `genres-view`), so this codebase already has a measured statement that transitions on a list cost something real on the renderer it ships on. Adding them back — anywhere — needs the same measurement on the reference device (Chrome 113, 424x439), not a preference. 58 `transition:` declarations exist elsewhere, so this is not a blanket ban; it is that nobody has measured *these* surfaces. - **The press states themselves are done and are deliberately instant**, in both directions. A transition on the way *in* reads as lag on the one piece of feedback a tap has; a fade on the way out is the pleasant half and is exactly what wants measuring. CSS can express that asymmetry (`transition` on the base rule, `transition: none` in the `:active` rule), so this is a decision rather than a limitation. - **A view transition is a shell change, not a stylesheet one.** `index.ts` keeps every primary view mounted and toggles a `.view-hidden` class, precisely so `scrollTop` survives a navigation — so a cross-fade or slide has to happen between two elements that are both in the DOM, and it interacts with the history stack (`popstate` replays a navigation with `_isBack`, and a transition that plays "forwards" on a back press is worse than none). It also has to answer `prefers-reduced-motion`, which in this app outranks an app setting. - The View Transitions API is Chrome 111 for same-document transitions, so the reference device *does* have it — worth knowing before hand-rolling one, and worth checking against the paint containment on `.main-panel` that #60 measured. **Direction** Take it on a device, not in a browser: measure a candidate (the press fade first, since it is the cheapest and the most-touched surface) at 424x439 on the reference phone, keep it only if it does not cost frames on a scroll, and gate every one of them behind `prefers-reduced-motion: reduce`. If the answer turns out to be "the renderer cannot afford it", that is a perfectly good outcome and belongs written down here — it is the same shape as the two card grids' comment, made once for the whole app instead of twice in passing.
logan added the Area/Design
Priority
Low
4
Platform/AndroidKind/Enhancement
labels 2026-08-24 07:50:52 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: yonlu/yellowjacket#213