-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: scroll based animation in VerticalStack
- Loading branch information
1 parent
42bc163
commit 485e423
Showing
4 changed files
with
117 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import type { BaseBlock } from '@/components/Home/types' | ||
import { useEffect, useState, type ReactElement, type RefObject } from 'react' | ||
import css from './styles.module.css' | ||
import { Grid, Typography } from '@mui/material' | ||
import useScrollProgress from '@/hooks/useScrollProgress' | ||
import { selectIndex } from '@/components/Wallet/VerticalSlide/Table' | ||
|
||
export const GridItem = ({ | ||
image, | ||
title, | ||
text, | ||
isSelected, | ||
}: Partial<BaseBlock> & { isSelected: boolean }): ReactElement => ( | ||
<Grid item xs={12} className={`${css.card} ${isSelected ? css.selected : ''}`}> | ||
{image ? <img {...image} /> : null} | ||
|
||
<Typography variant="h5">{title}</Typography> | ||
|
||
{text && ( | ||
<Typography color="primary.light" component="div"> | ||
{text} | ||
</Typography> | ||
)} | ||
</Grid> | ||
) | ||
|
||
const Table = ({ items = [], sectionRef }: { items: BaseBlock['items']; sectionRef: RefObject<HTMLDivElement> }) => { | ||
const [selectedIndex, setSelectedIndex] = useState(0) | ||
const { scrollYProgress } = useScrollProgress(sectionRef) | ||
|
||
useEffect(() => { | ||
const handleScroll = () => { | ||
const newIndex = selectIndex(scrollYProgress.get()) | ||
setSelectedIndex(newIndex) | ||
} | ||
|
||
const unsubscribe = scrollYProgress.on('change', handleScroll) | ||
|
||
return () => { | ||
unsubscribe() | ||
} | ||
}, [scrollYProgress, items.length]) | ||
|
||
return ( | ||
<div className={css.cardWrapper}> | ||
{items.map((item, index) => ( | ||
<GridItem key={index} isSelected={index === selectedIndex} {...item} /> | ||
))} | ||
</div> | ||
) | ||
} | ||
|
||
export default Table |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,42 @@ | ||
import type { DetailedHTMLProps, ReactElement, SourceHTMLAttributes } from 'react' | ||
import dynamic from 'next/dynamic' | ||
import { useRef, type DetailedHTMLProps, type SourceHTMLAttributes } from 'react' | ||
import { Container, Grid, Typography } from '@mui/material' | ||
import type { BaseBlock } from '@/components/Home/types' | ||
import layoutCss from '@/components/common/styles.module.css' | ||
import css from './styles.module.css' | ||
|
||
const Table = dynamic(() => import('./Table')) | ||
|
||
type VideoEmbed = { | ||
sources: Array<DetailedHTMLProps<SourceHTMLAttributes<HTMLSourceElement>, HTMLSourceElement>> | ||
} | ||
|
||
export const GridItem = ({ image, title, text }: Partial<BaseBlock>): ReactElement => ( | ||
<Grid item xs={12} className={css.card}> | ||
{image ? <img {...image} /> : null} | ||
|
||
<Typography variant="h5">{title}</Typography> | ||
|
||
{text && ( | ||
<Typography color="primary.light" component="div"> | ||
{text} | ||
</Typography> | ||
)} | ||
</Grid> | ||
) | ||
|
||
const VerticalStack = ({ title, video, items = [] }: BaseBlock & { video: VideoEmbed }) => ( | ||
<Container className={layoutCss.containerShort}> | ||
<Grid container spacing="40px" justifyContent="space-between"> | ||
<Grid item md={6} className={css.titleWrapper}> | ||
{video && ( | ||
<video autoPlay muted playsInline loop className={css.video}> | ||
{video.sources.map((s, i) => ( | ||
<source key={i} {...s} /> | ||
))} | ||
</video> | ||
)} | ||
|
||
<Typography variant="h2">{title}</Typography> | ||
</Grid> | ||
|
||
<Grid item xs={12} md={5}> | ||
<div className={css.cardWrapper}> | ||
{items.map((item, index) => ( | ||
<GridItem key={index} {...item} /> | ||
))} | ||
</div> | ||
</Grid> | ||
</Grid> | ||
</Container> | ||
) | ||
const VerticalStack = ({ title, video, items = [] }: BaseBlock & { video: VideoEmbed }) => { | ||
const sectionRef = useRef<HTMLDivElement>(null) | ||
|
||
return ( | ||
<Container className={`${layoutCss.containerShort} ${css.sectionContainer}`} ref={sectionRef}> | ||
<div className={css.stickyContainer}> | ||
<Grid container spacing="40px" justifyContent="space-between"> | ||
<Grid item md={6} className={css.titleWrapper}> | ||
{video && ( | ||
<video autoPlay muted playsInline loop className={css.video}> | ||
{video.sources.map((s, i) => ( | ||
<source key={i} {...s} /> | ||
))} | ||
</video> | ||
)} | ||
|
||
<Typography variant="h2">{title}</Typography> | ||
</Grid> | ||
|
||
<Grid item xs={12} md={6}> | ||
<Table items={items} sectionRef={sectionRef} /> | ||
</Grid> | ||
</Grid> | ||
</div> | ||
</Container> | ||
) | ||
} | ||
|
||
export default VerticalStack |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters