このコミットが含まれているのは:
@@ -20,12 +20,13 @@ type Props = { user: User | null }
|
|||||||
export default (({ user }: Props) => {
|
export default (({ user }: Props) => {
|
||||||
const location = useLocation ()
|
const location = useLocation ()
|
||||||
|
|
||||||
const itemRefs = useRef<(HTMLAnchorElement | null)[]> ([])
|
const dirRef = useRef<(-1) | 1> (1)
|
||||||
|
const itemsRef = useRef<(HTMLAnchorElement | null)[]> ([])
|
||||||
const navRef = useRef<HTMLDivElement | null> (null)
|
const navRef = useRef<HTMLDivElement | null> (null)
|
||||||
|
|
||||||
const measure = () => {
|
const measure = () => {
|
||||||
const nav = navRef.current
|
const nav = navRef.current
|
||||||
const el = itemRefs.current[activeIdx]
|
const el = itemsRef.current[activeIdx]
|
||||||
if (!(nav) || !(el) || activeIdx < 0)
|
if (!(nav) || !(el) || activeIdx < 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -44,7 +45,6 @@ export default (({ user }: Props) => {
|
|||||||
const [menuOpen, setMenuOpen] = useState (false)
|
const [menuOpen, setMenuOpen] = useState (false)
|
||||||
const [openItemIdx, setOpenItemIdx] = useState (-1)
|
const [openItemIdx, setOpenItemIdx] = useState (-1)
|
||||||
const [postCount, setPostCount] = useState<number | null> (null)
|
const [postCount, setPostCount] = useState<number | null> (null)
|
||||||
const [subDir, setSubDir] = useState<(-1) | 1> (1)
|
|
||||||
const [wikiId, setWikiId] = useState<number | null> (WikiIdBus.get ())
|
const [wikiId, setWikiId] = useState<number | null> (WikiIdBus.get ())
|
||||||
|
|
||||||
const wikiPageFlg = Boolean (/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId)
|
const wikiPageFlg = Boolean (/^\/wiki\/(?!new|changes)[^\/]+/.test (location.pathname) && wikiId)
|
||||||
@@ -80,6 +80,14 @@ export default (({ user }: Props) => {
|
|||||||
|
|
||||||
const prevActiveIdxRef = useRef<number> (activeIdx)
|
const prevActiveIdxRef = useRef<number> (activeIdx)
|
||||||
|
|
||||||
|
if (activeIdx !== prevActiveIdxRef.current)
|
||||||
|
{
|
||||||
|
dirRef.current = activeIdx > prevActiveIdxRef.current ? 1 : -1
|
||||||
|
prevActiveIdxRef.current = activeIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
const dir = dirRef.current
|
||||||
|
|
||||||
useLayoutEffect (() => {
|
useLayoutEffect (() => {
|
||||||
if (activeIdx < 0)
|
if (activeIdx < 0)
|
||||||
return
|
return
|
||||||
@@ -99,15 +107,6 @@ export default (({ user }: Props) => {
|
|||||||
return () => unsubscribe ()
|
return () => unsubscribe ()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect (() => {
|
|
||||||
const prev = prevActiveIdxRef.current
|
|
||||||
if (prev !== activeIdx)
|
|
||||||
{
|
|
||||||
setSubDir (activeIdx > prev ? 1 : -1)
|
|
||||||
prevActiveIdxRef.current = activeIdx
|
|
||||||
}
|
|
||||||
}, [activeIdx])
|
|
||||||
|
|
||||||
useEffect (() => {
|
useEffect (() => {
|
||||||
setMenuOpen (false)
|
setMenuOpen (false)
|
||||||
setOpenItemIdx (menu.findIndex (item => (
|
setOpenItemIdx (menu.findIndex (item => (
|
||||||
@@ -150,9 +149,9 @@ export default (({ user }: Props) => {
|
|||||||
|
|
||||||
<div ref={navRef} className="relative hidden md:flex h-full items-center">
|
<div ref={navRef} className="relative hidden md:flex h-full items-center">
|
||||||
<div aria-hidden
|
<div aria-hidden
|
||||||
className={cn ('absolute top-1/2 -translate-y-1/2 h-full rounded-md',
|
className={cn ('absolute top-1/2 -translate-y-1/2 h-full',
|
||||||
'bg-yellow-200 dark:bg-red-950',
|
'bg-yellow-200 dark:bg-red-950',
|
||||||
'transition-[transform,width,opacity] duration-200 ease-out')}
|
'transition-[transform,width] duration-200 ease-out')}
|
||||||
style={{ width: hl.width,
|
style={{ width: hl.width,
|
||||||
transform: `translate(${ hl.left }px, -50%)`,
|
transform: `translate(${ hl.left }px, -50%)`,
|
||||||
opacity: hl.visible ? 1 : 0 }}/>
|
opacity: hl.visible ? 1 : 0 }}/>
|
||||||
@@ -161,12 +160,10 @@ export default (({ user }: Props) => {
|
|||||||
<Link key={i}
|
<Link key={i}
|
||||||
to={item.to}
|
to={item.to}
|
||||||
ref={el => {
|
ref={el => {
|
||||||
itemRefs.current[i] = el
|
itemsRef.current[i] = el
|
||||||
}}
|
}}
|
||||||
className={cn ('relative z-10 flex h-full items-center px-5',
|
className={cn ('relative z-10 flex h-full items-center px-5',
|
||||||
((i === openItemIdx)
|
(i === openItemIdx) && 'font-bold')}>
|
||||||
? 'font-bold'
|
|
||||||
: 'opacity-90 hover:opacity-100'))}>
|
|
||||||
{item.name}
|
{item.name}
|
||||||
</Link>))}
|
</Link>))}
|
||||||
</div>
|
</div>
|
||||||
@@ -186,16 +183,20 @@ export default (({ user }: Props) => {
|
|||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div className="hidden md:flex bg-yellow-200 dark:bg-red-950
|
<div className="relative hidden md:flex bg-yellow-200 dark:bg-red-950
|
||||||
items-center w-full min-h-[40px] px-3 overflow-hidden">
|
items-center w-full min-h-[40px] overflow-hidden">
|
||||||
<AnimatePresence mode="wait" initial={false}>
|
<AnimatePresence initial={false} custom={dir}>
|
||||||
<motion.div
|
<motion.div
|
||||||
key={activeIdx}
|
key={activeIdx}
|
||||||
className="flex items-center"
|
custom={dir}
|
||||||
initial={{ y: subDir * 24, opacity: 0 }}
|
variants={{ enter: (d: -1 | 1) => ({ y: d * 24, opacity: 0 }),
|
||||||
animate={{ y: 0, opacity: 1 }}
|
centre: { y: 0, opacity: 1 },
|
||||||
exit={{ y: subDir * 24, opacity: 0 }}
|
exit: (d: -1 | 1) => ({ y: (-d) * 24, opacity: 0 }) }}
|
||||||
transition={{ duration: .1, ease: 'easeOut' }}>
|
className="absolute inset-0 flex items-center px-3"
|
||||||
|
initial="enter"
|
||||||
|
animate="centre"
|
||||||
|
exit="exit"
|
||||||
|
transition={{ duration: .2, ease: 'easeOut' }}>
|
||||||
{(menu[activeIdx]?.subMenu ?? [])
|
{(menu[activeIdx]?.subMenu ?? [])
|
||||||
.filter (item => item.visible ?? true)
|
.filter (item => item.visible ?? true)
|
||||||
.map ((item, i) => (
|
.map ((item, i) => (
|
||||||
|
|||||||
新しい課題から参照
ユーザをブロックする