feat: a shared game shell header, starting with the top row - #40
Open
oyuh wants to merge 8 commits into
Open
Conversation
Imposter and Password each carried their own header with their own copy of the phase maps, the copy-to-clipboard dance and the badge markup. This is one header for both, and for the three games after them. Four things live up there and each is now drawn as what it is rather than all four being pills. The phase is a track. A pill can say the phase is called Voting; it cannot say voting is the third of four and the game is nearly done, which is the question people actually have. The current step is taller and brightest, the ones behind it are filled, and a line underneath says what to do rather than repeating what it is called. The clock is its own reading, big tabular figures over a bar that drains, because it is the only thing on the header that is always moving. It scales the bar rather than resizing it, since this runs every second all game. Under ten seconds it goes red and pulses. Host and spectator sit in one bordered case split by a hairline, so what you are is one object on the header instead of two loose icons. The code is shut until asked for. Mid-game the only reason to want it is to pull a spectator in, and a code sitting open all match is readable by whoever is stood behind you. Revealing copies too, and it shuts itself after ten seconds. Everything else a game wants to say is still a pill, through the pills slot. Dev page at /dev/game-shell.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Only the phase and the clock keep a container now. They are the pair you keep glancing back at, so they are the pair that earns an edge; the title, the pills, the role case and the code sit straight on the page. Boxing both rows was a box inside the page's other boxes saying nothing by it. The clock is nearly twice the size and its bar has moved out from under the figures to span the bottom edge of the container. Time left is about the whole phase, so it reads better as the whole thing emptying out. The phase track is gone. Four segments and a count were two ways of saying the same thing, and the count was the one that already fit. Phases take an icon instead, standing in the shell the game icon wears up top. They are passed in for now and belong in each game's metadata later, so a phase can look the same everywhere it is named. The header takes its accent from the game's own metadata rather than the default primary, so every game already wears its colour with nothing passed. The dev page has a row of all five to show it.
The line was retreating from the end of the phase. Now it fills toward it, which is the direction a progress bar is read in. A bar that creeps a percent a second is motion nobody can see, so the head of the fill breathes: 0.15 to 0.7 over two and a bit seconds, enough to say the thing is running and not enough to look at. Progress rides on a var so the fill and the head read the same number and arrive together, and the track is clipped so the head never escapes at either end. The phase icon has lost its case. The game icon up top is a badge standing in for the whole game, but this one is only the phase's mark, so it sits beside the name at the size of the name and lets the name be the thing you read.
Both headings sit centre now, with a hairline running out either side to the edge of the section. A centred label floats without something to give it the width of the thing it names, and the hairline is what the cards already use to separate one part from the next. Display Name is just Display, and it has a mark of its own like Join Game does. Both icons take the label colour rather than being the same grey knocked back with an inline opacity. The recents heading is left alone: it lives inside a toggle with a chevron after it, so it keeps its row.
The rules either side of the centred headings were a second line saying what was already said. On desktop the sections are split by .hc-divider, and on mobile each section is its own card with a border, so the hairline landed a couple of pixels inside one and read as a doubled edge. Centring stays, the rules go, and the line count is back to what it was. The icons were centred on the text box correctly, but the labels are uppercase and caps carry no descender, so the glyphs sit about a pixel above the middle of that box and the icon looked low. They are nudged onto the cap centre, which leaves a residual under half a pixel on both breakpoints. Transform rather than a negative margin: a margin on a centre-aligned flex item only moves it half as far, and does it by resizing the item.
Not everyone wants the phase panel on screen for a whole match, so a collapsible header grows a button that puts it away. Folded, the container is the thing being given up, so it goes entirely: no border, no fill, no corners. The line moves from the bottom edge to the top, where it picks up a second job separating the title row from what is under it, and the pills come down off the top row to sit beneath it with the clock on the right. The clock loses a few points with nothing left to sit beside. The phase name is what folding costs you, so the button that gives it back carries it in its tooltip. The narrow-screen rule that drops the pills onto their own line is now scoped to the top row. It was catching the folded pills too and ordering them past the clock, which put the clock on the left on a phone.
The clock keeps its size. It is meant to be the loudest thing on the header, and folding the panel away only makes that more true, so the rule that shrank it is gone. Around it, everything else gets quieter. The game icon drops its badge shell and sits as a mark beside the title, since the shell was there to hold its own against a panel that is no longer on screen. The pills lose their fills and outlines and read as plain text, because chips with their own outlines next to a clock that size start arguing with it. Folding animates now. The panel is kept mounted and closed with a row of 1fr to 0fr, which is what lets a panel of unknown height shut without a max-height guessed at from outside, and it goes inert while closed so nothing in there is still reachable. The container fades its fill, its corners and its padding on the same curve. Two things that only showed up once it moved. Taking the panel to no width rewraps its sentence into a tall column in the frame before the row starts closing, so the panel shoots up before it goes down; while shut it is held on one line, which costs nothing as it is being clipped anyway. And the row gap still counts a panel of no width, walking the pills in off the left edge, so the gap moves onto the clock where it was wanted.
… colour The code and the fold button now share one case, split by a hairline, the way the two roles do. Two things you press, one object. In the lobby the code is the point of the screen, so it stays readable. Once play starts it is down to its key, and clicking widens it back out to the code and copies at the same time, then it shuts itself again. The width animates rather than snapping, and the label carries its own margin so it can go to nothing without leaving the gap behind. The lobby is taken to be the phase a game opens on. The pills are chips again. Plain text was too far: folded they are most of what is left beside the clock, so they get a size you can read and the game's own colour instead of grey, which under a coloured clock was reading as disabled. The hairline in the new case had to move below both button rules. Each of them zeroes its own border and they sit at the same specificity, so whichever comes last wins, and it has to be this one.
oyuh
marked this pull request as ready for review
August 8, 2026 12:08
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.