From e908398c21b6d00af5f182d9fa21495e583468e6 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 9 Dec 2024 11:28:23 +0100 Subject: [PATCH 1/5] Solve issue if LayoutDefault-children wouldn't fill the page, the content would be aligned to the footer. Presence of beforeheader would trigger this. Support beforeHeader in LayoutDefault without breaking the CartFab and CompareFab. --- .changeset/brown-monkeys-lie.md | 5 ++ .changeset/kind-drinks-relax.md | 5 ++ .../components/LayoutDefault.tsx | 71 ++++++++++++------- 3 files changed, 54 insertions(+), 27 deletions(-) create mode 100644 .changeset/brown-monkeys-lie.md create mode 100644 .changeset/kind-drinks-relax.md diff --git a/.changeset/brown-monkeys-lie.md b/.changeset/brown-monkeys-lie.md new file mode 100644 index 0000000000..7955ef500e --- /dev/null +++ b/.changeset/brown-monkeys-lie.md @@ -0,0 +1,5 @@ +--- +'@graphcommerce/next-ui': patch +--- + +Support beforeHeader in LayoutDefault without breaking the CartFab and CompareFab. diff --git a/.changeset/kind-drinks-relax.md b/.changeset/kind-drinks-relax.md new file mode 100644 index 0000000000..346c268209 --- /dev/null +++ b/.changeset/kind-drinks-relax.md @@ -0,0 +1,5 @@ +--- +'@graphcommerce/next-ui': patch +--- + +Solve issue if LayoutDefault-children wouldn't fill the page, the content would be aligned to the footer. Presence of beforeheader would trigger this. diff --git a/packages/next-ui/LayoutDefault/components/LayoutDefault.tsx b/packages/next-ui/LayoutDefault/components/LayoutDefault.tsx index 30fc40b5d1..dbd565d29d 100644 --- a/packages/next-ui/LayoutDefault/components/LayoutDefault.tsx +++ b/packages/next-ui/LayoutDefault/components/LayoutDefault.tsx @@ -23,7 +23,7 @@ export type LayoutDefaultProps = { type OwnerState = { noSticky?: boolean } -const parts = ['root', 'fabs', 'header', 'children', 'footer'] as const +const parts = ['root', 'fabs', 'beforeHeader', 'header', 'children', 'footer'] as const const { withState } = extendableComponent( 'LayoutDefault', parts, @@ -61,8 +61,13 @@ export function LayoutDefault(props: LayoutDefaultProps) { minHeight: '-webkit-fill-available', }, display: 'grid', - gridTemplateRows: { xs: 'auto 1fr auto', md: 'auto auto 1fr auto' }, - gridTemplateColumns: '100%', + gridTemplate: ` + "beforeHeader" auto + "header" auto + "fabs" auto + "children" 1fr + "footer" auto / 100% + `, background: theme.palette.background.default, }), ...(Array.isArray(sx) ? sx : [sx]), @@ -70,13 +75,18 @@ export function LayoutDefault(props: LayoutDefaultProps) { > - {beforeHeader} + {beforeHeader ? ( + + {beforeHeader} + + ) : null} ({ + gridArea: 'header', zIndex: theme.zIndex.appBar - 1, display: 'flex', alignItems: 'center', @@ -108,27 +118,32 @@ export function LayoutDefault(props: LayoutDefaultProps) { sizing='shell' maxWidth={false} className={classes.fabs} - sx={(theme) => ({ - display: 'flex', - justifyContent: 'space-between', - width: '100%', - height: 0, - zIndex: 'speedDial', - [theme.breakpoints.up('sm')]: { - position: 'sticky', - marginTop: `calc(${theme.appShell.headerHeightMd} * -1 - calc(${fabIconSize} / 2))`, - top: `calc(${theme.appShell.headerHeightMd} / 2 - (${fabIconSize} / 2))`, - }, - [theme.breakpoints.down('md')]: { - position: 'fixed', - top: 'unset', - bottom: `calc(20px + ${fabIconSize})`, - padding: '0 20px', - '@media (max-height: 530px) and (orientation: portrait)': { - display: 'none', + sx={(theme) => { + const negativeHeaderHeightMd = `(${theme.appShell.headerHeightMd} * -1)` + const topMd = `(${theme.appShell.headerHeightMd} - ${fabIconSize}) / 2` + + return { + gridArea: 'fabs', + display: 'flex', + justifyContent: 'space-between', + width: '100%', + height: 0, + zIndex: 'speedDial', + [theme.breakpoints.up('md')]: { + position: 'sticky', + marginTop: `calc(${negativeHeaderHeightMd} + ${topMd})`, + top: `calc(${topMd})`, }, - }, - })} + [theme.breakpoints.down('md')]: { + position: 'fixed', + bottom: `calc(20px + ${fabIconSize})`, + padding: '0 20px', + '@media (max-height: 530px) and (orientation: portrait)': { + display: 'none', + }, + }, + } + }} > {menuFab} {cartFab && ( @@ -150,11 +165,13 @@ export function LayoutDefault(props: LayoutDefaultProps) { ) : (
)} -
+
{children} -
-
{footer}
+
+ + {footer} + ) From c7cc9d98adf38a4ec60d6dc7dae34d577e409505 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 9 Dec 2024 14:40:40 +0100 Subject: [PATCH 2/5] Revert theme colors back to original style --- examples/magento-graphcms/components/theme.ts | 4 ++-- packages/next-ui/Theme/createTheme.ts | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/magento-graphcms/components/theme.ts b/examples/magento-graphcms/components/theme.ts index 08a53157a1..a17c6d6e75 100644 --- a/examples/magento-graphcms/components/theme.ts +++ b/examples/magento-graphcms/components/theme.ts @@ -19,9 +19,9 @@ import { Components, PaletteOptions } from '@mui/material/styles' const lightPalette: PaletteOptions = { mode: 'light', primary: { - main: '#000000', + main: '#47C489', contrastText: '#ffffff', - dark: '#000000', + dark: '#47C489', }, secondary: { main: '#006bff', diff --git a/packages/next-ui/Theme/createTheme.ts b/packages/next-ui/Theme/createTheme.ts index 2fe431a2d8..d4f2965718 100644 --- a/packages/next-ui/Theme/createTheme.ts +++ b/packages/next-ui/Theme/createTheme.ts @@ -1,4 +1,4 @@ -import { Breakpoint } from '@mui/material' +import type { Breakpoint } from '@mui/material' export {} @@ -28,7 +28,15 @@ declare module '@mui/material/styles/createTheme' { headerHeightMd: string appBarHeightMd: string appBarInnerHeightMd: string + /** + * Sizing of the shell of the application. Provide a breakpoint to use the breakpoint value or + * false to disable the breakpoint. + */ containerSizingShell: false | Breakpoint | undefined + /** + * Sizing of the content of the application. Provide a breakpoint to use the breakpoint value + * or false to disable the breakpoint. + */ containerSizingContent: false | Breakpoint | undefined } From 6380ea50c5da16a115817439accbe96f56ac5012 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 9 Dec 2024 14:50:21 +0100 Subject: [PATCH 3/5] Working on sticky header --- .../components/Layout/LayoutNavigation.tsx | 37 +++++++- .../ProductListLayoutDefault.tsx | 13 +-- .../ProductListLayoutSidebar.tsx | 3 +- examples/magento-graphcms/pages/[...url].tsx | 1 - .../components/LayoutDefault.tsx | 91 ++++++++++++++----- 5 files changed, 114 insertions(+), 31 deletions(-) diff --git a/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx b/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx index b5466e3c33..9f1b8802fe 100644 --- a/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx +++ b/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx @@ -21,10 +21,11 @@ import { NavigationOverlay, useNavigationSelection, useMemoDeep, + Container, } from '@graphcommerce/next-ui' import { i18n } from '@lingui/core' import { Trans } from '@lingui/react' -import { Divider, Fab } from '@mui/material' +import { Divider, Fab, Link } from '@mui/material' import { useRouter } from 'next/router' import { Footer } from './Footer' import { LayoutQuery } from './Layout.gql' @@ -117,7 +118,39 @@ export function LayoutNavigation(props: LayoutNavigationProps) { ({ + [theme.breakpoints.up('md')]: { + '& .LayoutDefault-header.stickyHeader': { + bgcolor: 'background.default', + boxShadow: 1, + + // bgcolor: 'hsl(0deg 0% 100% / 0.95)', + // '&::before': { + // height: '200%', + // content: '""', + // display: 'block', + // position: 'absolute', + // inset: 0, + // WebkitBackdropFilter: 'blur(16px)', + // backdropFilter: 'blur(16px)', + // background: 'linear-gradient(to bottom, hsl(0deg 0% 95%), transparent 50%)', + // pointerEvents: 'none', + // WebkitMaskImage: 'linear-gradient(to bottom, black 0% 50%, transparent 50% 100%)', + // maskImage: 'linear-gradient(to bottom, black 0% 50%, transparent 50% 100%)', + // }, + }, + }, + })} + beforeHeader={ + + You are looking at the{' '} + + GraphCommerce + {' '} + demo environment + + } header={ <> diff --git a/examples/magento-graphcms/components/ProductListLayout/ProductListLayoutDefault.tsx b/examples/magento-graphcms/components/ProductListLayout/ProductListLayoutDefault.tsx index 76d5996ead..22b4470e7d 100644 --- a/examples/magento-graphcms/components/ProductListLayout/ProductListLayoutDefault.tsx +++ b/examples/magento-graphcms/components/ProductListLayout/ProductListLayoutDefault.tsx @@ -45,16 +45,17 @@ export const ProductListLayoutDefault = memoDeep((props: ProductListLayoutProps) sx={(theme) => ({ display: 'grid', rowGap: theme.spacings.sm, + pt: theme.spacings.sm, mb: theme.spacings.sm, gridAutoFlow: 'row', - justifyItems: { xs: 'left', md: 'center' }, + justifyItems: { xs: 'center', md: 'center' }, })} > {import.meta.graphCommerce.breadcrumbs && category && ( ({ - height: 0, + // height: 0, [theme.breakpoints.down('md')]: { '& .MuiBreadcrumbs-ol': { justifyContent: 'center' }, }, @@ -65,9 +66,9 @@ export const ProductListLayoutDefault = memoDeep((props: ProductListLayoutProps) {category ? ( <> {title} @@ -75,13 +76,13 @@ export const ProductListLayoutDefault = memoDeep((props: ProductListLayoutProps) ({ px: theme.page.horizontal })} + // sx={(theme) => ({ px: theme.page.horizontal })} description={category?.description} /> ({ justifyContent: 'center', - '& .CategoryChildren-scroller': { px: theme.page.horizontal }, + // '& .CategoryChildren-scroller': { px: theme.page.horizontal }, })} params={params} > diff --git a/examples/magento-graphcms/components/ProductListLayout/ProductListLayoutSidebar.tsx b/examples/magento-graphcms/components/ProductListLayout/ProductListLayoutSidebar.tsx index 7084773c20..3286bd9fe8 100644 --- a/examples/magento-graphcms/components/ProductListLayout/ProductListLayoutSidebar.tsx +++ b/examples/magento-graphcms/components/ProductListLayout/ProductListLayoutSidebar.tsx @@ -85,6 +85,7 @@ export const ProductListLayoutSidebar = memoDeep((props: ProductListLayoutProps) display: 'grid', gridAutoFlow: 'row', rowGap: theme.spacings.xs, + pt: theme.spacings.md, })} > {category ? ( @@ -168,7 +169,7 @@ export const ProductListLayoutSidebar = memoDeep((props: ProductListLayoutProps) display='block' sx={(theme) => ({ gridArea: 'sidebar', - mt: import.meta.graphCommerce.breadcrumbs === true ? 0 : theme.spacings.lg, + mt: import.meta.graphCommerce.breadcrumbs === true ? 0 : theme.spacings.xl, })} > diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index 22dc1247f9..3534f0b7bb 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -69,7 +69,6 @@ function CategoryPage(props: CategoryProps) { const page = pages?.[0] const isCategory = params && category && products?.items - console.log(page?.asset) return ( } & OwnerState type OwnerState = { - noSticky?: boolean + stickyHeader?: boolean } -const parts = ['root', 'fabs', 'beforeHeader', 'header', 'children', 'footer'] as const + +const parts = [ + 'root', + 'fabs', + 'beforeHeader', + 'header', + 'children', + 'footer', + 'cartFab', + 'menuFab', +] as const const { withState } = extendableComponent( 'LayoutDefault', parts, @@ -37,7 +46,7 @@ export function LayoutDefault(props: LayoutDefaultProps) { footer, menuFab, cartFab, - noSticky, + stickyHeader = false, className, sx = [], } = props @@ -48,7 +57,7 @@ export function LayoutDefault(props: LayoutDefaultProps) { ([y, offset]: number[]) => y + offset, ) - const classes = withState({ noSticky }) + const classes = withState({ stickyHeader }) const fabIconSize = useFabSize('responsive') return ( @@ -69,6 +78,17 @@ export function LayoutDefault(props: LayoutDefaultProps) { "footer" auto / 100% `, background: theme.palette.background.default, + + // '&.stickyHeader .LayoutHeaderContent-content': { + // [theme.breakpoints.up('md')]: { + // pt: theme.spacings.sm, + // }, + // }, + // '&.stickyHeader .CompareFab-root': { + // [theme.breakpoints.up('md')]: { + // mt: theme.spacings.sm, + // }, + // }, }), ...(Array.isArray(sx) ? sx : [sx]), ]} @@ -92,9 +112,10 @@ export function LayoutDefault(props: LayoutDefaultProps) { alignItems: 'center', justifyContent: 'center', height: theme.appShell.headerHeightSm, - pointerEvents: 'none', + pointerEvents: 'none' as const, '& > *': { - pointerEvents: 'all', + pointerEvents: 'all' as const, + zIndex: theme.zIndex.appBar, }, [theme.breakpoints.up('md')]: { height: theme.appShell.headerHeightMd, @@ -103,8 +124,8 @@ export function LayoutDefault(props: LayoutDefaultProps) { justifyContent: 'left', width: '100%', }, - '&.sticky': { - [theme.breakpoints.down('md')]: { + '&.stickyHeader': { + [theme.breakpoints.up('md')]: { position: 'sticky', top: 0, }, @@ -128,7 +149,7 @@ export function LayoutDefault(props: LayoutDefaultProps) { justifyContent: 'space-between', width: '100%', height: 0, - zIndex: 'speedDial', + zIndex: theme.zIndex.appBar, [theme.breakpoints.up('md')]: { position: 'sticky', marginTop: `calc(${negativeHeaderHeightMd} + ${topMd})`, @@ -145,18 +166,36 @@ export function LayoutDefault(props: LayoutDefaultProps) { } }} > - {menuFab} + *': { display: { md: 'none' } } }} + > + {menuFab} + {cartFab && ( ({ - display: 'flex', - flexDirection: 'row-reverse', - gap: theme.spacings.sm, - [theme.breakpoints.up('md')]: { - flexDirection: 'column', - alignItems: 'flex-end', - }, - })} + className={classes.cartFab} + sx={(theme) => { + const topMd = `(${theme.appShell.headerHeightMd} - ${fabIconSize}) / 2` + return { + display: 'flex', + flexDirection: 'row-reverse', + + [theme.breakpoints.down('md')]: { + columnGap: theme.spacings.sm, + }, + + [theme.breakpoints.up('md')]: { + rowGap: `calc(${topMd})`, + '&.stickyHeader': { + rowGap: `calc(${topMd} + ${theme.spacings.sm})`, + }, + + flexDirection: 'column', + alignItems: 'flex-end', + }, + } + }} > {cartFab} @@ -165,7 +204,17 @@ export function LayoutDefault(props: LayoutDefaultProps) { ) : (
)} - + ({ + gridArea: 'children', + '&.stickyHeader': { + [theme.breakpoints.up('md')]: { + pt: theme.spacings.sm, + }, + }, + })} + className={classes.children} + >
{children} From 7fc22c69e190eb6987078a4afc6d319689c775e2 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 9 Dec 2024 14:58:54 +0100 Subject: [PATCH 4/5] Clear background blur stuff --- .../components/Layout/LayoutNavigation.tsx | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx b/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx index 9f1b8802fe..c428e9468f 100644 --- a/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx +++ b/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx @@ -124,21 +124,6 @@ export function LayoutNavigation(props: LayoutNavigationProps) { '& .LayoutDefault-header.stickyHeader': { bgcolor: 'background.default', boxShadow: 1, - - // bgcolor: 'hsl(0deg 0% 100% / 0.95)', - // '&::before': { - // height: '200%', - // content: '""', - // display: 'block', - // position: 'absolute', - // inset: 0, - // WebkitBackdropFilter: 'blur(16px)', - // backdropFilter: 'blur(16px)', - // background: 'linear-gradient(to bottom, hsl(0deg 0% 95%), transparent 50%)', - // pointerEvents: 'none', - // WebkitMaskImage: 'linear-gradient(to bottom, black 0% 50%, transparent 50% 100%)', - // maskImage: 'linear-gradient(to bottom, black 0% 50%, transparent 50% 100%)', - // }, }, }, })} From ec11e25ab9bae8e08028fe472c448a227277d5df Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Wed, 11 Dec 2024 12:51:13 +0100 Subject: [PATCH 5/5] Further work on sticky header functionality --- .changeset/polite-plums-breathe.md | 5 - .changeset/pre.json | 1 - .../components/Layout/LayoutNavigation.tsx | 35 ++- .../components/Layout/LayoutNavigation.tsx | 7 +- .../framer-utils/components/StickyBox.tsx | 35 +++ .../framer-utils/hooks/useMakeFullscreen.ts | 37 +++ packages/framer-utils/hooks/useMotionRect.ts | 73 ++++++ packages/framer-utils/hooks/useStickyTop.ts | 103 ++++++++ packages/framer-utils/index.ts | 6 +- packages/framer-utils/package.json | 2 + packages/framer-utils/utils/numberToPx.ts | 3 + .../components/CartFab/CartFab.tsx | 4 +- .../CategoryChildren/CategoryChildren.tsx | 3 +- .../plugins/AddCompareFabNextToCart.tsx | 2 +- .../next-ui/FramerScroller/SidebarGallery.tsx | 21 +- .../components/LayoutDefault.tsx | 221 +++++++++--------- 16 files changed, 424 insertions(+), 134 deletions(-) delete mode 100644 .changeset/polite-plums-breathe.md create mode 100644 packages/framer-utils/components/StickyBox.tsx create mode 100644 packages/framer-utils/hooks/useMakeFullscreen.ts create mode 100644 packages/framer-utils/hooks/useMotionRect.ts create mode 100644 packages/framer-utils/hooks/useStickyTop.ts create mode 100644 packages/framer-utils/utils/numberToPx.ts diff --git a/.changeset/polite-plums-breathe.md b/.changeset/polite-plums-breathe.md deleted file mode 100644 index cbe2b93722..0000000000 --- a/.changeset/polite-plums-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@graphcommerce/magento-graphcms': patch ---- - -Add maxWidth to ProductListLayouts diff --git a/.changeset/pre.json b/.changeset/pre.json index 422f58d537..be5de7a2d0 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -229,7 +229,6 @@ "pink-students-greet", "polite-crabs-cry", "polite-kiwis-wash", - "polite-plums-breathe", "poor-masks-learn", "poor-plants-look", "poor-swans-sip", diff --git a/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx b/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx index c428e9468f..b002b4f3fa 100644 --- a/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx +++ b/examples/magento-graphcms/components/Layout/LayoutNavigation.tsx @@ -30,6 +30,7 @@ import { useRouter } from 'next/router' import { Footer } from './Footer' import { LayoutQuery } from './Layout.gql' import { Logo } from './Logo' +import { StickyBox } from '@graphcommerce/framer-utils' export type LayoutNavigationProps = LayoutQuery & Omit @@ -118,22 +119,43 @@ export function LayoutNavigation(props: LayoutNavigationProps) { ({ [theme.breakpoints.up('md')]: { - '& .LayoutDefault-header.stickyHeader': { + '& .sticky': { bgcolor: 'background.default', boxShadow: 1, }, }, })} + // stickyHeader={router.asPath.split('?')[0] !== '/'} + stickyAfterHeader + // stickyBeforeHeader beforeHeader={ - + You are looking at the{' '} GraphCommerce {' '} - demo environment + demo + + } + afterHeader={ + + This is a demo store, no actual products are being shipped. } header={ @@ -176,13 +198,12 @@ export function LayoutNavigation(props: LayoutNavigationProps) { } /> - {/* The placeholder exists because the CartFab is sticky but we want to reserve the space for the */} - {cartEnabled && } + } - footer={