Scroll the current dashboard to the middle of the phone rail
On mount and on every switch the horizontal rail scrolls itself (not the page) so the active entry is centred, instantly under reduced motion.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { useQueries } from "@tanstack/react-query"
|
||||
import type { LinkProps } from "@tanstack/react-router"
|
||||
import { useReducedMotion } from "motion/react"
|
||||
import { useEffect, useRef } from "react"
|
||||
|
||||
import { dashboardQueryOptions } from "@/components/Dashboard/queries"
|
||||
import { useUi } from "./ui"
|
||||
@@ -32,6 +34,8 @@ export function PanelRail({
|
||||
horizontal?: boolean
|
||||
}) {
|
||||
const { Rail } = useUi()
|
||||
const box = useRef<HTMLDivElement>(null)
|
||||
const still = useReducedMotion()
|
||||
const entries = useQueries({
|
||||
queries: dashboards.map((name) => dashboardQueryOptions(name)),
|
||||
combine: (results) =>
|
||||
@@ -44,5 +48,28 @@ export function PanelRail({
|
||||
})),
|
||||
})
|
||||
|
||||
return <Rail entries={entries} horizontal={horizontal} />
|
||||
// A row of more dashboards than fit scrolls sideways, so the current one is
|
||||
// brought to its middle. Only the row moves: `scrollIntoView` would scroll
|
||||
// the page under it too.
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: a new current dashboard is what scrolls.
|
||||
useEffect(() => {
|
||||
if (!horizontal) return
|
||||
const item = box.current?.querySelector('[aria-current="page"]')
|
||||
const row = item?.closest(".dui-rail")
|
||||
if (!item || !row) return
|
||||
const at = item.getBoundingClientRect()
|
||||
const frame = row.getBoundingClientRect()
|
||||
row.scrollBy({
|
||||
left: at.left + at.width / 2 - (frame.left + frame.width / 2),
|
||||
behavior: still ? "instant" : "smooth",
|
||||
})
|
||||
}, [current, horizontal, still])
|
||||
|
||||
// `contents`, so the wrapper is only something to search from: the caller
|
||||
// places the rail itself.
|
||||
return (
|
||||
<div ref={box} className="contents">
|
||||
<Rail entries={entries} horizontal={horizontal} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user