Input and device capability profile — the single answer to "is this a
touch-first device, is it an iPhone or an iPad, can its pointer hover?"
Every JS-side touch adaptation in the viewer (gesture routing, long-press
menus, mobile rendering budgets, tap-friendly copy) keys off this profile so
the decision is made once, from the same signals, and so a test can stub
one module instead of navigator and matchMedia in a dozen places. CSS
adaptations do NOT go through here: they use the (pointer: coarse) /
(any-hover: none) media features directly, which is why the ?input= override
below is documented as JS-only.
Deliberately import-free: rendering/pixel-ratio-cap.ts and other
leaf modules depend on this file precisely so they can stay out of every
import cycle, and utils/ is the one layer every other layer may reach.
Signal semantics (all best-effort, all false/0/empty outside a browser, so
the no-information default is a hover-capable fine-pointer desktop — the
historical behaviour):
coarsePointer: the PRIMARY pointer is coarse ((pointer: coarse)), i.e.
a finger. A touch-screen laptop with a trackpad reports false.
anyHover: SOME pointer can hover ((any-hover: hover)). An iPad with a
Magic Keyboard trackpad reports true while still being coarse-primary,
which is exactly the case that must keep hover tooltips.
iPadOS Safari reports a Macintosh user agent (desktop-site mode is the
default since iPadOS 13). The masquerade is unmasked by platform
starting with Mac together with maxTouchPoints > 1 — no Mac has a
multi-touch screen.
Input and device capability profile — the single answer to "is this a touch-first device, is it an iPhone or an iPad, can its pointer hover?"
Every JS-side touch adaptation in the viewer (gesture routing, long-press menus, mobile rendering budgets, tap-friendly copy) keys off this profile so the decision is made once, from the same signals, and so a test can stub one module instead of
navigatorandmatchMediain a dozen places. CSS adaptations do NOT go through here: they use the(pointer: coarse)/(any-hover: none)media features directly, which is why the?input=override below is documented as JS-only.Deliberately import-free:
rendering/pixel-ratio-cap.tsand other leaf modules depend on this file precisely so they can stay out of every import cycle, andutils/is the one layer every other layer may reach.Signal semantics (all best-effort, all false/0/empty outside a browser, so the no-information default is a hover-capable fine-pointer desktop — the historical behaviour):
coarsePointer: the PRIMARY pointer is coarse ((pointer: coarse)), i.e. a finger. A touch-screen laptop with a trackpad reportsfalse.anyHover: SOME pointer can hover ((any-hover: hover)). An iPad with a Magic Keyboard trackpad reportstruewhile still being coarse-primary, which is exactly the case that must keep hover tooltips.platformstarting withMactogether withmaxTouchPoints > 1— no Mac has a multi-touch screen.