PageGrid chunks; Image lazy removed (unstable in Safari)

This commit is contained in:
tmshv committed 2020-03-03 21:12:29 +03:00
1 parent 23b4b35395
commit b0b3f98233
3 files changed
+72 -94

No files matched your search

+3 -41
View File
@@ -1,5 +1,5 @@
import './styles.css' import './styles.css'
import { memo, useRef, useState, useEffect, useCallback } from 'react' import { memo, useRef, useEffect, useCallback } from 'react'
export type ImageProps = { export type ImageProps = {
style?: React.CSSProperties style?: React.CSSProperties
@@ -9,7 +9,6 @@ export type ImageProps = {
} }
export const Image: React.FC<ImageProps> = memo(props => { export const Image: React.FC<ImageProps> = memo(props => {
const [imageSrc, setImageSrc] = useState<[string, string]>([null, null])
const ref = useRef<HTMLImageElement>() const ref = useRef<HTMLImageElement>()
const onLoad = useCallback((event) => { const onLoad = useCallback((event) => {
event.target.classList.add('loaded') event.target.classList.add('loaded')
@@ -22,43 +21,6 @@ export const Image: React.FC<ImageProps> = memo(props => {
} }
}) })
useEffect(() => {
let observer: IntersectionObserver
let didCancel = false
if (ref.current && imageSrc[0] !== props.src) {
if (IntersectionObserver) {
observer = new IntersectionObserver(
entries => {
entries.forEach(entry => {
if (
!didCancel &&
(entry.intersectionRatio > 0 || entry.isIntersecting)
) {
setImageSrc([props.src, props.srcSet])
observer.unobserve(ref.current)
}
})
},
{
threshold: 0.01,
rootMargin: "75%",
}
)
observer.observe(ref.current)
} else {
// Old browsers fallback
setImageSrc([props.src, props.srcSet])
}
}
return () => {
didCancel = true
if (observer && observer.unobserve) {
observer.unobserve(ref.current)
}
}
}, [props.src, props.srcSet, imageSrc, ref])
return ( return (
<img <img
ref={ref} ref={ref}
@@ -66,8 +28,8 @@ export const Image: React.FC<ImageProps> = memo(props => {
className={'image'} className={'image'}
style={props.style} style={props.style}
alt={props.alt} alt={props.alt}
src={imageSrc[0]} src={props.src}
srcSet={imageSrc[1]} srcSet={props.srcSet}
/> />
) )
}) })
-10
View File
@@ -1,12 +1,3 @@
@keyframes loaded {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.image { .image {
width: 100%; width: 100%;
display: block; display: block;
@@ -17,6 +8,5 @@
} }
.image.loaded { .image.loaded {
animation: loaded 250ms ease-in-out;
opacity: 1; opacity: 1;
} }
+69 -43
View File
@@ -4,58 +4,84 @@ import { Card, CardLayout } from '../Card'
import { Date } from './Date' import { Date } from './Date'
import { Block } from '../Block' import { Block } from '../Block'
import { Spacer } from '../Spacer' import { Spacer } from '../Spacer'
import { imageSrcSet } from 'src/lib/image' import { imageSrcSet, imageSrc } from 'src/lib/image'
import { Button } from '../Button'
import { useState, useCallback } from 'react'
export type PageGridProps = { export type PageGridProps = {
items: PageCardData[] items: PageCardData[]
} }
export const PageGrid: React.FC<PageGridProps> = props => { export const PageGrid: React.FC<PageGridProps> = props => {
const [page, setPage] = useState(1)
const i = page * 24
const items = props.items.slice(0, i)
const onMore = useCallback(() => {
setPage(x => x + 1)
}, [])
const hasMore = i < props.items.length
return ( return (
<CardGrid <>
style={{ <CardGrid
marginBottom: 'var(--size-m)', style={{
}} marginBottom: 'var(--size-m)',
> }}
{props.items.map((item, i) => { >
const gridColumn = item.featured ? 'span 2' : 'auto' {items.map((item, i) => {
const layout: CardLayout = item.featured ? 'featured' : 'simple' const gridColumn = item.featured ? 'span 2' : 'auto'
const src = item.coverSrc ?? process.env.APP_CARD_DEFAULT_IMAGE const layout: CardLayout = item.featured ? 'featured' : 'simple'
const srcSet = imageSrcSet(src, [ImageSize.large, ImageSize.medium, ImageSize.small]) const cover = item.coverSrc ?? process.env.APP_CARD_DEFAULT_IMAGE
const src = cover
const srcSet = imageSrcSet(src, [ImageSize.large, ImageSize.medium, ImageSize.small])
const content = !item.featured const content = !item.featured
? ( ? (
<Block <Block
direction={'vertical'} direction={'vertical'}
>
{item.title}
<Spacer />
<Date style={{
marginTop: 'var(--size-m)',
}}>{item.date}</Date>
</Block>
) : (
item.title
)
return (
<Card
key={i}
href={item.url}
img={{
alt: item.title,
src,
srcSet,
}}
layout={layout}
style={{
gridColumn,
}}
> >
{item.title} {content}
<Spacer /> </Card>
<Date style={{
marginTop: 'var(--size-m)',
}}>{item.date}</Date>
</Block>
) : (
item.title
) )
})}
return ( </CardGrid>
<Card <Block direction={'horizontal'} style={{
key={i} marginTop: 'var(--size-l)'
href={item.url} }}>
img={{ <Spacer />
alt: item.title, <Button
src, disabled={!hasMore}
srcSet, onClick={onMore}
}} style={{
layout={layout} flex: 2,
style={{ }}
gridColumn, >Загрузить ещё</Button>
}} <Spacer />
> </Block>
{content} </>
</Card>
)
})}
</CardGrid>
) )
} }