Skip to content

Commit fb7fff4

Browse files
authored
ntp: prevent gradients bleeding through (#1382)
* ntp: prevent gradients bleeding through * fixed tests * set explicit widths on icon+text to prevent overflows
1 parent b2b227e commit fb7fff4

File tree

6 files changed

+61
-49
lines changed

6 files changed

+61
-49
lines changed

special-pages/pages/new-tab/app/components/App.module.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ body {
2020
body:has([data-reset-layout="true"]) .tube {
2121
padding-top: 0;
2222
}
23+
body[data-animate-background="true"] {
24+
transition: background-color .3s;
25+
}
2326

2427
:global(.layout-centered) {
2528
margin-inline: auto;

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

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { values } from '../customizer/values.js';
55
import { useContext, useState } from 'preact/hooks';
66
import { CustomizerContext } from '../customizer/CustomizerProvider.js';
77
import { detectThemeFromHex } from '../customizer/utils.js';
8+
import { useSignalEffect } from '@preact/signals';
89

910
/**
1011
* @import { BackgroundVariant, BrowserTheme } from "../../types/new-tab"
@@ -59,40 +60,56 @@ export function BackgroundConsumer({ browser }) {
5960
const { data } = useContext(CustomizerContext);
6061
const background = data.value.background;
6162

62-
switch (background.kind) {
63-
case 'default': {
64-
return <div className={styles.root} data-testid="BackgroundConsumer" data-background-kind="default" data-theme={browser} />;
63+
useSignalEffect(() => {
64+
const background = data.value.background;
65+
66+
// reflect some values onto the <body> tag
67+
document.body.dataset.backgroundKind = background.kind;
68+
let nextBodyBackground = '';
69+
70+
if (background.kind === 'gradient') {
71+
const gradient = values.gradients[background.value];
72+
nextBodyBackground = gradient.fallback;
73+
}
74+
if (background.kind === 'color') {
75+
const color = values.colors[background.value];
76+
nextBodyBackground = color.hex;
77+
}
78+
if (background.kind === 'hex') {
79+
nextBodyBackground = background.value;
6580
}
81+
if (background.kind === 'userImage') {
82+
const isDark = background.value.colorScheme === 'dark';
83+
nextBodyBackground = isDark ? 'var(--default-dark-bg)' : 'var(--default-light-bg)';
84+
}
85+
if (background.kind === 'default') {
86+
nextBodyBackground = browser.value === 'dark' ? 'var(--default-dark-bg)' : 'var(--default-light-bg)';
87+
}
88+
89+
document.body.style.setProperty('background-color', nextBodyBackground);
90+
91+
// let animations occur, after properties above have been flushed to the DOM
92+
if (!document.body.dataset.animateBackground) {
93+
requestAnimationFrame(() => {
94+
document.body.dataset.animateBackground = 'true';
95+
});
96+
}
97+
});
98+
99+
switch (background.kind) {
100+
case 'color':
101+
case 'default':
66102
case 'hex': {
67-
return (
68-
<div
69-
class={styles.root}
70-
data-animate="true"
71-
data-testid="BackgroundConsumer"
72-
style={{
73-
backgroundColor: background.value,
74-
}}
75-
></div>
76-
);
103+
return null;
77104
}
78-
case 'color': {
79-
const color = values.colors[background.value];
80-
return (
81-
<div
82-
class={styles.root}
83-
data-animate="true"
84-
data-background-color={color.hex}
85-
data-testid="BackgroundConsumer"
86-
style={{
87-
backgroundColor: color.hex,
88-
}}
89-
></div>
90-
);
105+
case 'userImage': {
106+
const img = background.value;
107+
return <ImageCrossFade src={img.src} />;
91108
}
92109
case 'gradient': {
93110
const gradient = values.gradients[background.value];
94111
return (
95-
<Fragment key="gradient">
112+
<Fragment>
96113
<ImageCrossFade src={gradient.path}></ImageCrossFade>
97114
<div
98115
className={styles.root}
@@ -102,17 +119,13 @@ export function BackgroundConsumer({ browser }) {
102119
opacity: 0.5,
103120
mixBlendMode: 'soft-light',
104121
}}
105-
></div>
122+
/>
106123
</Fragment>
107124
);
108125
}
109-
case 'userImage': {
110-
const img = background.value;
111-
return <ImageCrossFade src={img.src} />;
112-
}
113126
default: {
114127
console.warn('Unreachable!');
115-
return <div className={styles.root}></div>;
128+
return null;
116129
}
117130
}
118131
}

special-pages/pages/new-tab/app/components/BackgroundReceiver.module.css

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,7 @@
88
pointer-events: none;
99

1010
&[data-animate="true"] {
11-
transition: background .25s ease-in-out;
12-
}
13-
&[data-background-kind="default"][data-theme=dark] {
14-
background: var(--default-dark-bg);
15-
}
16-
&[data-background-kind="default"][data-theme=light] {
17-
background: var(--default-light-bg);
11+
transition: background .3s;
1812
}
1913
}
2014

special-pages/pages/new-tab/app/customizer/integration-tests/customizer.page.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,21 +129,20 @@ export class CustomizerPage {
129129

130130
async hasDefaultBackground() {
131131
const { page } = this.ntp;
132-
await expect(page.getByTestId('BackgroundConsumer')).toHaveCSS('background-color', 'rgb(250, 250, 250)');
132+
await expect(page.locator('body')).toHaveCSS('background-color', 'rgb(250, 250, 250)');
133133
}
134134

135135
async hasDefaultDarkBackground() {
136136
const { page } = this.ntp;
137-
await expect(page.getByTestId('BackgroundConsumer')).toHaveCSS('background-color', 'rgb(51, 51, 51)');
137+
await expect(page.locator('body')).toHaveCSS('background-color', 'rgb(51, 51, 51)');
138138
}
139139

140140
/**
141-
* @param {keyof typeof values.colors} color
141+
* @param {string} expectedRGB
142142
*/
143-
async hasColorBackground(color) {
143+
async hasColorBackground(expectedRGB) {
144144
const { page } = this.ntp;
145-
const value = values.colors[color];
146-
await expect(page.getByTestId('BackgroundConsumer')).toHaveAttribute('data-background-color', value.hex);
145+
await expect(page.locator('body')).toHaveCSS('background-color', expectedRGB);
147146
}
148147

149148
async selectsColor() {

special-pages/pages/new-tab/app/customizer/integration-tests/customizer.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ test.describe('newtab customizer', () => {
8080
kind: 'color',
8181
value: 'color01',
8282
});
83-
await cp.hasColorBackground('color01');
83+
await cp.hasColorBackground('rgb(0, 0, 0)');
8484
});
8585
test('loads with the default background and accepts theme update', async ({ page }, workerInfo) => {
8686
const ntp = NewtabPage.create(page, workerInfo);

special-pages/pages/new-tab/app/favorites/components/Tile.module.css

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
.item {
2+
--icon-width: 4rem;
3+
24
display: block;
35
position: relative;
46
text-decoration: none;
@@ -29,8 +31,8 @@
2931
display: grid;
3032
align-content: center;
3133
justify-items: center;
32-
width: 4rem;
33-
height: 4rem;
34+
width: var(--icon-width);
35+
height: var(--icon-width);
3436
margin-bottom: 4px;
3537
border-radius: var(--border-radius-lg);
3638
}
@@ -89,6 +91,7 @@
8991
}
9092

9193
.text {
94+
width: var(--icon-width);
9295
text-align: center;
9396
font-size: calc(10 * var(--px-in-rem));
9497
line-height: 1.1;

0 commit comments

Comments
 (0)