Skip to content

v2.9.0 - UI revamp

Choose a tag to compare

@theyashgupta theyashgupta released this 16 Aug 19:14
· 190 commits to main since this release
fb75ede

The complaint that started this release was "the UI looks very AI-generated", which is not a thing you can build against. So the first job was working out what it actually meant. It turned out not to be the obvious version. Dispatch has no gradients, no glassmorphism, no bouncing hover states, no accidental light theme. It had the quieter developer-tool version of the same problem: the entire working type scale spanned three pixels, one radius value was applied to every element regardless of size or role, one accent colour was carrying seven or eight unrelated meanings, every card and nav icon rendered at the same visual weight, and a modal's own heading was styled smaller and quieter than the card title sitting behind it.

None of those is a bug. Each one is individually defensible. Together they mean nothing on screen is ever allowed to matter more than anything else, and that flatness is what reads as machine assembled.

Fixing that by taste would have turned into an argument per screen, so it did not happen that way. A written design contract came first, naming one direction and pinning actual values for type scale, weight, spacing, radius, colour roles and elevation. Then every surface was rebuilt against it, and then every surface was audited against it one at a time, with a mismatch treated as a finding rather than an opinion. Forty eight surfaces, each with a recorded result.

See it

Dispatch v2.9.0 the redesigned board, modal hierarchy and the strip at phone width

Higher-quality video: dispatch-v2.9.0-ui-revamp.webm

The modal heading, which was the whole complaint in miniature

A dialog used to sit in front of the board with a heading smaller and quieter than the card titles visible behind it. Your eye went to the background. It now reads 17px at semibold against 13px card titles, on a raised surface with the dialog radius, and the thing you opened is the loudest thing on screen. This was the single sharpest artifact of the original complaint and it is the one I would look at first.

Hierarchy you can actually see

The type scale now spans a real range with weight used as a hierarchy tool rather than sitting near uniform everywhere. Radius became a small vocabulary tied to element role instead of one value sprayed across everything, so chips and badges read as chips, cards read as cards, and floating menus read as floating. Elevation follows one surface ladder with a single shadow definition rather than a literal copy pasted into whichever file needed it.

The accent colour got one narrow written job. Everything else it used to mean got expressed some other way, and focus in particular now has a treatment distinct from selection and from drag target, which matters because those three states used to be indistinguishable at a glance.

The top strip

The strip was rebuilt into identity, primary and utility zones instead of one flat row of identically weighted icons, at instrument panel scale rather than marketing header scale. The wordmark is defined once as a real type value instead of a hardcoded weight duplicated across two files.

The more interesting half is what happens when the window gets narrow. The strip never fit inside a 390px viewport. Two controls ran off the right edge, Activity by about 15px and Settings by about 47px, and the sync status wrapped to three lines and spilled out of a 44px strip. That was not caused by the redesign. The commit before any of this work measured 61px of overflow against the shipped 60px, so it has been broken for a while and nobody had closed it.

It closes now, and it took three things rather than one. Horizontal padding steps from 24px to 16px below 768px. The sync status truncates to a single line with an ellipsis, which required unpicking a chain of minimum width constraints that had been quietly preventing the ellipsis from ever engaging, no matter what the CSS said. And below 768px the DISPATCH wordmark stops rendering, leaving the diamond mark alone. That last one is the visible change on a phone, and it was not optional: at 136.5px the wordmark is more than a third of a 390px viewport, and the fixed elements do not fit beside it even with the status text erased entirely. The app name still reaches VoiceOver through the mark itself.

Worth saying plainly, because it is a real tradeoff: the mode control sits beside the mark at phone width rather than centred in the viewport. It stays put when the Inbox button comes and goes, which is the property that actually mattered.

Column headers that stop collapsing

The To Do and In Progress column headers were rendering about 11px shorter than every other column's. Under real content overflow the sticky header was flex shrinking, so the two columns you look at most had the two headers that were quietly wrong. They render at their full 32px now, at every window size, and no card row was lost to make room. Like the strip overflow, this predates the redesign.

The detail panel

The panel got a reading rhythm distinct from the board's scanning density, with wider padding on the surfaces you actually read rather than scan. Its resize handle became a proper keyboard operable separator, so you can size the panel with arrow keys and it reports a width that matches what is rendered rather than what was requested. It also stays out of the tab order when the panel is closed, which it previously did not.

Opening a group parent from search used to show you a group with no members, because the card came back without them. The single card fetch now returns the members alongside the card, so a group opened from search shows what it actually contains. Failed hydration now says what went wrong too, distinguishing a card that no longer exists from a network that did not answer, instead of leaving you looking at nothing.

Settings, Inbox and Orca

The Settings tab strip had no keyboard focus indicator at all. Tabbing through it moved focus invisibly. It now takes the same focus ring as everything else, and it is visually distinct from the underline that marks the selected tab rather than sitting on top of it. The Cleanup tab's save button says what it saves instead of just "Save".

The multi select dropdown joined the same elevation and radius treatment as the other floating menus, so all three now look like the same kind of thing. Orca's section headers and count badges match the board's, which they did not, in three separate ways that had drifted apart. The update banner sits on the same horizontal inset as the strip above it, which it also did not, by 8px, in a way that was only visible when both were on screen together.

About the audit

Every surface got checked against the contract at four window sizes, in a real browser, measuring what was rendered rather than reading what the source said it should be. That distinction earned its keep: the column header collapse and the strip overflow were both invisible to source reading. They only appear under real layout pressure.

Nine of the checks used along the way turned out to be incapable of reporting a failure at all, three of them prescribed by the plan itself. A scroll width check that could never see overflow because the overflow went leftwards. A one line check where both numbers moved together so a five line status still passed. A panel open check that could not tell open from closed because the closed panel keeps its content parked offscreen. Those are written down now, which is probably the most reusable thing this release produced.

Full changelog: v2.8.0...v2.9.0

Requires Node ≥ 22.22, tmux, ttyd, git, and the Claude Code CLI. Setup is in the README.