Skip to content

feat(web): give the shell the console's motion and grid - #41

Merged
enricobuehler merged 5 commits into
mainfrom
claude/cool-edison-opbrhc
Oct 1, 2026
Merged

enricobuehler merged 5 commits into
mainfrom
claude/cool-edison-opbrhc

Conversation

@enricobuehler

Copy link
Copy Markdown
Contributor

What

The web shell was built on the console's stack but not on its motion: @unom/ui's cards and buttons inherit their entrance from a motion ancestor, and nothing in this shell ever drove one, so no card here had animated on mount. This brings the shell in line with the management console and fixes the layout bugs that came up on the way.

  • The console's cadence. components/stagger.tsx is the console's own file. Every page, dialog and settings tab is a cascade root; the sidebar's entries rise in turn with the console's hover wash and press feedback; the phone's bar slides up under a new brand bar; the active tab pill slides across with a shared layoutId.
  • Even host cards. The host list is the console's grid — explicit container-query columns, minmax(0, 1fr) each — so a card can no longer size its own column and the gaps are the gap.
  • Nothing clipped. The desktop shelf is padded out to the page gutters so its scroller stops cutting rings and shadows off. The card is the console's opaque surface again: the glass cost a backdrop filter per card over a gradient that never moves, and its 64px shadow was what every scroller clipped.
  • Library grid. A list the arrow keys walk by the columns the grid resolved to, instead of an ARIA grid with no rows and a column count guessed from one tile's width. Posters fan in at the console's cadence.
  • Toaster. The interface gained a notify verb beside render, backed by @unom/ui's toaster, mounted once outside the frame. Copy link goes through it.
  • Exit animations. The stream overlay's quick menu, statistics panel, notice and captured-mouse hint leave the way they came.
  • Screens as PNGs. tools/screenshots.mjs captures every story at a desktop and a phone width from the Storybook build; CI attaches them to each run. Not asserted — a layout that drifted is for a person to see.
  • Also: the Penner easing tokens @unom/ui resolves by name, a theme-color meta, README updates.

How it was checked

git.unom.io was unreachable from the session, so the private packages could not be installed. The UI was typechecked with the app's strict tsconfig against stubs of @unom/ui and @punktfunk/stream, rendered through Vite and a real Storybook build (stubs aliased in) in headless Chromium at 1440, 1024 and 390px: card geometry is equal at every width, the cascades play (sampled per frame), the quick menu fades out in under 200ms, and the screenshot tool captured 48 of 48 screens. Two things are unverified against the real library: whether its AnimatedCard forwards motion variants under asChild, and the first run of the playwright install --with-deps step on the runner.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KYYUqwKH4xjE2TDBPxSQDZ


Generated by Claude Code

claude added 5 commits October 1, 2026 18:15
The console's pages are a cascade: @unom/ui's cards and buttons inherit
from → enter from the nearest motion ancestor, and nothing in this shell
drove one, so no card here has ever animated on mount. stagger.tsx is
the console's own file; every page, dialog and settings tab is a root of
it, the sidebar's entries rise in turn, the phone's bar slides up under
a brand bar, a press answers at once, and the tab pill slides across.

The host list is the console's grid — explicit columns of the list's
own width, minmax(0, 1fr) each — so a card can no longer size its column
and the gaps are the gap. The desktop shelf is padded out to the page's
gutters so the scroller stops cutting rings and shadows off, and the
card is the console's opaque surface again: the glass cost a backdrop
filter per card to blur a gradient that never moves, and its 64px
shadow was what every scroller clipped.

The posters are a list the arrow keys walk by the columns the grid
resolved to, not an ARIA grid without rows and a column count guessed
from a tile's width.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KYYUqwKH4xjE2TDBPxSQDZ
Copy link put the link on the clipboard and showed nothing, so the only
way to know it had worked was to paste it somewhere. The host list now
carries a line for a moment — the link copied, or that the browser kept
the clipboard — through the same Screen the rest of the page reads, and
the live region reads it out.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KYYUqwKH4xjE2TDBPxSQDZ
The copied link was answered by a line the home screen carried in its
Screen for a few seconds — presentation state the state machine had to
own, time and all, for one action. The console answers the same kind of
thing with @unom/ui's toaster, so the interface now has a notify verb
beside render: a line in the corner, gone by itself, that the web shell
hands to the toaster and the gamepad console hands on to the web shell.
Nothing about where the client is changes, so nothing of it is a
Screen.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KYYUqwKH4xjE2TDBPxSQDZ
The quick menu, the statistics panel, a notice and the captured-mouse
hint each faded in over the picture and then vanished on the frame they
closed. They now go out the way they came — the same short fade, nudged
back to where they entered from — through AnimatePresence, as the
console's sheet does. Opacity and a few pixels of travel only, since a
stream is live underneath.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KYYUqwKH4xjE2TDBPxSQDZ
The Storybook build proved the shell compiles and mounts, and nothing
looked at what it drew: a clipped shelf and a grid of uneven cards both
passed it. tools/screenshots.mjs is the console's screenshot tool for
this client's stories — headless Chromium over storybook-static, every
screen at a desktop and a phone width — and CI uploads the set with each
run. Nothing is asserted: a cascade's last frame and a font's arrival
make a pixel diff flap, and a layout that drifted is for a person to
see.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KYYUqwKH4xjE2TDBPxSQDZ
@enricobuehler
enricobuehler merged commit 4496789 into main Oct 1, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants