Skip to content

Redesign the window around one design system - #21

Merged
MrBeldum merged 11 commits into
mainfrom
design/ui-overhaul
Sep 30, 2026
Merged

MrBeldum merged 11 commits into
mainfrom
design/ui-overhaul

Conversation

@MrBeldum

@MrBeldum MrBeldum commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

Redesign of the whole UI: a real design system in crates/ui, every screen and state rebuilt on it, the stream overlay reworked, and a snapshot harness that covers all of it. The full audit (every finding, severity, state) and the design system are in docs/design/AUDIT.md.

Biggest finds

  • The unified window never showed the host panel. Paired devices, Unpair, the service log, Wake-on-LAN and network status, Stop service and Repair were unreachable on a real install. They are now the Sharing tab.
  • The snapshot harness read the real client.toml/host.toml, and the relay-state renders were identical because the card was off-screen.
  • Idle repaint loop (every 400 ms forever), and a tailscale --version process spawn on the UI thread every 2 s when Tailscale is missing.
  • WCAG failures: footer and small print at 3.2 to 3.6:1, destructive button text at 2.83:1, violet pill text at 3.89:1.
  • Tab order ran backwards through right-aligned controls (row actions and the stream toolbar).
  • Copy told Windows and Linux users about "this Mac", and pointed at "BroLink Host … run setup", a UI that no longer exists.

What changed

  • crates/ui: colour, type (Geist + Geist Mono, OFL; replaces Inter), spacing, size, radius and elevation tokens; buttons in five kinds, popup menus, tabs, segmented, switch, slider, select, rows, notices/banners, tags, keycaps, disclosure. Each has accesskit info and a focus ring. Contrast is tested.
  • Window: tabs for Machines, Sharing and Settings (Cmd/Ctrl-1/2/, and Escape); a machine list with status dots and a "…" menu; honest connecting, pairing, failure, empty, looking and Tailscale states; Settings grouped with one quality control.
  • Stream: consistent toolbar and menus (a More menu when narrow), host-key keycaps, a Cancel button while connecting, proper panels for Stream settings and Stream performance, and Turn off HDR as the primary action when the picture is black. Nothing new costs a frame while the toolbar is hidden.
  • Harness: every state at 640×420, 1280×800 and 1920×1200, at 1× and 2× (144 PNGs), plus unignored fit, overlap, keyboard-order and no-idle-repaint tests.
  • macOS release binary: 12,167,440 → 11,689,120 bytes.

Outside the UI files (small, listed for the merge)

  • client/src/session.rs: error strings only (7 messages).
  • client/src/path.rs: Path::tone() mapping (a relay is amber, not red) and three "this Mac" strings, with tests.
  • client/src/update.rs: one "this Mac" string.
  • client/src/share.rs: LocalShare trimmed to the summary fields, plus a SharePage trait.
  • host/src/product.rs: hosts the Sharing page, and syncs only on change.
  • host/src/app.rs poller: repaints only when the status changes.

Not verified here

The real app was not launched (rules). Unverified: rendering over a live picture, real DPI and font hinting on Windows, VoiceOver/Narrator, IME. Windows-only code is covered by CI's test-windows.

🤖 Generated with Claude Code

MrBeldum and others added 9 commits September 30, 2026 01:32
The window read as three apps glued together: violet pills and cards in
the viewer, a host panel the unified window never showed, and egui's own
menus in the stream toolbar. Every screen now takes its colours, type,
spacing, radii and elevation from crates/ui, in the product site's
black, white and hairlines, set in Geist and Geist Mono.

- crates/ui is a real design system: surface levels, three text
  strengths, one primary (white), status tones, the logo violet only for
  focus and progress, a 4-point spacing scale, a type scale, three
  radii, two elevations. Buttons come in five kinds; menus, tabs,
  switches, sliders, notices, tags and keycaps are drawn here, report
  themselves to accesskit and show a focus ring. Contrast is tested.
- The unified window has tabs: Machines, Sharing and Settings. Sharing
  is the host's page (setup, status, paired devices, options, log),
  which the unified window used to leave unreachable.
- The machine list, connection progress, failures, empty and Tailscale
  states, Settings and the stream overlay are rebuilt on it, with
  shorter, honest copy that names the right kind of machine.
- The idle window no longer repaints on a timer, the Tailscale probe
  and the host's network calls are off the UI thread, and the host
  poller repaints only when something changed.
- The snapshot harness builds every screen headless with default
  settings (it used to read the real client.toml) and renders each
  state at 640x420, 1280x800 and 1920x1200, at 1x and 2x; unignored
  tests check every state fits with no overlapping controls.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
body, titled_card, toggle and steps had no callers after the redesign,
and card_frame, focus_ring and paint_icon are only used inside the kit,
so they are private now. A component that nothing draws is one more
thing to keep consistent for no gain.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every install is a viewer now, but the connection errors and the path
explanations still said "this Mac", and told people to "open BroLink
Host and run setup", a window and a button that no longer exist. They
now say "this machine" and point at the Sharing tab, and each error
ends with what to do.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
egui focuses widgets in the order they are made, and a right-to-left
layout makes the rightmost first, so Tab went to a machine's menu before
its Connect button, and through the stream toolbar from Disconnect
backwards. Controls on the right are now laid out left to right and
pushed against the edge, measured on the previous pass (a changed width
discards the pass, so nothing is ever drawn misplaced).

A key that expires within 30 days now shows at the top of the machine
list, with the other things that need doing, rather than under it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The guides still sent people to "Set up this PC", the status pill, the
This PC card and a Settings card the unified window does not have, and
described the toolbar's old Mouse, Keys and quick-profile controls. They
now describe what is on screen: the Machines, Sharing and Settings
tabs, a machine's … menu, the toolbar and its More menu on narrow
windows, and the grouped Settings. CONTRIBUTING says what the snapshot
run renders and where new visual elements go.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
When a stream's picture is black and the machine says its HDR desktop
is the cause, the fix was a quiet text button after "Restart stream",
which on its own cannot help, and the headline kept saying "Asking the
PC why…" after the PC had answered. The fix is now the primary button,
Restart stream is secondary, and the stale half of the headline goes
once the answer is in. The snapshot run renders this overlay.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An iPhone or Android device on the tailnet showed "BroLink isn't
installed", which sends someone looking for an app that does not
exist. It now says phones and tablets can't share a desktop.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every problem found on 4.0.2, with its severity and what happened to
it, the tokens and components the screens are now built from, and what
is left or could not be verified without running the app.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
After a successful setup the Sharing page kept a card titled "Sharing
is set up" with another Run setup again button and a note that "the
list above clears" when there was no list. It now shows one line that
other machines can connect. The power switch no longer mentions waking
on a Mac, which BroLink does not do, and Settings' update row is
labelled for what it shows.

The changelog's size figure is now measured: the macOS release binary
went from 12,167,440 to 11,689,120 bytes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
MrBeldum and others added 2 commits September 30, 2026 07:41
At 640x420, the smallest window, the stream toolbar's More menu ran past
the bottom edge: "Command acts as Ctrl" and the PC's power items were cut
off, and Tab could move focus onto them without showing them. Stream
performance ran off the bottom as well, and both stream panels sat
partly under the toolbar.

Menus now choose where to open in crates/ui: below their control when
they fit, above it when there is more room there (a machine's menu near
the foot of the list), and capped at that side's room, scrolling inside
with the scroll bar showing when neither side has room for all of it.
Dropdown lists, Stream settings, Stream performance and the restart and
install questions are capped the same way, below the toolbar. A control
scrolls into view when Tab reaches it, and focus rings are no longer cut
off at a window's edge.

Tests open the More, Keys, Mouse, PC and machine menus, both panels, the
questions and a dropdown at 640x420 (the separate toolbar menus from the
narrowest width that shows them), Tab to the last item and check by rect
that it and the whole menu or panel are on screen. The snapshot run
renders each of those states at 1x and 2x.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The failed-connection card's "Dismiss" sat 12 points right of the text
above it. A quiet button's label is inset by the button's padding, and
with no fill or outline to show the box, the label is what the eye
lines up. Actions under a notice now go in an action row that pulls a
quiet button leading a line back by that padding; filled and outlined
buttons still line up by their edge.

Checking the other notices and cards turned up two more: a notice with
no actions (Tailscale isn't connected, Installing a BroLink update) kept
an empty row's height at its foot, and the setup card's "Get Tailscale"
link started at the card's edge instead of under the checklist item it
belongs to. The empty row now takes no room, and the link sits in the
item's text column.

A test checks the label of a quiet action and the edge of a filled one
against the notice's title.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@MrBeldum
MrBeldum merged commit 58ff516 into main Sep 30, 2026
9 of 10 checks passed
@MrBeldum
MrBeldum deleted the design/ui-overhaul branch September 30, 2026 15:33
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