Floating Navbar
zyeon/floating-navbarFreeComponent
A header that hides on scroll-down and reappears on scroll-up, giving long reading surfaces the vertical space back without losing the nav.
Install it
npx shadcn@latest add https://ui.zyeon.ai/r/floating-navbar.jsonSource
1"use client"23import * as React from "react"4import { cn } from "@/lib/utils"56export interface FloatingNavbarProps extends React.HTMLAttributes<HTMLElement> {7 /** The consumer's own nav content — logo, links, actions. This component is a shell only. */8 children: React.ReactNode9 /** Scrollable container to track; omit to track the window. */10 target?: React.RefObject<HTMLElement | null>11 /** Top-of-page exemption band in px — while scroll position is within it, the bar always stays visible. */12 threshold?: number13}1415function getScrollTop(target?: React.RefObject<HTMLElement | null>) {16 const el = target?.current17 return el ? el.scrollTop : window.scrollY18}1920/**21 * A sticky header that hides on scroll-down and reappears on scroll-up, so long22 * reading surfaces (articles, docs, feeds) get the vertical space back without23 * losing the nav entirely. Direction is derived from a ref-held previous24 * scrollTop, not React state, so the high-frequency scroll math never re-renders.25 */26export const FloatingNavbar = React.forwardRef<HTMLElement, FloatingNavbarProps>(27 ({ children, target, threshold = 80, className, ...props }, ref) => {28 const [hidden, setHidden] = React.useState(false)29 const lastY = React.useRef(0)3031 // Passive scroll listener, throttled to one direction check per frame via rAF.32 // setHidden only ever runs inside the rAF callback, never synchronously in the effect body.33 React.useEffect(() => {34 lastY.current = getScrollTop(target)35 let raf = 03637 const tick = () => {38 raf = 039 const y = getScrollTop(target)4041 if (y <= threshold) {42 // Top-of-page exemption: never hide inside the band, no direction math needed.43 setHidden(false)44 lastY.current = y45 return46 }4748 const delta = y - lastY.current49 // Direction jitter guard — sub-8px wobble (trackpads, momentum scroll) is50 // ignored and keeps accumulating against the same reference point.51 if (Math.abs(delta) < 8) return52 setHidden(delta > 0)53 lastY.current = y54 }5556 const onScroll = () => {57 if (raf) return58 raf = requestAnimationFrame(tick)59 }6061 // Container + window, same lesson as scroll-to-top: a target container may62 // not be scrollable yet at mount time, so both sources stay wired.63 const node = target?.current ?? null64 const sources: EventTarget[] = node ? [node, window] : [window]65// … truncated
What it pulls in
Other registry items
Files it writes
More from zyeon
All 893 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| A/B Test Resultab-test-result | zyeon | Components | Paid | 2 deps · 2 files | |
| Accordionaccordion | zyeon | Components | Free | 1 dep | |
| Activity Feedactivity-feed | zyeon | Components | Free | 2 deps · 2 files | |
| Activity Heatmapactivity-heatmap | zyeon | Components | Paid | 1 dep · 2 files | |
| Address Formaddress-form | zyeon | Components | Paid | 1 dep | |
| Agent Graphagent-graph | zyeon | Components | Free | 2 deps · 2 files | |
| Agent Handoffagent-handoff | zyeon | Components | Free | 1 dep | |
| Agent Inboxagent-inbox | zyeon | Components | Free | 2 deps · 2 files |
