This commit is contained in:
2026-04-13 18:33:50 +09:00
parent 27989f3bb2
commit 584415edff
6 changed files with 64 additions and 46 deletions
+9 -6
View File
@@ -1,4 +1,4 @@
import { AnimatePresence, LayoutGroup } from 'framer-motion' import { AnimatePresence, LayoutGroup, motion } from 'framer-motion'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { BrowserRouter, import { BrowserRouter,
Navigate, Navigate,
@@ -46,7 +46,6 @@ const RouteTransitionWrapper = ({ user, setUser }: {
const location = useLocation () const location = useLocation ()
return ( return (
<LayoutGroup id="gallery-shared">
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
<Routes location={location}> <Routes location={location}>
<Route path="/" element={<Navigate to="/posts" replace/>}/> <Route path="/" element={<Navigate to="/posts" replace/>}/>
@@ -76,8 +75,7 @@ const RouteTransitionWrapper = ({ user, setUser }: {
<Route path="/more" element={<MorePage/>}/> <Route path="/more" element={<MorePage/>}/>
<Route path="*" element={<NotFound/>}/> <Route path="*" element={<NotFound/>}/>
</Routes> </Routes>
</AnimatePresence> </AnimatePresence>)
</LayoutGroup>)
} }
@@ -135,10 +133,15 @@ export default (() => {
<> <>
<RouteBlockerOverlay/> <RouteBlockerOverlay/>
<BrowserRouter> <BrowserRouter>
<div className="flex flex-col h-dvh w-full"> <LayoutGroup>
<motion.div
layout="position"
transition={{ layout: { duration: .2, ease: 'easeOut' } }}
className="flex flex-col h-dvh w-full overflow-y-hidden">
<TopNav user={user}/> <TopNav user={user}/>
<RouteTransitionWrapper user={user} setUser={setUser}/> <RouteTransitionWrapper user={user} setUser={setUser}/>
</div> </motion.div>
</LayoutGroup>
<Toaster/> <Toaster/>
</BrowserRouter> </BrowserRouter>
</>) </>)
+1 -1
View File
@@ -56,7 +56,7 @@ export default (({ posts, onClick }: Props) => {
cardRef.current.style.zIndex = '' cardRef.current.style.zIndex = ''
cardRef.current.style.position = '' cardRef.current.style.position = ''
}} }}
transition={{ type: 'spring', stiffness: 500, damping: 40, mass: .5 }}> transition={{ layout: { duration: .2, ease: 'easeOut' } }}>
<img src={post.thumbnail || post.thumbnailBase || undefined} <img src={post.thumbnail || post.thumbnailBase || undefined}
alt={post.title || post.url} alt={post.title || post.url}
title={post.title || post.url || undefined} title={post.title || post.url || undefined}
+3 -1
View File
@@ -65,7 +65,9 @@ export default (({ posts, onClick }: Props) => {
{CATEGORIES.flatMap (cat => cat in tags ? ( {CATEGORIES.flatMap (cat => cat in tags ? (
tags[cat].map (tag => ( tags[cat].map (tag => (
<li key={tag.id} className="mb-1"> <li key={tag.id} className="mb-1">
<motion.div layoutId={`tag-${ tag.id }`}> <motion.div
transition={{ layout: { duration: .2, ease: 'easeOut' } }}
layoutId={`tag-${ tag.id }`}>
<TagLink tag={tag} onClick={onClick}/> <TagLink tag={tag} onClick={onClick}/>
</motion.div> </motion.div>
</li>))) : [])} </li>))) : [])}
+7 -3
View File
@@ -201,17 +201,17 @@ export default (({ user }: Props) => {
</PrefetchLink> </PrefetchLink>
</motion.div>))} </motion.div>))}
<PrefetchLink <PrefetchLink
to="#" to="/more"
ref={(el: (HTMLAnchorElement | null)) => { ref={(el: (HTMLAnchorElement | null)) => {
itemsRef.current[visibleMenu.length] = el itemsRef.current[visibleMenu.length] = el
}} }}
onClick={e => e.preventDefault ()} onClick={() => setMoreVsbl (false)}
onMouseEnter={() => { onMouseEnter={() => {
setMoreVsbl (true) setMoreVsbl (true)
measure (-1) measure (-1)
}} }}
className={cn ('relative z-10 flex h-full items-center px-5', className={cn ('relative z-10 flex h-full items-center px-5',
(openItemIdx < 0) && 'font-bold')}> (openItemIdx < 0 || moreVsbl) && 'font-bold')}>
&raquo; &raquo;
</PrefetchLink> </PrefetchLink>
</div> </div>
@@ -280,6 +280,7 @@ export default (({ user }: Props) => {
: ( : (
<motion.div <motion.div
key={`l-${ i }-${ j }`} key={`l-${ i }-${ j }`}
transition={{ duration: .2, ease: 'easeOut' }}
{...((visibleMenu[activeIdx]?.name {...((visibleMenu[activeIdx]?.name
=== item.name) === item.name)
? { layoutId: `submenu-${ item.name }-${ j }` } ? { layoutId: `submenu-${ item.name }-${ j }` }
@@ -289,6 +290,7 @@ export default (({ user }: Props) => {
<PrefetchLink <PrefetchLink
to={subItem.to} to={subItem.to}
target={subItem.to.slice (0, 2) === '//' ? '_blank' : undefined} target={subItem.to.slice (0, 2) === '//' ? '_blank' : undefined}
onClick={() => setMoreVsbl (false)}
className="h-full flex items-center px-3"> className="h-full flex items-center px-3">
{subItem.name} {subItem.name}
</PrefetchLink> </PrefetchLink>
@@ -317,12 +319,14 @@ export default (({ user }: Props) => {
? ( ? (
<motion.div <motion.div
key={`c-${ i }`} key={`c-${ i }`}
transition={{ layout: { duration: .2, ease: 'easeOut' } }}
layoutId={`submenu-${ visibleMenu[activeIdx].name }-${ i }`}> layoutId={`submenu-${ visibleMenu[activeIdx].name }-${ i }`}>
{item.component} {item.component}
</motion.div>) </motion.div>)
: ( : (
<motion.div <motion.div
key={`l-${ i }`} key={`l-${ i }`}
transition={{ layout: { duration: .2, ease: 'easeOut' } }}
layoutId={`submenu-${ visibleMenu[activeIdx].name }-${ i }`}> layoutId={`submenu-${ visibleMenu[activeIdx].name }-${ i }`}>
<PrefetchLink <PrefetchLink
to={item.to} to={item.to}
+7 -2
View File
@@ -1,3 +1,5 @@
import { motion } from 'framer-motion'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import type { FC, ReactNode } from 'react' import type { FC, ReactNode } from 'react'
@@ -8,6 +10,9 @@ type Props = {
export default (({ children, className }: Props) => ( export default (({ children, className }: Props) => (
<main className={cn ('flex-1 overflow-y-auto p-4', className)}> <motion.main
transition={{ layout: { duration: .2, ease: 'easeOut' } }}
className={cn ('flex-1 overflow-y-auto p-4', className)}
layout="position">
{children} {children}
</main>)) satisfies FC<Props> </motion.main>)) satisfies FC<Props>
@@ -1,3 +1,4 @@
import { motion } from 'framer-motion'
import { Helmet } from 'react-helmet-async' import { Helmet } from 'react-helmet-async'
import type { FC, ReactNode } from 'react' import type { FC, ReactNode } from 'react'
@@ -6,7 +7,10 @@ type Props = { children: ReactNode }
export default (({ children }: Props) => ( export default (({ children }: Props) => (
<div className="p-4 w-full md:w-64 md:h-full md:overflow-y-auto sidebar"> <motion.div
layout="position"
transition={{ layout: { duration: .2, ease: 'easeOut' } }}
className="p-4 w-full md:w-64 md:h-full md:overflow-y-auto sidebar">
<Helmet> <Helmet>
<style> <style>
{` {`
@@ -23,4 +27,4 @@ export default (({ children }: Props) => (
</Helmet> </Helmet>
{children} {children}
</div>)) satisfies FC<Props> </motion.div>)) satisfies FC<Props>