A review measured against the browsers Dad left
A browser can pass every test and still feel wrong in the first minute. Todo #603 was a usability review of Voyager in daily use, row by row, each row a place where it behaved differently from Chrome or Safari. Its rows are numbered B1 and B2, M1 to M6, and m1 to m10, and the commit bodies call the m rows the minor ones. All of them landed on 2026-10-22 in seven commits: six name the rows they closed, and a seventh closed two gaps that a review of the day's own changes found.
| Rows | What changed | Taught in |
|---|---|---|
| B1 | the departure question at most once a day, in a toast | track 1 |
| M1, m7 | the address field completes, selects, shortens, pastes and goes | here |
| M2, M3 | Pippa herself stays live; an ended page reloads once | lesson 4 |
| M4, B2 | family apps get the microphone with no prompt; Settings names where the family hub lives | track 6 |
| M5, m6 | idle tabs sleep; the session is written off the main thread | lessons 2 and 3 |
| M6, m8 | a full strip keeps every tab reachable; tabs drag out | here |
| m1 to m5, m9, m10 | find counts, history lists, downloads, dialogs, other apps, mute | here |
The address field, Chrome's way
Before M1, typing "x" and pressing Return searched for "x". Chrome would have gone to the site Dad visits most. Now the field completes inline from history: the site of his most visited page whose host begins with what he typed ("you" becomes youtube.com, with a port kept for a family host), or, once the text has a slash, the page whose address begins with it. "www." is skipped unless typed, a typed scheme completes only its own pages, and a search or a whole site already typed is never stretched. The completion appears only while Dad types at the end of the text; a deletion or an edit in the middle is never completed again.
The rest is small and felt every minute. The first click selects the whole address, so typing replaces it. Outside the field the address is shown short: no https://, no leading www., no slash on a site's root, while plain http:// keeps its scheme so an insecure page still says so. Inside the field the whole address shows, because what Dad copies must be the address itself. The field's menu offers Paste and Go, or Paste and Search for words. A magnifier appears when a page sits at a zoom other than the default.
"3 of 17"
WebKit's find moves from match to match but answers only whether there was one. The count comes from the page itself: a script in Voyager's own content world walks the visible text, skipping scripts, styles and hidden nodes as WebKit's find does, and finds where the selection sits. The label then follows three cases, shown in the first code block. Find runs as Dad types, after a 150 ms pause, and starts from the match already selected so a longer word stays put. ⌘E puts the selection into the bar and into the find pasteboard that every Mac app shares.
Sound, downloads, dialogs and other apps
- m9: a tab that plays sound shows a speaker that mutes it. WebKit has no public mute, so Voyager mutes the page's media elements from its own script in every frame. Sound made with no element is neither heard nor muted, and the engine evaluation says so.
- m2: back and forward held for 0.4 seconds, or right-clicked, list the page's own history.
- m3: a download says it started, arrived or failed, and the Dock's Downloads stack bounces with the file.
- m4: a dialog from a tab behind waits until that tab is in front instead of pulling it forward.
- m5: a mail link opens Mail; any other app link asks once, with "Always allow <site> to open <app> links" remembered per site and scheme, never from a private window.
A strip that never loses a tab
Before M6, a tab past the strip's right edge was reachable only by ⌘9 or ⌃Tab. Now tabs narrow to 34 points times the interface scale. Under 64 times the scale a tab shows only its icon, and the tab in front only its close button, as Chrome's narrowest tabs do. Past that the strip draws a run of tabs, computed by TabRun, a pure function in the parent: as many as fit, moved so the tab in front is in view, never leaving room empty at the end. A chevron lists every tab. And m8 lets a tab be dragged out into a window of its own, or onto another window.
Two AppKit lessons from just before
Two fixes from earlier that month belong with these rows. In the title bar, AppKit tells the window server that only controls own their presses, so the top 28 points of every plain-view tab moved the window instead of the tab (todo #424, 2026-10-13). TabItemView became an NSControl, and it takes the first click of a window behind, as Chrome's tabs do. Then the mouse: WebKit acts on neither the side buttons nor the swipe that Logi Options+ sends in their place, so one local event monitor takes both before the page sees them and runs the window's own Back and Forward (todo #460, 2026-10-16). HistoryStep is the pure part that maps a button number or a swipe to a step.