Device

@sushindustries/ui

A phone, a tablet or a laptop in CSS 3D, chosen by the stylesheet rather than by JavaScript, with a real screen in it.

7 min read
View as Markdown

The home page is inside one of these. Which one depends on the window you are reading this in.

Viewport width
Desktop100%whatever the page has
tanstacktanstack add https://adamjurek.com/r/tanstack/device.jsonshadcnpnpm dlx shadcn@latest add https://adamjurek.com/r/shadcn/device.json

The machine is chosen by CSS

This is the decision everything else follows from, so it is worth stating on its own.

Nothing in this component measures anything. It renders one screen and every piece of chrome all three machines could need, and the stylesheet hides what does not apply. A phone below 720px, a tablet from 720, a laptop from 1080.

The obvious alternative is to read the width and return one of three trees, and it is wrong in three separate ways:

What goes wrongWhy
Nothing renders on the serverThere is no window to measure, so SSR emits whichever branch the fallback picked.
The first client frame is wrongThe correction happens after hydration, which is a visible flash of the wrong machine.
React throws the tree awayIf the server guessed and the client disagrees, that is a hydration mismatch, and the recovery is a full client re-render with dead event handlers on the way.

All three had already happened in this repo, on other components, for exactly this reason. Four empty <div>s and a display: none cost less than any of them, and are correct before a byte of JavaScript arrives.

The numbers are a table

Widths, aspect ratios, bezels, corner radii, tilt and which chrome each machine shows all live in packages/atoms/devices.md. pnpm doctor compiles it to devices.css and device-kinds.ts. Editing either output is a change that gets reverted.

Install

tanstack add https://adamjurek.com/r/tanstack/device.json
shell
pnpm dlx shadcn@latest add https://adamjurek.com/r/shadcn/device.json
shell
pnpm add @sushindustries/ui @sushindustries/atoms
shell

What you get

Version0.1.0
Categorylayout · Scenes
Filesdevice.tsx, device-kinds.ts
DependenciesNone
Tagsblock, 3d, perspective, responsive, no-js, no-deps

No runtime dependencies

It brings nothing with it beyond the stylesheet.

Used byuseDeviceKinduseDeviceKindWhich machine the stylesheet is currently drawing, as a value. Null until mounted, on purpose - a default would be a claim the server cannot support.@sushindustries/ui · layout