style: redesign the WebUI - #2
Merged
Merged
Conversation
Mr-Sunglasses
added a commit
to VocaHQ/vocaphone
that referenced
this pull request
Aug 8, 2026
The apps disagreed with each other and with their own icon: iOS was tinted
system blue, the keyboard's resting accent was blue again, Android used the
brand green, and the icon was navy on green — dark on dark.
Icon: the field keeps #0F6B57, the mark flips to near-white, and the outer arc
pair is dropped so the microphone can be drawn bigger. Contrast goes from 1.4:1
to 5.1:1 and it reads at 22px. mark_box("both") still reproduces the measured
349x329 avatar reconstruction exactly, so the provenance is intact.
iOS: BrandPalette holds the two values for every target. Explanations that were
List rows become Section footers, which is what made the screens read as a
column of slabs. SessionState gains displayName — the main screen was showing
raw case names like "uploadFailedRecoverable".
Android: SectionCard becomes Section, a heading and its content on the page
rather than fourteen filled cards down Settings; interruptions become Notice and
keep a container. Material's own button shape replaces a bespoke 16.dp corner
that was on buttons, chips and cards alike.
Two contrast bugs the blue was hiding, both of which would have shipped:
- SwiftUI .borderedProminent always draws a white label on the tint, which is
1.7:1 on the dark palette's #77D0B2. Prominent buttons now go through
brandProminentButton().
- The keyboard's dictation bar hardcoded a white title on its accent fill, and
every dark-mode accent there is a light pastel, so all six states sat near
2:1. The label colour is now derived from the fill's luminance.
Removing Android's cards also broke what they were propping up: on the white
page a chip fill at #F4F5F3 was 1.09:1, and the *pending* setup-checklist icons
were 1.76:1. The light containers and outline moved; both themes now pass every
pair.
The gateway WebUI half of this work is VocaHQ/vocagateway#2, since server/ is
now a submodule.
iOS: 90 tests, both appearances checked in the simulator. Android: 116 tests,
assembleDebug and lintDebug clean, but no emulator image or device was available
so it is compile- and contrast-verified only.
Hierarchy from type and hairlines instead of boxes, on the product palette the iOS and Android apps already use. - .card is a section with a rule, not a filled box; only inputs, data strips, tables and the QR plate keep a surface - the eight metric tiles become one hairline-divided strip; the benchmark grid matches it - Models is a grouped list of rows, not a 245px card grid with up to five pills each; Download is ghost so Select is the only green action - Settings drops six stacked boxes for four page sections; Network and storage merge so paths stop breaking mid-word - status is a dot, not a coloured pill; uppercase micro-labels are gone - fixed: pairing's <dl class="facts"> used div-wrapped pairs the grid did not expect, so long URLs overflowed - one --gutter for header, tabs and content, computed from 100% so a scrollbar cannot pull the header out of line favicon.svg is generated output — assets/generate.py in VocaHQ/vocaphone builds it, and this is the four-arc mark from the icon work in that repo.
Mr-Sunglasses
force-pushed
the
style/redesign-webui
branch
from
August 9, 2026 00:15
6062ef5 to
f819abc
Compare
Mr-Sunglasses
added a commit
to VocaHQ/vocaphone
that referenced
this pull request
Aug 9, 2026
The apps disagreed with each other and with their own icon: iOS was tinted
system blue, the keyboard's resting accent was blue again, Android used the
brand green, and the icon was navy on green — dark on dark.
Icon: the field keeps #0F6B57, the mark flips to near-white, and the outer arc
pair is dropped so the microphone can be drawn bigger. Mark-against-field
contrast goes from 2.98:1 to 5.90:1 and it reads at 22px -- measured, where the
figures first quoted for this were estimated and wrong. mark_box("both") still
reproduces the measured 349x329 avatar reconstruction exactly, so the
provenance is intact.
iOS: BrandPalette holds the two values for every target. Explanations that were
List rows become Section footers, which is what made the screens read as a
column of slabs. SessionState gains displayName — the main screen was showing
raw case names like "uploadFailedRecoverable".
Android: SectionCard becomes Section, a heading and its content on the page
rather than fourteen filled cards down Settings; interruptions become Notice and
keep a container. Material's own button shape replaces a bespoke 16.dp corner
that was on buttons, chips and cards alike.
Two contrast bugs the blue was hiding, both of which would have shipped:
- SwiftUI .borderedProminent always draws a white label on the tint, which is
1.7:1 on the dark palette's #77D0B2. Prominent buttons now go through
brandProminentButton().
- The keyboard's dictation bar hardcoded a white title on its accent fill, and
every dark-mode accent there is a light pastel, so all six states sat near
2:1. The label colour is now derived from the fill's luminance.
Removing Android's cards also broke what they were propping up: on the white
page a chip fill at #F4F5F3 was 1.09:1, and the *pending* setup-checklist icons
were 1.76:1. The light containers and outline moved; both themes now pass every
pair.
The gateway WebUI half of this work is VocaHQ/vocagateway#2, since server/ is
now a submodule.
iOS: 90 tests, both appearances checked in the simulator. Android: 116 tests,
assembleDebug and lintDebug clean, but no emulator image or device was available
so it is compile- and contrast-verified only.
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.
Hierarchy from type and hairlines instead of boxes, on the product palette the
iOS and Android apps already use. Every fact stays on the page.
.cardDownloadis ghost soSelectis the only green actionAlso removed: the uppercase micro-labels (
GATEWAY STATUS,LIVE OPERATIONS,UPTIME…), the Models marketing hero, and the "ready for dictation" block thatrepeated the headline above it.
Two fixes that came out of it:
<dl class="facts">useddiv-wrapped pairs the two-column grid didnot expect, so long URLs overflowed on narrow screens
--gutterfor header, tabs and content, computed from100%rather than100vwso a scrollbar cannot pull the header out of line with the contentAbout
app/webui/favicon.svgIt is generated output, and it is this repository's file — committed and
reviewed here, not written from outside.
assets/generate.pyinVocaHQ/vocaphonedraws it, because the geometry and the palette live there anda second copy of that generator here would be the worse duplication. To refresh
it, from a vocaphone checkout with this repo as its
server/submodule:That flag exists as of VocaHQ/vocaphone#43. Before it, the favicon was an
ordinary entry in the generator's output map, which meant a routine run there
silently dirtied a checkout of this repo. The neutral disc is deliberate — the
WebUI draws the mark small against its own dark chrome, where a green disc reads
as a smudge of colour.
The matching vocaphone PR is #43.
381 tests, ruff, ruff format and mypy all pass. Rendered headless at 1280px and
500px across all four tabs, plus the token modal, a mid-download row, a finished
test run and the not-ready setup state.