Skip to content

Redesign: put the app on the Back Bar design tokens - #50

Merged
mtaanquist merged 6 commits into
stagingfrom
worktree-design-refresh
Aug 9, 2026
Merged

Redesign: put the app on the Back Bar design tokens#50
mtaanquist merged 6 commits into
stagingfrom
worktree-design-refresh

Conversation

@mtaanquist

Copy link
Copy Markdown
Owner

Replaces the dark mode override sheet with a real set of design tokens, and
puts every screen on them.

Reviewing this

docs/design/ is ~6.5k lines of generated reference material from Claude
Design — worth collapsing. The four code commits are each readable on their
own and in order:

344dab2 The token sheet, and deleting the overrides
34b8f1d Order queue and status card
89b948f Guest menu
c0ef66b Everything else
6fa9bfd Hover states that ended up doing nothing

What it does

index.css was 327 lines, nearly all of it a second copy of the colour
scheme written as !important overrides on Tailwind's own utility classes.
Every new screen had to be remembered twice, and the past orders page was
only ever dark because of it, having no dark styling of its own.

It is now one set of role-named tokens, defined light and redefined once for
dark. Nothing has a dark: prefix any more. Colour also stops carrying the
five order steps: only ready lights up, because it is the only one that
needs somebody to move, and the rest are told apart by the bar down the left
edge of the row.

tailwind.config.js is deleted. Tailwind v4 only reads a JS config when the
stylesheet asks for one with @config, and nothing here did — the built
stylesheet is byte-identical with and without it.

Worth a closer look

  • The neutral ramp flips by index, so no ramp token is stable across schemes.
    The landing sign has to be ink in both, so it gets its own sign token,
    deliberately left out of the dark block.
  • That flip caught two real bugs: text over photos in the recipe view and the
    QR screens would have gone near-black in dark mode.
  • The disabled Order button now says why it cannot be used, instead of
    explaining itself in a pop-up after the guest has already tapped it. This
    is a behaviour change; the wording was already translated.
  • Four tests changed. Three were reaching for class names or for text that
    now matches twice; they ask for headings and accessible names instead. I
    checked the rewritten status-card test fails when the accessible name is
    removed, so it is not passing for free.

Checked

npm test 39/39, npm run lint, npm run typecheck, npm run build all
clean. Backend untouched, so its checks were not run.

Not yet seen in a browser. It compiles and behaves under test; no screen
has been looked at.

Not in this PR

The structural work from the two shell documents: the guest dock that keeps
the live order visible from every guest screen, the bartender rail and the
demotion of the four setup screens, tabs as URLs, and rendering the drink
form and recipe view as modals over the shell instead of replacing the whole
app. Each is worth its own change.

Some hardcoded English strings also remain untranslated — all pre-existing.

🤖 Generated with Claude Code

mtaanquist and others added 6 commits August 9, 2026 14:12
Copies of what came out of Claude Design, kept with the code so the two do
not drift. Nothing here is wired up yet.

tokens.css is the part that becomes real code: colours, type, spacing and
motion as Tailwind v4 custom properties, with light and dark sharing one set
of names. That is what will let the !important overrides in
frontend/src/index.css go away rather than being ported.

The .html files are specimen pages, not components. support.js is only what
those pages need to draw themselves and is not part of the app.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
index.css was 327 lines, nearly all of it a second copy of the colour
scheme written as !important overrides on Tailwind's own utility classes
(.bg-white, .text-gray-600 and so on). Every new screen had to be
remembered twice, and one of them — the past orders page — was only ever
dark because of it, having no dark styling of its own.

It is now the Back Bar token sheet: one set of names, defined light, and
redefined once for dark. A component asks for `surface` or `text-muted`
and is correct in both, so nothing needs a `dark:` prefix and nothing
needs an override. Also drops the leftover .fallback-test and
.test-element debugging rules.

tailwind.config.js goes with it. Tailwind v4 only reads a JS config when
the stylesheet asks for one with @config, and nothing here does, so it
has not been doing anything. Verified: the built stylesheet is
byte-identical with and without it.

Components still use the old grey utilities and are migrated next.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The five steps no longer each get their own colour. Ready is the only one
that lights up, because it is the only one that needs somebody to move;
the rest ride the grey ramp and are told apart by the bar down the left
edge of the row, which is a shape rather than a hue.

The queue rows now follow the design: one action per row, always the same
size and in the same place, with reject as a different shape set apart
from it, so the common case can be hit without looking. The count beside
"pending orders" turns the signal colour when a drink is waiting to be
collected.

orderStatus loses its per-step icons and gains statusPill and statusRail.
It is now a .ts file, since it holds no markup.

Two tests were reaching for class names — one for `div.rounded-lg`, one
matching the exact shape of a class string — so they broke on the
restyle without anything being wrong. Both now check what they were
actually for: the status card is found by its accessible name, and the
steps are still required to differ from one another in more than one way.
Giving the card that name is also a small improvement for anyone using a
screen reader. Checked that the rewritten test fails when the name is
taken away.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The drink card follows the design: the picture, then the name and the
description, then one strip along the bottom holding the recipe and the
order button. Without a picture the name is set large in its place, so a
menu where only some drinks have photos still reads as one grid.

The order button now says why it cannot be used — "you can only have one
active order at a time" — instead of going grey and only explaining
itself in a pop-up after the guest has already tapped it. The wording
was already translated, so nothing new had to be written.

Section headings lose their colours and their emoji and become a quiet
label with a rule, which lets the drinks be the loud thing. Surprise me
is no longer pink: the signal colour means a drink is ready to collect
and is not spent on anything else, so it is an ordinary bordered button.

Four tests were asking for the drink name with getByText, which now
matches twice because the name is also the picture. They ask for the
heading instead, which is what a guest reads and what a screen reader
announces. The one covering the one-drink-at-a-time rule now checks the
button explains itself, which is the thing that changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The remaining screens still used the old grey-and-blue utilities, which
had been kept upright by the override sheet that went in the first
commit. Without it they would have been light-only, so this finishes the
job: bartender screens, drink form, categories, settings, reports, the
recipe view, past orders, sign in and the way in from a QR code.

Most of it was a mechanical swap of one palette for another. Three parts
were not:

The landing page loses its purple gradient for the sign the design asks
for — an ink panel, the name of the thing set large, a rule, and a line
about what it is. That needed a token the sheet did not have. Every
colour so far flips between the two schemes, but a painted sign does not
lighten when the lights come up, so `sign` and `sign-fg` are defined once
and deliberately left out of the dark block. The same panel is used on
the QR arrival screens.

That flipping caught two real bugs in the mechanical swap. Text sitting
on a photo, in the recipe view and on the QR screens, had been given the
"inverse" colour, which is white in the light scheme but near-black in
the dark one — so it would have vanished against the dark end of a
photograph. Those now use the sign colour, which is white in both.

Dialogs keep the larger corner the design reserves for them, and gain a
border, since a shadow alone barely reads against a near-black room.

Two new strings for the landing panel, in both languages.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Where a control rested on the sunken surface and lifted to a slightly
darker grey, both greys mapped to the same token and the hover stopped
being visible. Those now lift to the border colour instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mtaanquist
mtaanquist merged commit 794e102 into staging Aug 9, 2026
4 checks passed
@mtaanquist
mtaanquist deleted the worktree-design-refresh branch August 9, 2026 12:55
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.

1 participant