diff --git a/special-pages/pages/new-tab/app/components/App.module.css b/special-pages/pages/new-tab/app/components/App.module.css index d80c41919..ed1e36174 100644 --- a/special-pages/pages/new-tab/app/components/App.module.css +++ b/special-pages/pages/new-tab/app/components/App.module.css @@ -20,6 +20,9 @@ body { body:has([data-reset-layout="true"]) .tube { padding-top: 0; } +body[data-animate-background="true"] { + transition: background-color .3s; +} :global(.layout-centered) { margin-inline: auto; diff --git a/special-pages/pages/new-tab/app/components/BackgroundProvider.js b/special-pages/pages/new-tab/app/components/BackgroundProvider.js index 920dab70b..815590cda 100644 --- a/special-pages/pages/new-tab/app/components/BackgroundProvider.js +++ b/special-pages/pages/new-tab/app/components/BackgroundProvider.js @@ -5,6 +5,7 @@ import { values } from '../customizer/values.js'; import { useContext, useState } from 'preact/hooks'; import { CustomizerContext } from '../customizer/CustomizerProvider.js'; import { detectThemeFromHex } from '../customizer/utils.js'; +import { useSignalEffect } from '@preact/signals'; /** * @import { BackgroundVariant, BrowserTheme } from "../../types/new-tab" @@ -59,40 +60,56 @@ export function BackgroundConsumer({ browser }) { const { data } = useContext(CustomizerContext); const background = data.value.background; - switch (background.kind) { - case 'default': { - return
; + useSignalEffect(() => { + const background = data.value.background; + + // reflect some values onto the tag + document.body.dataset.backgroundKind = background.kind; + let nextBodyBackground = ''; + + if (background.kind === 'gradient') { + const gradient = values.gradients[background.value]; + nextBodyBackground = gradient.fallback; + } + if (background.kind === 'color') { + const color = values.colors[background.value]; + nextBodyBackground = color.hex; + } + if (background.kind === 'hex') { + nextBodyBackground = background.value; } + if (background.kind === 'userImage') { + const isDark = background.value.colorScheme === 'dark'; + nextBodyBackground = isDark ? 'var(--default-dark-bg)' : 'var(--default-light-bg)'; + } + if (background.kind === 'default') { + nextBodyBackground = browser.value === 'dark' ? 'var(--default-dark-bg)' : 'var(--default-light-bg)'; + } + + document.body.style.setProperty('background-color', nextBodyBackground); + + // let animations occur, after properties above have been flushed to the DOM + if (!document.body.dataset.animateBackground) { + requestAnimationFrame(() => { + document.body.dataset.animateBackground = 'true'; + }); + } + }); + + switch (background.kind) { + case 'color': + case 'default': case 'hex': { - return ( -
- ); + return null; } - case 'color': { - const color = values.colors[background.value]; - return ( -
- ); + case 'userImage': { + const img = background.value; + return ; } case 'gradient': { const gradient = values.gradients[background.value]; return ( - +
+ />
); } - case 'userImage': { - const img = background.value; - return ; - } default: { console.warn('Unreachable!'); - return
; + return null; } } } diff --git a/special-pages/pages/new-tab/app/components/BackgroundReceiver.module.css b/special-pages/pages/new-tab/app/components/BackgroundReceiver.module.css index 9060ff8b1..2cdfd6918 100644 --- a/special-pages/pages/new-tab/app/components/BackgroundReceiver.module.css +++ b/special-pages/pages/new-tab/app/components/BackgroundReceiver.module.css @@ -8,13 +8,7 @@ pointer-events: none; &[data-animate="true"] { - transition: background .25s ease-in-out; - } - &[data-background-kind="default"][data-theme=dark] { - background: var(--default-dark-bg); - } - &[data-background-kind="default"][data-theme=light] { - background: var(--default-light-bg); + transition: background .3s; } } diff --git a/special-pages/pages/new-tab/app/customizer/integration-tests/customizer.page.js b/special-pages/pages/new-tab/app/customizer/integration-tests/customizer.page.js index fe06a64fc..7e2200ef1 100644 --- a/special-pages/pages/new-tab/app/customizer/integration-tests/customizer.page.js +++ b/special-pages/pages/new-tab/app/customizer/integration-tests/customizer.page.js @@ -129,21 +129,20 @@ export class CustomizerPage { async hasDefaultBackground() { const { page } = this.ntp; - await expect(page.getByTestId('BackgroundConsumer')).toHaveCSS('background-color', 'rgb(250, 250, 250)'); + await expect(page.locator('body')).toHaveCSS('background-color', 'rgb(250, 250, 250)'); } async hasDefaultDarkBackground() { const { page } = this.ntp; - await expect(page.getByTestId('BackgroundConsumer')).toHaveCSS('background-color', 'rgb(51, 51, 51)'); + await expect(page.locator('body')).toHaveCSS('background-color', 'rgb(51, 51, 51)'); } /** - * @param {keyof typeof values.colors} color + * @param {string} expectedRGB */ - async hasColorBackground(color) { + async hasColorBackground(expectedRGB) { const { page } = this.ntp; - const value = values.colors[color]; - await expect(page.getByTestId('BackgroundConsumer')).toHaveAttribute('data-background-color', value.hex); + await expect(page.locator('body')).toHaveCSS('background-color', expectedRGB); } async selectsColor() { diff --git a/special-pages/pages/new-tab/app/customizer/integration-tests/customizer.spec.js b/special-pages/pages/new-tab/app/customizer/integration-tests/customizer.spec.js index bc55a1c22..df14f2891 100644 --- a/special-pages/pages/new-tab/app/customizer/integration-tests/customizer.spec.js +++ b/special-pages/pages/new-tab/app/customizer/integration-tests/customizer.spec.js @@ -80,7 +80,7 @@ test.describe('newtab customizer', () => { kind: 'color', value: 'color01', }); - await cp.hasColorBackground('color01'); + await cp.hasColorBackground('rgb(0, 0, 0)'); }); test('loads with the default background and accepts theme update', async ({ page }, workerInfo) => { const ntp = NewtabPage.create(page, workerInfo); diff --git a/special-pages/pages/new-tab/app/favorites/components/Tile.module.css b/special-pages/pages/new-tab/app/favorites/components/Tile.module.css index b830d7e92..42a8bd955 100644 --- a/special-pages/pages/new-tab/app/favorites/components/Tile.module.css +++ b/special-pages/pages/new-tab/app/favorites/components/Tile.module.css @@ -1,4 +1,6 @@ .item { + --icon-width: 4rem; + display: block; position: relative; text-decoration: none; @@ -29,8 +31,8 @@ display: grid; align-content: center; justify-items: center; - width: 4rem; - height: 4rem; + width: var(--icon-width); + height: var(--icon-width); margin-bottom: 4px; border-radius: var(--border-radius-lg); } @@ -89,6 +91,7 @@ } .text { + width: var(--icon-width); text-align: center; font-size: calc(10 * var(--px-in-rem)); line-height: 1.1;