Skip to content

Commit 69bc2ae

Browse files
committed
Fix nav highlight route entry positioning
1 parent e33b659 commit 69bc2ae

1 file changed

Lines changed: 19 additions & 14 deletions

File tree

src/components/nav-card.tsx

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { HomeDraggableLayer } from '@/app/(home)/home-draggable-layer'
2727
import { useSiteAssetUrl } from '@/hooks/use-site-assets'
2828

2929
const list = [
30+
3031
{
3132
icon: ScrollOutlineSVG,
3233
iconActive: ScrollFilledSVG,
@@ -68,6 +69,11 @@ const list = [
6869
const extraSize = 5
6970
const APPS_ICON_SCALE = 1.5
7071
const DEFAULT_ICON_SIZE_CLASS = 'h-7 w-7'
72+
const NAV_HIGHLIGHT_TRANSITION = {
73+
type: 'spring' as const,
74+
stiffness: 400,
75+
damping: 30
76+
}
7177

7278
const AVATAR_URL = '/api/site-assets/avatar'
7379

@@ -79,13 +85,12 @@ export default function NavCard() {
7985
const [hoveredIndex, setHoveredIndex] = useState<number>(0)
8086
const [hoverRect, setHoverRect] = useState<{ centerX: number; top: number; width: number; height: number } | null>(null)
8187
const itemRefs = useRef<Array<HTMLAnchorElement | null>>([])
88+
const iconContainerRef = useRef<HTMLDivElement | null>(null)
8289
const { siteContent, cardStyles } = useConfigStore()
8390
const avatarUrl = useSiteAssetUrl('avatar')
8491
const styles = cardStyles.navCard
8592
const hiCardStyles = cardStyles.hiCard
8693

87-
const hoverLayoutId = useMemo(() => `nav-hover-${pathname === '/' ? 'home' : pathname.replace(/[^a-z0-9_-]/gi, '_')}`,[pathname])
88-
8994
const activeIndex = useMemo(() => {
9095
const index = list.findIndex(item => pathname === item.href)
9196
return index >= 0 ? index : undefined
@@ -135,18 +140,22 @@ export default function NavCard() {
135140
}
136141

137142
const activeItem = itemRefs.current[hoveredIndex]
138-
if (!activeItem) {
143+
const container = iconContainerRef.current
144+
if (!activeItem || !container) {
139145
setHoverRect(null)
140146
return
141147
}
142148

149+
const itemRect = activeItem.getBoundingClientRect()
150+
const containerRect = container.getBoundingClientRect()
151+
143152
setHoverRect({
144-
centerX: activeItem.offsetLeft + activeItem.offsetWidth / 2,
145-
top: activeItem.offsetTop,
146-
width: activeItem.offsetWidth,
147-
height: activeItem.offsetHeight
153+
centerX: itemRect.left - containerRect.left + itemRect.width / 2,
154+
top: itemRect.top - containerRect.top,
155+
width: itemRect.width,
156+
height: itemRect.height
148157
})
149-
}, [form, hoveredIndex, maxSM, maxXS, pathname])
158+
}, [form, hoveredIndex, maxSM, maxXS, pathname, size.width])
150159

151160

152161
if (maxSM) position = { x: center.x - size.width / 2, y: 16 }
@@ -183,14 +192,14 @@ export default function NavCard() {
183192
{form !== 'icons' && <div className='text-secondary mt-6 text-sm uppercase'>General</div>}
184193

185194
<div
195+
ref={iconContainerRef}
186196
className={cn('relative mt-2 space-y-2', form === 'icons' && 'mt-0 flex min-w-0 flex-1 items-center justify-between gap-2 space-y-0 overflow-visible sm:gap-4')}
187197
onMouseLeave={() => {
188198
if (form === 'icons') setHoveredIndex(activeIndex ?? 0)
189199
}}>
190200
{(form !== 'icons' || hoverRect) && (
191201
<motion.div
192202
className='pointer-events-none absolute max-w-[230px] rounded-full border'
193-
layoutId={hoverLayoutId}
194203
initial={false}
195204
animate={
196205
form === 'icons'
@@ -202,11 +211,7 @@ export default function NavCard() {
202211
}
203212
: { top: hoveredIndex * (itemHeight + 8), left: 0, width: '100%', height: itemHeight }
204213
}
205-
transition={{
206-
type: 'spring',
207-
stiffness: 400,
208-
damping: 30
209-
}}
214+
transition={NAV_HIGHLIGHT_TRANSITION}
210215
style={{ backgroundImage: 'linear-gradient(to right bottom, var(--color-border) 60%, var(--color-card) 100%)' }}
211216
/>
212217
)}

0 commit comments

Comments
 (0)