Skip to content

Commit

Permalink
ntp: customizer drawer
Browse files Browse the repository at this point in the history
  • Loading branch information
shakyShane committed Dec 16, 2024
1 parent ddd78b8 commit ab8ee9e
Show file tree
Hide file tree
Showing 45 changed files with 2,660 additions and 206 deletions.
71 changes: 50 additions & 21 deletions special-pages/pages/new-tab/app/components/App.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { h } from 'preact';
import { Fragment, h } from 'preact';
import cn from 'classnames';
import styles from './App.module.css';
import { useCustomizerDrawerSettings, usePlatformName } from '../settings.provider.js';
Expand All @@ -7,30 +7,52 @@ import { useGlobalDropzone } from '../dropzone.js';
import { Customizer, CustomizerButton, CustomizerMenuPositionedFixed, useContextMenu } from '../customizer/components/Customizer.js';
import { useDrawer, useDrawerControls } from './Drawer.js';
import { CustomizerDrawer } from '../customizer/components/CustomizerDrawer.js';
import { BackgroundConsumer } from './BackgroundProvider.js';
import { useComputed } from '@preact/signals';
import { CustomizerThemesContext } from '../customizer/CustomizerProvider.js';
import { useContext } from 'preact/hooks';

/**
* Renders the App component.
*
* @param {Object} props - The properties of the component.
* @param {import("preact").ComponentChild} [props.children] - The child components to be rendered within the App component.
*/
export function App({ children }) {
export function App() {
const platformName = usePlatformName();
const settings = useCustomizerDrawerSettings();
const customizerDrawer = useCustomizerDrawerSettings();

const customizerKind = settings.state === 'enabled' ? 'drawer' : 'menu';
const customizerKind = customizerDrawer.state === 'enabled' ? 'drawer' : 'menu';

useGlobalDropzone();
useContextMenu();

const { buttonRef, wrapperRef, visibility, displayChildren, hidden, buttonId, drawerId } = useDrawer();
const { toggle, close } = useDrawerControls();
// prettier-ignore
const {
buttonRef,
wrapperRef,
visibility,
displayChildren,
animating,
hidden,
buttonId,
drawerId
} = useDrawer();

const tabIndex = useComputed(() => (hidden.value ? -1 : 0));
const { toggle } = useDrawerControls();
const { main, browser } = useContext(CustomizerThemesContext);

return (
<div class={cn(styles.layout)} ref={wrapperRef} data-drawer-visibility={visibility}>
<main class={cn(styles.main)} data-customizer-kind={customizerKind}>
<div class={styles.tube} data-platform={platformName}>
<WidgetList />
<Fragment>
<BackgroundConsumer browser={browser} bg={main} />
<div class={styles.layout} ref={wrapperRef} data-animating={animating} data-drawer-visibility={visibility}>
<main class={cn(styles.main, styles.mainScroller)} data-main-scroller data-theme={main}>
<div class={styles.content}>
<div className={styles.tube} data-platform={platformName}>
<WidgetList />
</div>
</div>
<CustomizerMenuPositionedFixed>
{customizerKind === 'menu' && <Customizer />}
{customizerKind === 'drawer' && (
Expand All @@ -43,16 +65,23 @@ export function App({ children }) {
/>
)}
</CustomizerMenuPositionedFixed>
{children}
</div>
</main>
{customizerKind === 'drawer' && (
<aside id={drawerId} class={styles.aside} aria-hidden={hidden}>
<div class={styles.asideContent}>
<CustomizerDrawer onClose={close} wrapperRef={wrapperRef} displayChildren={displayChildren} />
</div>
</aside>
)}
</div>
</main>
{customizerKind === 'drawer' && (
<aside
class={cn(styles.aside, styles.asideScroller)}
tabindex={tabIndex}
aria-hidden={hidden}
data-theme={browser}
data-browser-panel
>
<div class={styles.asideContent}>
<div class={styles.asideContentInner}>
<CustomizerDrawer displayChildren={displayChildren} />
</div>
</div>
</aside>
)}
</div>
</Fragment>
);
}
76 changes: 60 additions & 16 deletions special-pages/pages/new-tab/app/components/App.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
@import url("../styles/ntp-theme.css");

body {
background: var(--ntp-background-color);
color: var(--ntp-text-normal);
font-size: var(--body-font-size);
font-weight: var(--body-font-weight);
line-height: var(--body-line-height);
overflow: hidden;
height: 100vh;
}

.tube {
Expand All @@ -34,40 +34,84 @@ body:has([data-reset-layout="true"]) .tube {

.layout {
display: grid;
grid-template-columns: auto 0;
transition: all ease .3s;
position: relative;
grid-template-columns: auto 0 0;
grid-template-areas: "main gap aside";
transition: all .3s ease-in-out;
z-index: 1;

&[data-drawer-visibility='visible'] {
grid-template-columns: auto var(--ntp-drawer-width);
grid-template-columns: auto 4px var(--ntp-combined-width);
}
}

.main {
&[data-customizer-kind="drawer"] {
overflow: hidden;
height: 100vh;
height: 100vh;
overflow: auto;
grid-area: main;
color: var(--ntp-text-normal);
}

.mainScroller {
&::-webkit-scrollbar {
width: 4px;
}

&::-webkit-scrollbar-track {
border-radius: 6px;
}

&::-webkit-scrollbar-thumb {
background: rgb(108, 108, 108);
border-radius: 6px;
}
}

.active {}
.content {
width: 100%;
}

.aside {
overflow: hidden;
height: 100vh;
color: var(--ntp-text-normal);
background: var(--ntp-surfaces-panel-background-color);
grid-area: aside;
height: 100vh;
z-index: 1;
overflow: auto;

/** todo: is this re-usable in any way, or unique? */
box-shadow: 0px 0px 1px 0px #FFF inset, 0px 0px 2px 0px rgba(0, 0, 0, 0.08), 0px 8px 12px 0px rgba(0, 0, 0, 0.12);
@media screen and (prefers-color-scheme: dark) {

&[data-theme=dark] {
box-shadow: 0px 0px 1px 0px rgba(0, 0, 0, 0.60) inset, 0px 0px 2px 0px rgba(0, 0, 0, 0.16), 0px 8px 12px 0px rgba(0, 0, 0, 0.24);
}

.layout[data-animating="true"] & {
overflow: hidden;
}
}

.asideContent {
box-sizing: border-box;
height: 100vh;
opacity: 1;
width: var(--ntp-drawer-width);
padding: var(--sp-2);
}

.asideContentInner {
padding: 1rem;
padding-right: calc(1rem - var(--ntp-drawer-scroll-width));
}

.asideScroller {
&::-webkit-scrollbar {
width: var(--ntp-drawer-scroll-width);
}

&::-webkit-scrollbar-track {
border-radius: 6px;
}

&::-webkit-scrollbar-thumb {
background: rgb(108, 108, 108);
border: 4px solid var(--ntp-surfaces-panel-background-color);
border-radius: 6px;
}
}
140 changes: 140 additions & 0 deletions special-pages/pages/new-tab/app/components/BackgroundProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { Fragment, h } from 'preact';
import styles from './BackgroundReceiver.module.css';
import { detectThemeFromHex, values } from '../customizer/values.js';
import { useContext } from 'preact/hooks';
import { CustomizerContext } from '../customizer/CustomizerProvider.js';

/**
* @import { BackgroundVariant, BrowserTheme } from "../../types/new-tab"
*/

/**
* @param {BackgroundVariant} background
* @param {BrowserTheme} browserTheme
* @param {'light' | 'dark'} system
* @return {{bg: 'light' | 'dark', browser: 'light' | 'dark'}}
*/
export function inferSchemeFrom(background, browserTheme, system) {
const browser = themeFromBrowser(browserTheme, system);
switch (background.kind) {
case 'default':
return { bg: browser, browser };
case 'color': {
const color = values.colors[background.value];
return { bg: color.colorScheme, browser };
}

case 'gradient': {
const gradient = values.gradients[background.value];
return { bg: gradient.colorScheme, browser };
}

case 'userImage':
return { bg: background.value.colorScheme, browser };

case 'hex':
return { bg: detectThemeFromHex(background.value), browser };
}
}

/**
* @param {BrowserTheme} browserTheme
* @param {'light' | 'dark'} system
* @return {'light' | 'dark'}
*/
export function themeFromBrowser(browserTheme, system) {
if (browserTheme === 'system') {
return system;
}
return browserTheme;
}

/**
* @param {object} props
* @param {import("@preact/signals").Signal<'light' | 'dark'>} props.bg
* @param {import("@preact/signals").Signal<'light' | 'dark'>} props.browser
*/
export function BackgroundConsumer({ bg, browser }) {
const { data } = useContext(CustomizerContext);
const background = data.value.background;

switch (background.kind) {
case 'default': {
return <div className={styles.root} data-testid="BackgroundConsumer" data-background-kind="default" data-theme={browser} />;
}
case 'hex': {
return (
<div
class={styles.root}
data-animate="true"
data-testid="BackgroundConsumer"
style={{
backgroundColor: background.value,
}}
></div>
);
}
case 'color': {
const color = values.colors[background.value];
return (
<div
class={styles.root}
data-animate="true"
data-background-color={color.hex}
data-testid="BackgroundConsumer"
style={{
backgroundColor: color.hex,
}}
></div>
);
}
case 'gradient': {
const gradient = values.gradients[background.value];
return (
<Fragment key="gradient">
<div
class={styles.root}
data-animate="false"
data-testid="BackgroundConsumer"
style={{
backgroundColor: gradient.fallback,
backgroundImage: `url(${gradient.path})`,
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
}}
/>
<div
class={styles.root}
data-animate="false"
style={{
backgroundImage: `url(gradients/grain.png)`,
backgroundRepeat: 'repeat',
opacity: 0.5,
mixBlendMode: 'soft-light',
}}
></div>
</Fragment>
);
}
case 'userImage': {
const img = background.value;
return (
<div
class={styles.root}
data-animate="true"
data-testid="BackgroundConsumer"
style={{
backgroundImage: `url(${img.src})`,
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center center',
}}
></div>
);
}
default: {
console.warn('Unreachable!');
return <div className={styles.root}></div>;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.root {
position: fixed;
z-index: 0;
inset: 0;
width: 100vw;
height: 100vh;
pointer-events: none;

&[data-animate="true"] {
transition: all .3s 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ body[data-display="components"] {
background: var(--color-gray-20);
}

@media screen and (prefers-color-scheme: dark) {
[data-theme=dark] & {
&:hover {
background: var(--color-gray-90);
}
Expand Down
4 changes: 2 additions & 2 deletions special-pages/pages/new-tab/app/components/DismissButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { Cross } from './Icons';
import { useTypedTranslation } from '../types';
import styles from './DismissButton.module.css';

/*
/**
* @param {object} props
* @param {string} [props.className]
* @param {() => void} props.onClick
* @param {() => void} [props.onClick]
*/
export function DismissButton({ className, onClick }) {
const { t } = useTypedTranslation();
Expand Down
Loading

0 comments on commit ab8ee9e

Please sign in to comment.