Repository navigation
feat(browser): Chrome-style new tab and address bar suggestions - #31604
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to
|
…switch to tab A new tab's bar held the text "about:blank", so a click before typing merged the input into it and Enter silently failed.
…us when the list closes
…en tabs by exact URL Enter on a completion skipped the remote pane's file-URL check, and the history key dropped meaningful trailing slashes.
…tion the caret accepts
…switch-to-tab subscription
…mpletes to the same text
A row without an icon of its own, like a host completion, takes one from history on the same host.
…hosts A background tab's title update re-ranks history, which could move row 0 off the page the bar shows.
…s row Row 0 now follows the shown completion text, so evicted history can't move it either.
01377f3 to
bdaf5a5
Compare
ELI5
A new browser tab now opens with an empty address bar that says "Search or enter URL". Before, it said
about:blank, and clicking into it before typing glued your text onto that, so Enter did nothing. While you type, pages you've visited now come before the web search, and a visited address fills in as you type, like Chrome. If a suggestion is already open in another tab, its row has a "Switch to tab" button that takes you there instead of opening a second copy. Each page suggestion shows that site's icon, like the tab strip, and web searches keep the magnifier.What Changed
New tab. A new tab still loads the same blank page under the hood. The only change is how the address bar shows it:
toDisplayUrlnow turns a blank page into an empty string instead of the textabout:blank. Every pane that draws the bar goes through that function: local, client-hosted, remote streamed, and the document preview edit. The bar also gets a "Search or enter URL" placeholder.Root cause of "typing breaks": the bar held the real text
about:blankand relied on select-all-on-focus to protect it. A click on the already-focused bar, an arrow key, or Home/End dropped the selection. The input then becameabout:blankexample.com, which fails validation, and blank tabs hide the error overlay, so Enter looked dead.Suggestion order. Same rule as Chrome: row 0 is always what Enter does.
git→git|hub.com, with the rest selected) and that page is row 0. Your other history comes next, and the search for your text goes last.localhost:3000never jumps to/dashboardbecause you went there more often.file:URLs and so on. Completions that the submit path would treat as a search (intranet) or reach somewhere else aren't offered: path case, afile:URL's host, or a bare host whose default scheme differs from the visited one (localhost:3000for anhttps:dev server).Suggestion icons. On main, page rows (history, the typed address, the inline completion) all show a globe; web search rows already show the magnifier.
BrowserFaviconthe tab strip and the new-tab omnibox use: 14px box, broken image falls back to the globe, light outline for dark icons on dark themes.git→github.com, a typed address, an entry saved without one) takes the icon of a visited page on the same host, ignoringwww..Switch to tab.
buildSearchableBrowserPages, split out ofbuildOpenTabSearchEntries), so host ownership and worktree-id collisions across hosts behave the same. The bar reads them only while its list is open.activateBrowserPagePaletteResult. If that tab closed in the meantime, the row opens here instead.BrowserAddressBar.tsxwas already at the 400-line cap, so the inline completion, switch to tab, the edit hand-off on remount, and the overlay width measuring each moved into their own small hooks.Design
Chosen: keep the blank guest and change only what the bar shows. Use Chrome's "row 0 is what Enter does" with host-first inline completion, plus a Switch-to-tab button.
Ruled out:
orca://newtabURL, anabout:blanksrc, or no guest until first navigation. The attach policy and SSH route partitions only allow the blank data URL, so any of these means main-process and guest-lifecycle changes for nothing the user can see.react hooksopening a page titled "React hooks").Two blind design-challenge rounds ran before code. They led to host-first completion, one decision for row order and completion, and reusing the palette's open-page builder.
For suggestion icons: reuse history's stored favicon plus a same-host fallback, rendered with the tab strip's
BrowserFavicon. Ruled out: Chrome's favicon database (image bytes per page). It needs main-process capture through each guest's session partition and a bigger saved session (#18161), and every other Orca surface already loads the same icon URLs. Also ruled out: an origin-keyed fallback, which missesyoutube.comcompleting fromwww.youtube.comhistory. Two blind design rounds; the first moved the key to thewww.-stripped host.Open questions for you:
browser_navigator.cc). I left it out: remote pages always report back history, so "nothing to go back to" can't be trusted there. Want it for local blank tabs?Not in this PR (different root cause):
orca tab listand the agent bridge report blank local tabs asdata:text/html,(url and title), because main readswc.getURL()raw at about a dozen sites.showFailureOverlayis gated on!isBlankTab. The remote pane already shows it.aria-controls="browser-history-listbox"points at nothing.github.com/stablyai/orca, was saved without one; a traced visit towikipedia.orgbackfilled fine, so the cause isn't pinned. The same-host fallback covers it in the address bar. The new-tab omnibox still shows a globe for that entry.favicon-dark.pngis faint on a light Orca theme, in the tab strip and now in these rows (see the lightgitshot).Mobile:
displayBrowserUrlinmobile/src/browser/browser-url.tsstill showsabout:blank, and the field's placeholder is "URL". Parity needs those two lines plus, if wanted, the same row order and switch button in the mobile suggestion UI. Favicons would also need history to reach mobile, which has no browser history of its own today. The mobile app doesn't use this component, so nothing here changes it.Linked Issue
None. Requested internally. #537 (closed) asked for a custom landing page instead of
about:blank; this doesn't add that, but a new tab no longer showsabout:blank.Visual Proof
All recorded on a hidden dev build over CDP, using the same scripted flows before and after. History was seeded by visiting real pages.
1. New tab, click into the bar, type
example.com, EnterBefore: the bar shows
about:blank. After the click, typing givesabout:blankexample.comand Enter does nothing.before-newtab-light.mp4
After (light, then dark): an empty bar with the placeholder.
ecompletes toexample.com, and Enter loads it.after-newtab-light.mp4
after-newtab-dark.mp4
2. Order: type
git; 3. Switch to tab: typepulls, arrow to the open page, Tab, EnterBefore: the
gitsearch sits above your GitHub history. Picking the open pulls page loads a second copy.before-omnibox-light.mp4
After (light, then dark):
gitcompletes togithub.com, history follows, and the search is last.pullsshows "Switch to tab". Tab fills the button, and Enter goes to the existing tab.after-omnibox-light.mp4
after-omnibox-dark.mp4
gitpullsDark:
4. Suggestion icons: type
git,news,dev,exa,react hooksSame history in both builds: GitHub, Hacker News, MDN and example.com (which has no favicon).
Before (
origin/main, light then dark): every page row has a globe; only the search row has the magnifier.before-icons-flow-light.mp4
before-icons-flow-dark.mp4
After (light then dark): GitHub, Hacker News and MDN rows show their icons, including the
github.comanddeveloper.mozilla.orgcompletion rows with no history entry of their own. example.com keeps the globe. Searches keep the magnifier.after-icons-flow-light.mp4
after-icons-flow-dark.mp4
gitdevexa(no favicon)git, darkIn the light
gitshot, GitHub's icon is its white dark-mode variant (see "Not in this PR"); the tab strip shows the same one.Testing
Manual testing (macOS, hidden dev build driven over CDP with real keys):
https://github.com/stablyai/orca/pu, then ArrowDown, ArrowUp: the completion comes back with its tail selected, and Escape restores the typed text.Automated tests (each fails on the code before its fix):
localhost:3000, path case,intranetandfile:.www..file:hosts and scheme changes.Existing tests that pinned
about:blankin the bar now expect''.Gates on the rebased head:
pnpm lint,pnpm tc,oxfmt --check ., import boundaries,check:code-quality:changed,check:react-doctor:changed,check:zustand-selector-fanout, and the browser-pane, tab-bar, favicon and history tests (1,845). React Doctor reports two non-blocking warnings on lines from the earlier commits.Not tested:
toDisplayUrl, and their unit tests pass. Remote and client-hosted pages record no favicon, so their rows can only show an icon learned locally for the same host.Review: codex ran three rounds against
origin/main, with two P2 findings per round, all fixed with a test. The loop hit its three-round cap rather than ending on a clean round.file:check; switch matching collapsed URLs that differ only by a trailing/in the query.Recording the AFTER video caught one more bug: the selection was lost when a keystroke completed to the same text. It's fixed with a key-by-key test.
Review, suggestion icons follow-up: three more codex rounds. None of the findings were in the icon code; all were about inline completion, and each is fixed with a test that fails without it. The loop hit its cap again.
file:hosts completed to a website.localhost:3000forhttps://localhost:3000).The round 3 fix itself wasn't reviewed by codex again.
AI Disclosure
Review
Agent skill upstream boundary
Notes
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)