Lab Mock content

Four decisions that changed the feel.

The card interaction study went through more than forty iterations. These are the four changes that mattered most. Each one runs the same recorded gesture through the old rule and the new rule, so you can watch where they disagree. Then drag on a phone to feed in your own.mock The four preset gestures are synthesised from typical values, not captured from a person.

01v1 → v12 → now

Close on where the pull is going, not where it is

The problem
The first versions looked at distance only. A short fast flick was cancelled, and a long pull that you were already taking back was closed. The case study counted 31% missed closes. mock
The change
At release the sheet projects the pull forward: distance + release velocity × τ. If that lands past 35% of the sheet height, it closes. A pull shorter than 16 px never counts.
Why
People judge intent by speed first and distance second. The projection is one multiplication, cheap enough to show and tune.
  • mock 38% as the old line (v12)

Showing Short fast flick: About 150 px in 125 ms, still accelerating at lift-off. With JavaScript this replays and you can record your own.

Old rulev12 · distance only
cardRead more →close line

Stayed open

139 px < 243 px

Old rule: only the distance counts. You let go 139 px down; the line is 243 px (38% of the sheet). Short of it, so it stayed open, however fast you were going.

New rulenow · projected
cardRead more →close line

Closed

139 px + 1.59 × 80 ms = 267 px > 224 px

New rule: where was it going? 139 px so far, moving 1.59 px/ms down, so 80 ms later it would be 267 px. The line is 224 px (35%). Past it, so it closed.

One tunable: the look-ahead

The new rule closes when distance + velocity × τ passes 35% of the sheet. τ is how far ahead it looks. The table re-runs both rules on all recordings as you move it (τ = 0 is the old distance-only idea, at 35% instead of 38%).

Shipped: 80 ms. The slider needs JavaScript.

Outcome of each rule for every recording
RecordingOld ruleNew rule
Short fast flickStayed openClosed
Pull far, then swing back upClosedStayed open
Ordinary pullClosedClosed
Accidental twitchStayed openStayed open

Why 80 ms. On these four recordings the right answer holds for roughly 55 to 125 ms. Below that, the flick is missed again; above it, the twitch starts to close the sheet. 80 ms is about five frames at 60 Hz, inside the window and a little on the cautious side. It is still to be tuned by hand on a phone. mock

02v18.0.4 → v18.0.5

Close the picture first, let the text go

The problem
Closing shrank the whole sheet as one piece. The text was squashed on the way down and the picture reached its card late.
The change
The picture flies straight to the card on its own spring. The text is already gone by the 40% mark, so nothing readable is ever distorted.
Why
The picture is the thing that must be recognised on arrival; the text only has to get out of the way.
  • mock old spring stiffness 170 (slower than today’s 300)

Showing Ordinary pull: Steady pull, release, close. With JavaScript this replays and you can record your own.

Old choreographyv18.0.4 · all at once
cardRead more →

Closed

picture lands 480 ms, text squashed ×0.21

v18.0.4 and earlier: the whole sheet shrinks as one piece. The text is squashed on the way down (to 21% of its height) and the picture only reaches the card at 480 ms.

New choreographyv18.0.5+ · hero first
cardRead more →

Closed

picture lands 360 ms, text gone by 80 ms

v18.0.5+: the text fades out first (gone by 80 ms) while the picture flies straight to the card, landing at 360 ms. Nothing is squashed.

03v20.0.5 → v20.0.7

A drag is not a tap, and an echo is not a tap

The problem
Pulling the sheet down from a link lifted the finger over that link and the browser fired a click. And the echo of the tap that opened the sheet could land on the backdrop and close it right away.
The change
A press that moves past a slop (8 px mouse, 10 px touch) is a drag, and the click that follows it is swallowed once. A backdrop tap in the first 260 ms after opening is ignored.
Why
Taps must still work with a shaky finger, so the slop is small. The grace window is long enough for a ghost click and short enough that nobody notices it.
  • mock “ghost click arrives 120 ms after opening” (typical, not measured)

Showing Pull that starts on a link: The finger lands on "Read more", drags the sheet down 78 px and lets go. With JavaScript this replays and you can record your own.

Old guardv20.0.5 · none
cardRead more →

Link fired

click leaked after the pull

v20.0.5 and earlier: the finger started on the link, dragged the sheet and lifted off still on the link (the sheet moves with the finger), so the browser fired a click. A pull navigated away.

New guardv20.0.7+ · slop + grace
cardRead more →

Click swallowed

moved 78 px (> 10 px slop) = a drag

v20.0.6+: the press moved past the 10 px slop, so it stopped being a tap and became a drag. The click that follows a drag is swallowed once. The link stays quiet.

04v20.0.x → this site

Snap back with the speed your hand had

The problem
When a pull was not enough to close, the sheet returned with a fixed ease-out that started from rest. A hand that was moving still saw the sheet lurch.
The change
The return is a spring that starts at the release position with the release velocity. A new press can grab it mid-flight with no jump.
Why
Continuing the motion you just made reads as the sheet being physical; restarting it reads as an animation playing.
  • mock old duration 220 ms (170–220 ms were used for reveals)

Showing Slow pull, gentle release: Pull 145 px, ease off, let go. Below the close line. With JavaScript this replays and you can record your own.

Old returnlegacy · fixed ease
cardRead more →

Stayed open

hand 17 px/s, next frame -2574 px/s, at rest 156 ms

Legacy prototypes: a fixed 220 ms ease-out from where you let go. It ignores how fast the hand was moving: the hand was at 17 px/s, one frame later the sheet is at -2574 px/s. That sudden change is the hitch.

New returnnow · velocity spring
cardRead more →

Stayed open

hand 17 px/s, next frame -498 px/s, at rest 364 ms

This site: a spring that starts from your release position and your release speed (17 px/s) and then pulls toward home, so the speed builds from what the hand was doing instead of lurching (-498 px/s one frame later). It overshoots by 3 px and is at rest in 364 ms.