useDeviceKind

@sushindustries/ui

Which machine the stylesheet is currently drawing, as a value. Null until mounted, on purpose.

3 min read
View as Markdown

It listens rather than measuring

window.matchMedia(`(min-width: ${device.from}px)`);
ts

One MediaQueryList per machine, and the widest match wins - which is exactly how the cascade resolves the same queries in devices.css.

Reading innerWidth would be one line and would disagree with the stylesheet the moment a scrollbar exists: a media query measures the viewport including the scrollbar, and innerWidth does not. That is a 15px window where the number says one machine and the screen shows another, and it is the kind of disagreement nobody finds by reading either file.

Listeners are removed on unmount, and none are attached at all when an override is passed.

An override short-circuits it

useDeviceKind(settings.device === "auto" ? undefined : settings.device);
tsx

Passed a kind, it returns that kind and attaches nothing. This matches what the stylesheet does with data-device, so a settings panel that writes the attribute and reads this hook cannot end up with the two disagreeing.

What it is generated from

Nothing here holds a number. DEVICES comes from packages/atoms/devices.md, which is also what the media queries are compiled from, so this hook is correct by construction rather than by somebody remembering to update it twice.

ExportWhat it is
DEVICESevery machine, narrowest first, with its from, width and aspect
DEVICE_KINDSjust the names, for a menu
deviceKindFor(width)the same decision without touching the DOM
deviceQuery(kind)the media query text, for anything doing its own matching
UsesDeviceDeviceA phone, a tablet or a laptop in CSS 3D, chosen by the stylesheet rather than by JavaScript, whose screen is a real scroll container with real controls in it.@sushindustries/ui · layout