Skip to content

Commit f996039

Browse files
shakyShanemgurgel
andauthored
ntp: support default background colors (#1596)
* ntp: support default background colors * hash * bring example into docs * screenshot tag * support history view also * Hash --------- Co-authored-by: Marcos Gurgel <[email protected]>
1 parent 8f55dc1 commit f996039

32 files changed

+386
-21
lines changed

injected/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
},
3131
"devDependencies": {
3232
"@canvas/image-data": "^1.0.0",
33-
"@duckduckgo/privacy-configuration": "github:duckduckgo/privacy-configuration#main",
33+
"@duckduckgo/privacy-configuration": "github:duckduckgo/privacy-configuration#ca6101bb972756a87a8960ffb3029f603052ea9d",
3434
"@fingerprintjs/fingerprintjs": "^4.5.1",
3535
"@types/chrome": "^0.0.308",
3636
"@types/jasmine": "^5.1.7",

package-lock.json

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

special-pages/pages/history/app/history.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ title: History View
99
### `initialSetup`
1010
{@link "History Messages".InitialSetupRequest}
1111

12-
Configures initial history system settings.
12+
Configure initial history system settings.
1313

1414
**Types:**
1515
- Response: {@link "History Messages".InitialSetupResponse}
@@ -24,6 +24,22 @@ Configures initial history system settings.
2424
}
2525
```
2626

27+
With {@link "History Messages".DefaultStyles} overrides
28+
29+
```json
30+
{
31+
"locale": "en",
32+
"env": "production",
33+
"platform": {
34+
"name": "macos"
35+
},
36+
"defaultStyles": {
37+
"lightBackgroundColor": "#E9EBEC",
38+
"darkBackgroundColor": "#27282A"
39+
}
40+
}
41+
```
42+
2743
### `getRanges`
2844
{@link "History Messages".GetRangesRequest}
2945

special-pages/pages/history/app/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ export async function init(root, messaging, baseEnvironment) {
5959
messaging.reportInitException({ message });
6060
};
6161

62+
// apply default styles
63+
applyDefaultStyles(init.defaultStyles);
64+
6265
const strings = await getStrings(environment);
6366
const service = new HistoryService(messaging);
6467
const query = paramsToQuery(environment.urlParams, 'initial');
@@ -108,6 +111,20 @@ export async function init(root, messaging, baseEnvironment) {
108111
}
109112
}
110113

114+
/**
115+
* This will apply default background colors as early as possible.
116+
*
117+
* @param {import("../types/history.ts").DefaultStyles | null | undefined} defaultStyles
118+
*/
119+
function applyDefaultStyles(defaultStyles) {
120+
if (defaultStyles?.lightBackgroundColor) {
121+
document.body.style.setProperty('--default-light-background-color', defaultStyles.lightBackgroundColor);
122+
}
123+
if (defaultStyles?.darkBackgroundColor) {
124+
document.body.style.setProperty('--default-dark-background-color', defaultStyles.darkBackgroundColor);
125+
}
126+
}
127+
111128
/**
112129
* @param {import('../types/history.js').HistoryQuery} query
113130
* @param {HistoryService} service

special-pages/pages/history/app/mocks/mock-transport.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ export function mockTransport() {
157157
platform: { name: 'integration' },
158158
env: 'development',
159159
locale: 'en',
160+
defaultStyles: getDefaultStyles(),
160161
};
161162

162163
return Promise.resolve(initial);
@@ -195,6 +196,20 @@ export function mockTransport() {
195196
});
196197
}
197198

199+
/**
200+
* @returns {import("../../types/history").DefaultStyles | null}
201+
*/
202+
function getDefaultStyles() {
203+
if (url.searchParams.get('defaultStyles') === 'visual-refresh') {
204+
// https://app.asana.com/0/1201141132935289/1209349703167198/f
205+
return {
206+
lightBackgroundColor: '#E9EBEC',
207+
darkBackgroundColor: '#27282A',
208+
};
209+
}
210+
return null;
211+
}
212+
198213
async function withLatency(value) {
199214
let queryLatency = 50;
200215
const fromParam = url.searchParams.get('query.latency');

special-pages/pages/history/integration-tests/history.page.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,19 @@ export class HistoryTestPage {
588588
async selectedRowCountIs(number) {
589589
await expect(this.main().locator('[aria-selected="true"]')).toHaveCount(number);
590590
}
591+
592+
/**
593+
* @param {object} params
594+
* @param {string} params.hex
595+
* @returns {Promise<void>}
596+
*/
597+
async hasBackgroundColor({ hex }) {
598+
const r = parseInt(hex.slice(1, 3), 16);
599+
const g = parseInt(hex.slice(3, 5), 16);
600+
const b = parseInt(hex.slice(5, 7), 16);
601+
const rgb = `rgb(${[r, g, b].join(', ')})`;
602+
await expect(this.page.locator('[data-layout-mode="normal"]')).toHaveCSS('background-color', rgb, { timeout: 50 });
603+
}
591604
}
592605

593606
/**

special-pages/pages/history/integration-tests/history.spec.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,4 +235,32 @@ test.describe('history', () => {
235235
await hp.submitSearchForm();
236236
await hp.didMakeNthQuery({ nth: 2, query: { term: 'café' } });
237237
});
238+
test.describe('default background colors', () => {
239+
test('default background light', async ({ page }, workerInfo) => {
240+
const hp = HistoryTestPage.create(page, workerInfo).withEntries(0);
241+
await hp.openPage();
242+
await hp.hasEmptyState();
243+
await hp.hasBackgroundColor({ hex: '#fafafa' });
244+
});
245+
test('default background dark', async ({ page }, workerInfo) => {
246+
const hp = HistoryTestPage.create(page, workerInfo).withEntries(0);
247+
await hp.darkMode();
248+
await hp.openPage();
249+
await hp.hasEmptyState();
250+
await hp.hasBackgroundColor({ hex: '#333333' });
251+
});
252+
test('with overrides from initial setup (light)', async ({ page }, workerInfo) => {
253+
const hp = HistoryTestPage.create(page, workerInfo).withEntries(0);
254+
await hp.openPage({ additional: { defaultStyles: 'visual-refresh' } });
255+
await hp.hasEmptyState();
256+
await hp.hasBackgroundColor({ hex: '#E9EBEC' });
257+
});
258+
test('with overrides from initial setup (dark)', async ({ page }, workerInfo) => {
259+
const hp = HistoryTestPage.create(page, workerInfo).withEntries(0);
260+
await hp.darkMode();
261+
await hp.openPage({ additional: { defaultStyles: 'visual-refresh' } });
262+
await hp.hasEmptyState();
263+
await hp.hasBackgroundColor({ hex: '#27282A' });
264+
});
265+
});
238266
});

special-pages/pages/history/messages/initialSetup.response.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@
1919
"enum": ["macos", "windows", "android", "ios", "integration"]
2020
}
2121
}
22+
},
23+
"defaultStyles": {
24+
"oneOf": [
25+
{
26+
"type": "null"
27+
},
28+
{
29+
"$ref": "types/default-styles.json"
30+
}
31+
]
2232
}
2333
}
2434
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"type": "object",
4+
"title": "Default Styles",
5+
"properties": {
6+
"darkBackgroundColor": {
7+
"description": "Optional default dark background color. Any HEX value is permitted",
8+
"type": "string",
9+
"examples": [
10+
"#000000",
11+
"#333333"
12+
]
13+
},
14+
"lightBackgroundColor": {
15+
"description": "Optional default light background color. Any HEX value is permitted",
16+
"type": "string",
17+
"examples": [
18+
"#FFFFFF",
19+
"#CCCCCC"
20+
]
21+
}
22+
}
23+
}

special-pages/pages/history/styles/history-theme.css

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
:root {
2-
--default-light-bg: var(--color-gray-0);
3-
--default-dark-bg: var(--color-gray-85);
4-
52
/* H1 title */
63
--title-font-size: 20px;
74
--title-font-weight: 600;
@@ -23,6 +20,11 @@
2320
--title-3-em-line-height: 20px;
2421
}
2522

23+
body {
24+
--default-light-background-color: var(--color-gray-0);
25+
--default-dark-background-color: var(--color-gray-85);
26+
}
27+
2628
/* This comes from the application settings */
2729
:root:has([data-platform="windows"]) {
2830
/* H1 title */
@@ -47,7 +49,7 @@
4749
}
4850

4951
[data-theme=light] {
50-
--history-background-color: var(--default-light-bg);
52+
--history-background-color: var(--default-light-background-color);
5153
--history-surface-background-color: var(--color-white-at-30);
5254
--history-surface-border-color: var(--color-black-at-9);
5355
--history-scrollbar-controls-color: var(--color-black-at-18);
@@ -57,7 +59,7 @@
5759
}
5860

5961
[data-theme=dark] {
60-
--history-background-color: var(--default-dark-bg);
62+
--history-background-color: var(--default-dark-background-color);
6163
--history-surface-background-color: var(--color-black-at-18);
6264
--history-surface-border-color: var(--color-white-at-12);
6365
--history-scrollbar-controls-color: var(--color-white-at-18);

special-pages/pages/history/types/history.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,17 @@ export interface InitialSetupResponse {
196196
platform: {
197197
name: "macos" | "windows" | "android" | "ios" | "integration";
198198
};
199+
defaultStyles?: null | DefaultStyles;
200+
}
201+
export interface DefaultStyles {
202+
/**
203+
* Optional default dark background color. Any HEX value is permitted
204+
*/
205+
darkBackgroundColor?: string;
206+
/**
207+
* Optional default light background color. Any HEX value is permitted
208+
*/
209+
lightBackgroundColor?: string;
199210
}
200211
/**
201212
* Generated from @see "../messages/query.request.json"

special-pages/pages/new-tab/app/components/BackgroundProvider.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,11 @@ export function BackgroundConsumer({ browser }) {
8080
}
8181
if (background.kind === 'userImage') {
8282
const isDark = background.value.colorScheme === 'dark';
83-
nextBodyBackground = isDark ? 'var(--default-dark-bg)' : 'var(--default-light-bg)';
83+
nextBodyBackground = isDark ? 'var(--default-dark-background-color)' : 'var(--default-light-background-color)';
8484
}
8585
if (background.kind === 'default') {
86-
nextBodyBackground = browser.value === 'dark' ? 'var(--default-dark-bg)' : 'var(--default-light-bg)';
86+
nextBodyBackground =
87+
browser.value === 'dark' ? 'var(--default-dark-background-color)' : 'var(--default-light-background-color)';
8788
}
8889

8990
document.body.style.setProperty('background-color', nextBodyBackground);

special-pages/pages/new-tab/app/favorites/components/Favorites.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ function useVisibleRows(rows, rowHeight, safeAreaRef, expansion) {
317317
}, [rows.length]);
318318

319319
useEffect(() => {
320-
if (!contentTubeRef.current) return console.warn('cannot find content tube');
320+
if (!contentTubeRef.current) return;
321321
let lastHeight;
322322
let debounceTimer;
323323
const resizer = new ResizeObserver((entries) => {

special-pages/pages/new-tab/app/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ export async function init(root, messaging, telemetry, baseEnvironment) {
7777
// install global side effects that are not specific to any widget
7878
installGlobalSideEffects(environment, settings);
7979

80+
// apply default styles
81+
applyDefaultStyles(init.defaultStyles);
82+
8083
// return early if we're in the 'components' view.
8184
if (environment.display === 'components') {
8285
return renderComponents(root, environment, settings, strings);
@@ -162,6 +165,20 @@ function installGlobalSideEffects(environment, settings) {
162165
document.body.dataset.animation = environment.urlParams.get('animation') || '';
163166
}
164167

168+
/**
169+
* This will apply default background colors as early as possible.
170+
*
171+
* @param {import("../types/new-tab.ts").DefaultStyles | null | undefined} defaultStyles
172+
*/
173+
function applyDefaultStyles(defaultStyles) {
174+
if (defaultStyles?.lightBackgroundColor) {
175+
document.body.style.setProperty('--default-light-background-color', defaultStyles.lightBackgroundColor);
176+
}
177+
if (defaultStyles?.darkBackgroundColor) {
178+
document.body.style.setProperty('--default-dark-background-color', defaultStyles.darkBackgroundColor);
179+
}
180+
}
181+
165182
/**
166183
*
167184
* @param {import('../types/new-tab.js').InitialSetupResponse['widgets']} widgets

special-pages/pages/new-tab/app/mock-transport.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,7 @@ export function mockTransport() {
503503
env: 'development',
504504
locale: 'en',
505505
updateNotification,
506+
defaultStyles: getDefaultStyles(),
506507
};
507508

508509
const feed = url.searchParams.get('feed') || 'stats';
@@ -539,6 +540,20 @@ export function mockTransport() {
539540
});
540541
}
541542

543+
/**
544+
* @returns {import("../types/new-tab.js").DefaultStyles | null}
545+
*/
546+
function getDefaultStyles() {
547+
if (url.searchParams.get('defaultStyles') === 'visual-refresh') {
548+
// https://app.asana.com/0/1201141132935289/1209349703167198/f
549+
return {
550+
lightBackgroundColor: '#E9EBEC',
551+
darkBackgroundColor: '#27282A',
552+
};
553+
}
554+
return null;
555+
}
556+
542557
/**
543558
* @template {{id: string}} T
544559
* @param {T[]} array

special-pages/pages/new-tab/app/new-tab.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ children:
1616
### `initialSetup`
1717
- {@link "NewTab Messages".InitialSetupRequest}
1818
- Returns {@link "NewTab Messages".InitialSetupResponse}
19-
- See the `initialSetupResponse` section of [example of initial data](../messages/examples/widgets.js)
2019
- See also
2120
- [Widget Config](./widget-list/widget-config.md) for the initial page widgets
2221
- [Update Notification](./update-notification/update-notification.md) for the optional data
2322
- [Customizer Drawer Feature Flags](./customizer/customizer.md) for optional feature flags like the customizer drawer
2423
about release notes (windows only).
2524

25+
{@includeCode ../messages/examples/widgets.js#initialSetupResponse}
26+
2627
## Notifications
2728

2829
### `contextMenu`

0 commit comments

Comments
 (0)