アニメーション(#139) (#252)
#139 #139 #139 #139 #139 Merge branch 'feature/140' into feature/139 Merge remote-tracking branch 'origin/main' into feature/139 #140 Merge remote-tracking branch 'origin/main' into feature/140 Merge remote-tracking branch 'origin/main' into feature/140 #140 ぼちぼち Merge remote-tracking branch 'origin/main' into feature/140 #140 #140 #140 #139 アニメーション Co-authored-by: miteruzo <miteruzo@naver.com> Reviewed-on: #252
This commit was merged in pull request #252.
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
import { Link } from 'react-router-dom'
|
||||
import { motion } from 'framer-motion'
|
||||
import { useRef } from 'react'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
|
||||
import PrefetchLink from '@/components/PrefetchLink'
|
||||
import { useSharedTransitionStore } from '@/stores/sharedTransitionStore'
|
||||
|
||||
import type { FC, MouseEvent } from 'react'
|
||||
|
||||
@@ -8,18 +13,61 @@ type Props = { posts: Post[]
|
||||
onClick?: (event: MouseEvent<HTMLElement>) => void }
|
||||
|
||||
|
||||
export default (({ posts, onClick }: Props) => (
|
||||
<div className="flex flex-wrap gap-6 p-4">
|
||||
{posts.map ((post, i) => (
|
||||
<Link to={`/posts/${ post.id }`}
|
||||
key={post.id}
|
||||
className="w-40 h-40 overflow-hidden rounded-lg shadow-md hover:shadow-lg"
|
||||
onClick={onClick}>
|
||||
<img src={post.thumbnail || post.thumbnailBase || undefined}
|
||||
alt={post.title || post.url}
|
||||
title={post.title || post.url || undefined}
|
||||
loading={i < 12 ? 'eager' : 'lazy'}
|
||||
decoding="async"
|
||||
className="object-cover w-full h-full"/>
|
||||
</Link>))}
|
||||
</div>)) satisfies FC<Props>
|
||||
export default (({ posts, onClick }: Props) => {
|
||||
const location = useLocation ()
|
||||
|
||||
const setForLocationKey = useSharedTransitionStore (s => s.setForLocationKey)
|
||||
|
||||
const cardRef = useRef<HTMLDivElement> (null)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-wrap gap-6 p-4">
|
||||
{posts.map ((post, i) => {
|
||||
const id2 = `page-${ post.id }`
|
||||
const layoutId = id2
|
||||
|
||||
return (
|
||||
<PrefetchLink
|
||||
to={`/posts/${ post.id }`}
|
||||
key={post.id}
|
||||
className="w-40 h-40"
|
||||
state={{ sharedId: `page-${ post.id }` }}
|
||||
onClick={e => {
|
||||
const sharedId = `page-${ post.id }`
|
||||
setForLocationKey (location.key, sharedId)
|
||||
onClick?.(e)
|
||||
}}>
|
||||
<motion.div
|
||||
ref={cardRef}
|
||||
layoutId={layoutId}
|
||||
className="w-full h-full overflow-hidden rounded-xl shadow
|
||||
transform-gpu will-change-transform"
|
||||
whileHover={{ scale: 1.02 }}
|
||||
onLayoutAnimationStart={() => {
|
||||
if (cardRef.current)
|
||||
{
|
||||
cardRef.current.style.position = 'relative'
|
||||
cardRef.current.style.zIndex = '9999'
|
||||
}
|
||||
}}
|
||||
onLayoutAnimationComplete={() => {
|
||||
if (cardRef.current)
|
||||
{
|
||||
cardRef.current.style.zIndex = ''
|
||||
cardRef.current.style.position = ''
|
||||
}
|
||||
}}
|
||||
transition={{ type: 'spring', stiffness: 500, damping: 40, mass: .5 }}>
|
||||
<img src={post.thumbnail || post.thumbnailBase || undefined}
|
||||
alt={post.title || post.url}
|
||||
title={post.title || post.url || undefined}
|
||||
loading={i < 12 ? 'eager' : 'lazy'}
|
||||
decoding="async"
|
||||
className="object-cover w-full h-full"/>
|
||||
</motion.div>
|
||||
</PrefetchLink>)
|
||||
})}
|
||||
</div>
|
||||
</>)
|
||||
}) satisfies FC<Props>
|
||||
|
||||
Reference in New Issue
Block a user