Skip to content

Commit bacb6d9

Browse files
authored
NTP: Remove search icon and input suffix from omnibar, tweak surface colours (#1871)
1 parent c626203 commit bacb6d9

15 files changed

+52
-123
lines changed

special-pages/pages/new-tab/app/omnibar/components/Omnibar.module.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
.root:has([role="listbox"]) .popup,
6060
.root:not(:has([role="listbox"])) .field {
61-
backdrop-filter: blur(48px);
61+
backdrop-filter: blur(16px);
6262
background: var(--ntp-surface-tertiary);
6363
border-radius: var(--border-radius-lg);
6464
}

special-pages/pages/new-tab/app/omnibar/components/OmnibarConsumer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function OmnibarReadyState({ config: { enableAi = true, showAiSetting = true, mo
4141
return (
4242
<>
4343
{showAiSetting && <AiSetting enableAi={enableAi} setEnableAi={setEnableAi} />}
44-
<Omnibar mode={mode} setMode={setMode} enableAi={enableAi} />
44+
<Omnibar mode={mode} setMode={setMode} enableAi={showAiSetting && enableAi} />
4545
</>
4646
);
4747
}

special-pages/pages/new-tab/app/omnibar/components/SearchForm.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Fragment, h } from 'preact';
22
import { useEffect, useMemo } from 'preact/hooks';
33
import { eventToTarget } from '../../../../../shared/handlers.js';
4-
import { GlobeIcon, SearchIcon } from '../../components/Icons.js';
54
import { usePlatformName } from '../../settings.provider.js';
65
import { useTypedTranslationWith } from '../../types';
76
import { getInputSuffix, getSuggestionCompletionString, startsWithIgnoreCase } from '../utils.js';
@@ -125,7 +124,6 @@ export function SearchForm({ autoFocus, onOpenSuggestion, onSubmit }) {
125124
});
126125
}}
127126
>
128-
{inputSuffix?.kind === 'visit' ? <GlobeIcon inert /> : <SearchIcon inert />}
129127
<input
130128
ref={inputRef}
131129
type="text"

special-pages/pages/new-tab/app/omnibar/components/SearchForm.module.css

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
.form {
22
align-items: center;
33
display: flex;
4-
padding: var(--sp-1) 7px;
5-
6-
svg {
7-
flex: none;
8-
margin: var(--sp-2);
9-
}
4+
height: var(--sp-10);
5+
padding: var(--sp-1) 7px var(--sp-1) calc(7px + var(--sp-2));
106
}
117

128
.input {
@@ -17,7 +13,7 @@
1713
height: var(--sp-8);
1814
left: 7px;
1915
padding-bottom: 0;
20-
padding-left: calc(var(--sp-2) + var(--sp-4) + var(--sp-2));
16+
padding-left: var(--sp-2);
2117
padding-right: var(--suffix-text-width);
2218
padding-top: 0;
2319
position: absolute;

special-pages/pages/new-tab/app/omnibar/unit-tests/utils.spec.js

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
getSuggestionCompletionString,
77
getSuggestionSuffix,
88
parseURL,
9-
isURLish,
109
formatURL,
1110
formatURLForTerm,
1211
getDuckDuckGoSearchQuery,
@@ -22,23 +21,8 @@ test.describe('getInputSuffix', () => {
2221
equal(getInputSuffix('', null), null);
2322
});
2423

25-
test('returns "Visit $url" for url-like input', () => {
26-
let suffix = getInputSuffix('example.com', null);
27-
equal(suffix?.kind, 'visit');
28-
equal(suffix?.url, 'example.com');
29-
30-
suffix = getInputSuffix('https://foobar.com/path', null);
31-
equal(suffix?.kind, 'visit');
32-
equal(suffix?.url, 'foobar.com/path');
33-
34-
suffix = getInputSuffix('www.foo.com/bar/?q=yes#frag', null);
35-
equal(suffix?.kind, 'visit');
36-
equal(suffix?.url, 'www.foo.com/bar');
37-
});
38-
39-
test('returns "Search DuckDuckGo" for non-url terms', () => {
40-
const suffix = getInputSuffix('pizza delivery near me', null);
41-
equal(suffix?.kind, 'searchDuckDuckGo');
24+
test('returns null when there is no selected suggestion', () => {
25+
equal(getInputSuffix('pizza', null), null);
4226
});
4327

4428
test('returns "Search DuckDuckGo" if selected suggestion is a phrase', () => {
@@ -361,50 +345,6 @@ test.describe('parseURL', () => {
361345
});
362346
});
363347

364-
test.describe('isURLish', () => {
365-
test('returns true for simple domain with dot', () => {
366-
equal(isURLish('example.com'), true);
367-
equal(isURLish('foo.bar'), true);
368-
equal(isURLish('some.site'), true);
369-
equal(isURLish('my-site.org'), true);
370-
});
371-
372-
test('returns true for full url', () => {
373-
equal(isURLish('https://example.com'), true);
374-
equal(isURLish('http://www.example.com'), true);
375-
equal(isURLish('ftp://files.example.com'), true);
376-
});
377-
378-
test('returns true for domain with path/params/hash', () => {
379-
equal(isURLish('example.com/path'), true);
380-
equal(isURLish('example.com/index.html'), true);
381-
equal(isURLish('example.com?q=search'), true);
382-
equal(isURLish('example.com/path#hash'), true);
383-
equal(isURLish('example.com:8080'), true);
384-
});
385-
386-
test('returns false for regular strings', () => {
387-
equal(isURLish('localhost'), false);
388-
equal(isURLish('duck'), false);
389-
equal(isURLish('what time is it'), false);
390-
});
391-
392-
test('returns false for empty string', () => {
393-
equal(isURLish(''), false);
394-
});
395-
396-
test('returns true for IP addresses', () => {
397-
equal(isURLish('127.0.0.1'), true);
398-
equal(isURLish('192.168.1.1'), true);
399-
equal(isURLish('8.8.8.8:53'), true);
400-
});
401-
402-
test('returns true for URLs with subdomains', () => {
403-
equal(isURLish('www.example.com'), true);
404-
equal(isURLish('a.b.c.domain.co.uk'), true);
405-
});
406-
});
407-
408348
test.describe('formatURL', () => {
409349
test('returns full URL by default (scheme, www, trailing slash, search, hash)', () => {
410350
const url = new URL('https://www.example.com/path/?q=123#myhash');

special-pages/pages/new-tab/app/omnibar/utils.js

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,43 +25,24 @@
2525
* @returns {Suffix}
2626
*/
2727
export function getInputSuffix(term, selectedSuggestion) {
28-
if (!term) {
29-
return null;
30-
}
31-
32-
if (selectedSuggestion) {
33-
return getSuggestionInputSuffix(selectedSuggestion, term);
34-
}
28+
// Intentionally differs from the macOS app's implementation, which returns
29+
// "Search DuckDuckGo" or "Visit $url" when there is a term and no selection
30+
if (!term || !selectedSuggestion) return null;
3531

36-
if (isURLish(term)) {
37-
const url = parseURL(term);
38-
if (!url) throw new Error('isURLish returned true but parseURL failed');
39-
return { kind: 'visit', url: formatURL(url, { scheme: false, trailingSlash: false, search: false, hash: false }) };
40-
} else {
41-
return { kind: 'searchDuckDuckGo' };
42-
}
43-
}
44-
45-
/**
46-
* @param {Suggestion} suggestion
47-
* @param {string} term
48-
* @returns {Suffix}
49-
*/
50-
function getSuggestionInputSuffix(suggestion, term) {
51-
switch (suggestion.kind) {
32+
switch (selectedSuggestion.kind) {
5233
case 'phrase':
5334
return { kind: 'searchDuckDuckGo' };
5435
case 'website': {
55-
const url = parseURL(suggestion.url);
36+
const url = parseURL(selectedSuggestion.url);
5637
if (!url) return null;
5738
return { kind: 'visit', url: formatURL(url, { scheme: false, trailingSlash: false, search: false, hash: false }) };
5839
}
5940
case 'bookmark':
6041
case 'historyEntry':
6142
case 'internalPage': {
62-
const title = getSuggestionTitle(suggestion, term);
63-
const autocompletion = getSuggestionCompletionString(suggestion, term);
64-
const url = parseURL(suggestion.url);
43+
const title = getSuggestionTitle(selectedSuggestion, term);
44+
const autocompletion = getSuggestionCompletionString(selectedSuggestion, term);
45+
const url = parseURL(selectedSuggestion.url);
6546
if (title && title !== autocompletion) {
6647
return { kind: 'raw', text: title };
6748
} else if (url) {
@@ -174,15 +155,6 @@ export function parseURL(string) {
174155
return null;
175156
}
176157

177-
/**
178-
* @param {string} string
179-
* @returns {boolean}
180-
*/
181-
export function isURLish(string) {
182-
// @todo: This is overly simplistic.
183-
return string.includes('.') && parseURL(string) !== null;
184-
}
185-
186158
/**
187159
* @param {URL} url
188160
* @param {object} [options]

special-pages/pages/new-tab/app/styles/ntp-theme.css

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ body {
6060

6161
/* Global Colors & Styles - https://www.figma.com/design/3W4vi0zX8hrpQc7zInQQB6/%F0%9F%8E%A8-Global-Colors---Styles?node-id=11-1&p=f&vars=1&m=dev */
6262
/* @todo: This palette is what the native apps use, we should gradually move over to it */
63-
--ntp-surface-tertiary: #FFFFFF;
64-
--ntp-text-primary: #1F1F1F;
65-
--ntp-text-tertiary: rgba(31, 31, 31, 0.4);
66-
--ntp-icons-primary: rgba(31, 31, 31, 0.84);
63+
--ntp-surface-tertiary: rgba(255, 255, 255, 0.88); /* This differs from Figma. We're adding alpha so that surfaces blend with custom backgrounds. */
64+
--ntp-text-primary: rgba(0, 0, 0, 0.96);
65+
--ntp-text-tertiary: rgba(0, 0, 0, 0.42);
66+
--ntp-icons-primary: rgba(0, 0, 0, 0.84);
6767
--ntp-icons-tertiary: rgba(0, 0, 0, 0.36);
6868
--ntp-accent-primary: var(--color-blue-50);
6969
--ntp-accent-secondary: var(--color-blue-60);
@@ -94,9 +94,9 @@ body {
9494

9595
/* Global Colors & Styles - https://www.figma.com/design/3W4vi0zX8hrpQc7zInQQB6/%F0%9F%8E%A8-Global-Colors---Styles?node-id=11-1&p=f&vars=1&m=dev */
9696
/* @todo: This palette is what the native apps use, we should gradually move over to it */
97-
--ntp-surface-tertiary: rgba(71, 71, 71, 0.66); /* @fixme: This differs from Figma. We're adding alpha so that surfaces blend with custom backgrounds. */
98-
--ntp-text-primary: rgba(255, 255, 255, 0.9);
99-
--ntp-text-tertiary: rgba(255, 255, 255, 0.4);
97+
--ntp-surface-tertiary: rgba(0, 0, 0, 0.72); /* This differs from Figma. We're adding alpha so that surfaces blend with custom backgrounds. */
98+
--ntp-text-primary: rgba(255, 255, 255, 0.96);
99+
--ntp-text-tertiary: rgba(255, 255, 255, 0.36);
100100
--ntp-icons-primary: rgba(255, 255, 255, 0.78);
101101
--ntp-icons-tertiary: rgba(255, 255, 255, 0.24);
102102
--ntp-accent-primary: var(--color-blue-20);

special-pages/pages/new-tab/integration-tests/new-tab.screenshots.spec.js

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,36 @@ test.describe('NTP screenshots', { tag: ['@screenshots'] }, () => {
167167
});
168168
});
169169

170-
test('ai disabled', async ({ page }, workerInfo) => {
171-
const ntp = NewtabPage.create(page, workerInfo);
172-
const omnibar = new OmnibarPage(ntp);
173-
await ntp.reducedMotion();
174-
await ntp.openPage({ additional: { omnibar: 'true', 'omnibar.enableAi': 'false' } });
175-
await omnibar.ready();
176-
await expect(page).toHaveScreenshot('omnibar-ai-disabled.png', { maxDiffPixels });
170+
test.describe('sidebar', () => {
171+
test('ai enabled', async ({ page }, workerInfo) => {
172+
const ntp = NewtabPage.create(page, workerInfo);
173+
const omnibar = new OmnibarPage(ntp);
174+
await ntp.reducedMotion();
175+
await ntp.openPage({ additional: { omnibar: 'true' } });
176+
await omnibar.ready();
177+
await omnibar.customizeButton().click();
178+
await expect(page).toHaveScreenshot('omnibar-sidebar-ai-enabled.png', { maxDiffPixels });
179+
});
180+
181+
test('ai disabled', async ({ page }, workerInfo) => {
182+
const ntp = NewtabPage.create(page, workerInfo);
183+
const omnibar = new OmnibarPage(ntp);
184+
await ntp.reducedMotion();
185+
await ntp.openPage({ additional: { omnibar: 'true', 'omnibar.enableAi': 'false' } });
186+
await omnibar.ready();
187+
await omnibar.customizeButton().click();
188+
await expect(page).toHaveScreenshot('omnibar-sidebar-ai-disabled.png', { maxDiffPixels });
189+
});
190+
191+
test('hide ai setting', async ({ page }, workerInfo) => {
192+
const ntp = NewtabPage.create(page, workerInfo);
193+
const omnibar = new OmnibarPage(ntp);
194+
await ntp.reducedMotion();
195+
await ntp.openPage({ additional: { omnibar: 'true', 'omnibar.showAiSetting': 'false' } });
196+
await omnibar.ready();
197+
await omnibar.customizeButton().click();
198+
await expect(page).toHaveScreenshot('omnibar-sidebar-hide-ai-setting.png', { maxDiffPixels });
199+
});
177200
});
178201
});
179202
});
Loading

0 commit comments

Comments
 (0)