Skip to content

Commit 07179fa

Browse files
alexnodelandclaude
andcommitted
docs: touch-grade smoothness pass + in-page support figures
Fixes the root cause of mobile bugginess: .fv-canvas set touch-action: none on EVERY canvas, so thumb swipes over any figure ate page scroll. Canvases now default to pan-y; full gesture capture is opt-in via a shared FV.drag manager (pointer capture, claims the gesture only when the touch actually hits a draggable, >=22px hit inflation on coarse pointers, grab halo). Killed the same class in inline.js (unconditional preventDefault on touchmove) and in every hero's hand-rolled drag code; monad's machinery strip no longer steals scroll swipes as Steps; flash decay is time-based; layouts audited at 390px and 320px. Adds docs/viz/minis.js — eight page-support figures woven into the explorables' explanation sections: autocorrelation decay and a live sigma-sweep on Metropolis, the double-well momentum-vs-random-walk strip and a divergence-cliff scatter on HMC, an animated bind-chain on the monad page, sequential-update small multiples on Anatomy, an ESS timeline on SMC, and a natural-return-types flow on Distributions. Mobile-verified via emulated 390x844 touch contexts with CDP touch events: swipe-over-widget scrolls the page, point-drags move points without scrolling, zero console errors, zero >50ms long tasks; full desktop regression green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DEAKcbnLVP8iSXub2Pqor2
1 parent 0f103ec commit 07179fa

16 files changed

Lines changed: 1544 additions & 223 deletions

docs/book.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ preferred-dark-theme = "navy"
1818
git-repository-url = "https://github.com/alexnodeland/fugue"
1919
site-url = "/fugue/"
2020
additional-css = ["./mdbook-admonish.css", "fugue-viz.css"]
21-
additional-js = ["mermaid.min.js", "mermaid-init.js", "fugue-viz.js", "viz/anatomy.js", "viz/monad.js", "viz/metropolis.js", "viz/hmc.js", "viz/smc.js", "viz/distributions.js", "viz/inline.js"]
21+
additional-js = ["mermaid.min.js", "mermaid-init.js", "fugue-viz.js", "viz/anatomy.js", "viz/monad.js", "viz/metropolis.js", "viz/hmc.js", "viz/smc.js", "viz/distributions.js", "viz/inline.js", "viz/minis.js"]
2222

2323
[output.html.fold]
2424
enable = true

docs/fugue-viz.css

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,30 @@ html.dark {
6363
display: block;
6464
width: 100%;
6565
border-radius: 6px;
66-
touch-action: none; /* let pointer drags on canvas work on touch */
66+
/* Default: allow the page to scroll when a thumb swipes the canvas. Ambient
67+
micros keep this so they never eat scroll. A widget that owns the whole
68+
canvas for interaction opts into full gesture capture via .fv-touch-none
69+
(added automatically by FugueViz.drag with its default fullCapture). */
70+
touch-action: pan-y;
71+
}
72+
73+
/* Belt-and-braces: any canvas inside an explorable defaults to pan-y even if a
74+
widget forgot the .fv-canvas class. */
75+
.fugue-explorable canvas {
76+
touch-action: pan-y;
77+
}
78+
79+
/* Full-capture opt-in: the whole canvas is interactive, so no gesture scrolls
80+
the page (FugueViz.drag adds/removes this class around a fullCapture drag). */
81+
.fv-canvas.fv-touch-none,
82+
.fugue-explorable canvas.fv-touch-none {
83+
touch-action: none;
84+
}
85+
86+
/* Cursor while a FugueViz.drag grab is active (paired with an on-canvas halo). */
87+
.fv-canvas.fv-grabbing,
88+
.fugue-explorable canvas.fv-grabbing {
89+
cursor: grabbing;
6790
}
6891

6992
/* ---- Controls row --------------------------------------------------------- */
@@ -198,8 +221,11 @@ html.rust .fv-btn.fv-primary {
198221
font-variant-numeric: tabular-nums;
199222
color: var(--fv-prior);
200223
user-select: none;
224+
-webkit-user-select: none;
201225
padding: 0 1px;
202226
white-space: nowrap;
227+
/* A horizontal thumb-drag scrubs the number; never let it scroll the page. */
228+
touch-action: none;
203229
}
204230

205231
.fv-scrub:focus-visible {
@@ -312,3 +338,66 @@ html.rust .fv-btn.fv-primary {
312338
margin-top: 6px;
313339
line-height: 1.4;
314340
}
341+
342+
/* ---- Coarse-pointer (touch) sizing bumps ---------------------------------- */
343+
/* On touch devices grow the tap targets without changing their layout on
344+
mouse/trackpad. Native range inputs get a taller hit box; buttons, checkbox,
345+
glyph and scrub all reach the ~44px comfortable-touch neighbourhood. */
346+
@media (pointer: coarse) {
347+
.fv-range {
348+
height: 30px;
349+
width: 160px;
350+
}
351+
.fv-btn {
352+
padding: 8px 14px;
353+
font-size: 0.8rem;
354+
line-height: 1.5;
355+
}
356+
.fv-checkbox {
357+
width: 20px;
358+
height: 20px;
359+
}
360+
.fv-toggle {
361+
gap: 8px;
362+
}
363+
/* Enlarge the scrub's tap target vertically without shifting the text. */
364+
.fv-scrub {
365+
padding: 3px 4px;
366+
}
367+
.fv-glyph {
368+
width: 30px;
369+
height: 30px;
370+
opacity: 0.5;
371+
font-size: 0.85rem;
372+
}
373+
}
374+
375+
/* ---- Phone-width layout (~390px and the 320px floor) ---------------------- */
376+
/* Controls and readouts already wrap (flex-wrap); here we tighten padding and
377+
shrink the range width so nothing overflows the panel at narrow widths. */
378+
@media (max-width: 420px) {
379+
.fugue-explorable {
380+
padding: 10px 10px;
381+
}
382+
.fv-controls {
383+
gap: 8px 12px;
384+
}
385+
.fv-readouts {
386+
gap: 10px 14px;
387+
}
388+
.fv-range {
389+
width: 130px;
390+
}
391+
}
392+
393+
@media (max-width: 340px) {
394+
/* Last resort at the 320px floor: let a range take the full row so it never
395+
pushes the panel wider than the viewport. */
396+
.fv-control {
397+
flex: 1 1 100%;
398+
}
399+
.fv-range {
400+
width: 100%;
401+
min-width: 0;
402+
}
403+
}

0 commit comments

Comments
 (0)