Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create new App Shell component that supports more area's for specific design #2447

Open
wants to merge 5 commits into
base: canary
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/brown-monkeys-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphcommerce/next-ui': patch
---

Support beforeHeader in LayoutDefault without breaking the CartFab and CompareFab.
5 changes: 5 additions & 0 deletions .changeset/kind-drinks-relax.md
Original file line number Diff line number Diff line change
@@ -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.
5 changes: 0 additions & 5 deletions .changeset/polite-plums-breathe.md

This file was deleted.

1 change: 0 additions & 1 deletion .changeset/pre.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
49 changes: 44 additions & 5 deletions examples/magento-graphcms/components/Layout/LayoutNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ 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'
import { Logo } from './Logo'
import { StickyBox } from '@graphcommerce/framer-utils'

export type LayoutNavigationProps = LayoutQuery &
Omit<LayoutDefaultProps, 'footer' | 'header' | 'cartFab' | 'menuFab'>
Expand Down Expand Up @@ -117,7 +119,45 @@ export function LayoutNavigation(props: LayoutNavigationProps) {

<LayoutDefault
{...uiProps}
noSticky={router.asPath.split('?')[0] === '/'}
sx={(theme) => ({
[theme.breakpoints.up('md')]: {
'& .sticky': {
bgcolor: 'background.default',
boxShadow: 1,
},
},
})}
// stickyHeader={router.asPath.split('?')[0] !== '/'}
stickyAfterHeader
// stickyBeforeHeader
beforeHeader={
<Container
sx={{
py: { xs: 0, md: 1 },
position: 'relative',
boxShadow: 1,
textAlign: { xs: 'center', md: 'left' },
}}
>
You are looking at the{' '}
<Link color='inherit' underline='always' href='https://graphcommerce.org'>
GraphCommerce
</Link>{' '}
demo
</Container>
}
afterHeader={
<Container
sx={{
py: { xs: 0, md: 1 },
position: 'relative',
boxShadow: 1,
textAlign: { xs: 'center', md: 'left' },
}}
>
This is a demo store, no actual products are being shipped.
</Container>
}
header={
<>
<Logo />
Expand Down Expand Up @@ -158,13 +198,12 @@ export function LayoutNavigation(props: LayoutNavigationProps) {
</Fab>
<WishlistFab icon={<IconSvg src={iconHeart} size='large' />} />
<CustomerFab guestHref='/account/signin' authHref='/account' />
{/* The placeholder exists because the CartFab is sticky but we want to reserve the space for the <CartFab /> */}
{cartEnabled && <PlaceholderFab />}
<PlaceholderFab />
</DesktopNavActions>
</>
}
footer={<Footer footer={footer} />}
cartFab={<CartFab />}
footer={<Footer footer={footer} />}
menuFab={<NavigationFab onClick={() => selection.set([])} />}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 && (
<CategoryBreadcrumbs
category={category}
sx={(theme) => ({
height: 0,
// height: 0,
[theme.breakpoints.down('md')]: {
'& .MuiBreadcrumbs-ol': { justifyContent: 'center' },
},
Expand All @@ -65,23 +66,23 @@ export const ProductListLayoutDefault = memoDeep((props: ProductListLayoutProps)
{category ? (
<>
<LayoutTitle
gutterTop
gutterTop={false}
variant='h1'
sx={{ alignItems: { xs: 'left', md: 'center' } }}
// sx={{ alignItems: { xs: 'center', md: 'center' } }}
gutterBottom={false}
>
{title}
</LayoutTitle>
<CategoryDescription
textAlignMd='center'
textAlignSm='center'
sx={(theme) => ({ px: theme.page.horizontal })}
// sx={(theme) => ({ px: theme.page.horizontal })}
description={category?.description}
/>
<CategoryChildren
sx={(theme) => ({
justifyContent: 'center',
'& .CategoryChildren-scroller': { px: theme.page.horizontal },
// '& .CategoryChildren-scroller': { px: theme.page.horizontal },
})}
params={params}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const ProductListLayoutSidebar = memoDeep((props: ProductListLayoutProps)
display: 'grid',
gridAutoFlow: 'row',
rowGap: theme.spacings.xs,
pt: theme.spacings.md,
})}
>
{category ? (
Expand Down Expand Up @@ -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,
})}
>
<ProductFiltersProClearAll sx={{ alignSelf: 'center' }} />
Expand Down
4 changes: 2 additions & 2 deletions examples/magento-graphcms/components/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
1 change: 0 additions & 1 deletion examples/magento-graphcms/pages/[...url].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ function CategoryPage(props: CategoryProps) {
const page = pages?.[0]
const isCategory = params && category && products?.items

console.log(page?.asset)
return (
<InContextMaskProvider mask={productList.mask}>
<CategoryMeta
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ import {
DesktopNavActions,
DesktopNavBar,
DesktopNavItem,
iconChevronDown,
iconCustomerService,
iconHeart,
IconSvg,
LayoutDefault,
MenuFabSecondaryItem,
NavigationFab,
NavigationOverlay,
NavigationProvider,
PlaceholderFab,
iconChevronDown,
iconCustomerService,
iconHeart,
useMemoDeep,
useNavigationSelection,
} from '@graphcommerce/next-ui'
Expand Down Expand Up @@ -117,7 +117,6 @@ export function LayoutNavigation(props: LayoutNavigationProps) {

<LayoutDefault
{...uiProps}
noSticky={router.asPath.split('?')[0] === '/'}
header={
<>
<Logo />
Expand Down
35 changes: 35 additions & 0 deletions packages/framer-utils/components/StickyBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Box, useForkRef } from '@mui/material'
import type { BoxProps } from '@mui/material/Box'
import clsx from 'clsx'
import { px } from 'framer-motion'
import React, { useRef } from 'react'
import type { StickyStackConfig } from '../hooks/useStickyTop'
import { useStickyTop } from '../hooks/useStickyTop'
import { numberToPx } from '../utils/numberToPx'

export const StickyBox = React.forwardRef<
HTMLDivElement,
BoxProps & {
stickyConfig: Omit<StickyStackConfig<HTMLDivElement>, 'ref'>
}
>((props, forwardedRef) => {
const { sx, children, className, stickyConfig, ...rest } = props
const ref = useRef<HTMLDivElement>(null)
const forkedRef = useForkRef(forwardedRef, ref)
const top = useStickyTop({ ref, ...stickyConfig })

return (
<Box
ref={forkedRef}
style={{ '--top': px.transform(top) }}
sx={[
{ '&.sticky': { position: 'sticky', top: 'var(--top, 0px)' } },
...(Array.isArray(sx) ? sx : [sx]),
]}
className={clsx(className, stickyConfig.sticky && 'sticky')}
{...rest}
>
{children}
</Box>
)
})
37 changes: 37 additions & 0 deletions packages/framer-utils/hooks/useMakeFullscreen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { px } from 'framer-motion'
import { numberToPx } from '../utils/numberToPx'
import type { UseMotionRectOptions } from './useMotionRect'
import { useMotionRect } from './useMotionRect'
import { useMotionValueValue } from './useMotionValueValue'

type UseMakeFullScreenReturn = {
marginTop: string
marginBottom: string
marginLeft: string
marginRight: string
margin: `${string} ${string} ${string} ${string}`
}

/** Calculate negative margin values to make an element fullscreen. */
export function useMakeFullscreen<E extends HTMLElement>(
ref: React.RefObject<E>,
options?: UseMotionRectOptions,
): UseMakeFullScreenReturn {
const rect = useMotionRect(ref, options)

return useMotionValueValue(rect, (r) => {
const { top, left, marginBottom, marginRight } = r
const mt = numberToPx(top * -1)
const mb = numberToPx(marginBottom * -1)
const ml = numberToPx(left * -1)
const mr = numberToPx(marginRight * -1)

return {
marginTop: mt,
marginBottom: mb,
marginLeft: ml,
marginRight: mr,
margin: `${mt} ${mr} ${mb} ${ml}`,
}
})
}
73 changes: 73 additions & 0 deletions packages/framer-utils/hooks/useMotionRect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { useMotionValue } from 'framer-motion'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'

const emptyRect = {
top: 0,
bottom: 0,
left: 0,
right: 0,
height: 0,
width: 0,
marginTop: 0,
marginLeft: 0,
marginRight: 0,
marginBottom: 0,
}

export type Rect = typeof emptyRect

export type UseMotionRectOptions = {
pause?: boolean
windowResize?: boolean
resizeObserver?: boolean
}

export function useMotionRect<E extends HTMLElement>(
ref: React.RefObject<E>,
options?: UseMotionRectOptions,
) {
const { pause = false, windowResize = true, resizeObserver = false } = options ?? {}

const motionRect = useMotionValue<Rect>(emptyRect)

useIsomorphicLayoutEffect(() => {
if (!ref?.current || pause) return () => {}

const onResize = () => {
if (ref.current) {
const { bottom, right, top, left, height, width } = ref.current.getBoundingClientRect()
const { clientHeight, clientWidth } = document.documentElement
motionRect.set({
top,
bottom,
left,
right,
height,
width,
marginRight: clientWidth - right,
marginBottom: clientHeight - bottom,
marginTop: top,
marginLeft: left,
})
}
}
onResize()

let ro: ResizeObserver | undefined
if (resizeObserver) {
ro = new ResizeObserver(onResize)
ro.observe(ref.current)
}

if (windowResize) {
window.addEventListener('resize', onResize)
}

return () => {
ro?.disconnect()
window.removeEventListener('resize', onResize)
}
}, [motionRect, pause, ref, windowResize, resizeObserver])

return motionRect
}
Loading
Loading