In-page navbar
100xui/in-page-navbarFreeBlock
A smart, fully responsive, and accessible navigation bar that tracks section progress as you scroll, providing a clear visual indicator of your journey through the page. Best suited for single-page layouts where all content lives on a single page.
Live preview
live · rendered by the registry
Rendered by 100xui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://100xui.com/r/in-page-navbar.jsonSource
1"use client";2import React from "react";3import {4 AnimatePresence,5 motion,6 useScroll,7 useTransform,8 type Variants,9 type MotionValue,10} from "motion/react";11import { EqualIcon, XIcon } from "lucide-react";12import { useIsServer } from "@/hooks/use-is-server";13import { cn } from "@/lib/utils";1415const fadeVariants: Variants = {16 fadeIn: { opacity: 1 },17 fadeOut: { opacity: 0 },18};1920interface NavSection extends Omit<React.ComponentProps<"a">, "href"> {21 label: string;22 id: string;23}2425export interface InPageNavbarProps extends React.ComponentProps<"div"> {26 logo: React.ReactElement;27 sections: NavSection[];28}2930export function InPageNavbar({31 logo,32 sections,33 className,34 ...rest35}: InPageNavbarProps) {36 const [isSidebarOpen, setIsSidebarOpen] = React.useState(false);37 const [isSmallScreen, setIsSmallScreen] = React.useState(false);38 const isServer = useIsServer();3940 const navButtons = (41 <NavButtonGroup42 sections={sections}43 isServer={isServer}44 className="gap-x-1.5 gap-y-1 max-sm:mx-auto max-sm:grid max-sm:max-w-fit max-sm:grid-rows-3 max-sm:py-8 max-sm:text-sm sm:flex sm:items-center"45 />46 );4748 React.useEffect(() => {49 const handleMediaQuery = ({ matches }: { matches: boolean }) =>50 setIsSmallScreen(matches);51 const mediaQuery = window.matchMedia("(max-width:639px)");52 mediaQuery.addEventListener("change", handleMediaQuery);53 return () => mediaQuery.removeEventListener("change", handleMediaQuery);54 }, []);5556 return (57 <>58 <div59 className={cn(60 "pointer-events-none fixed inset-x-4.5 top-1.5 z-[100]",61 "[&_a,button]:focus-visible:ring-offset-background [&_a,button]:focus-visible:ring-ring [&_a,button]:transition-opacity [&_a,button]:duration-150 [&_a,button]:ease-out [&_a,button]:hover:opacity-70 [&_a,button]:focus-visible:opacity-70 [&_a,button]:focus-visible:ring-1 [&_a,button]:focus-visible:ring-offset-1 [&_a,button]:focus-visible:outline-0",62 className,63 )}64 {...rest}65 >66 <motion.div67 initial={false}68 animate={isSidebarOpen && isSmallScreen ? "fadeOut" : "fadeIn"}69 variants={fadeVariants}70 className="bg-card/85 border-border/50 pointer-events-auto mx-auto flex max-w-xl items-center justify-between rounded-lg border p-3 text-sm font-medium shadow-md backdrop-blur-[2px] sm:rounded-xl"71 >72 <a73 href="#"74 tabIndex={1}75 onClick={(e) => {76// … truncated
What it pulls in
npm packages
Files it writes
More from 100xui
All 14 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Apple galleryapple-gallery | 100xui | Blocks | Free | 1 dep | |
| Chat bento cardchat-bento-card | 100xui | Blocks | Free | 1 dep | |
| demosdemos | 100xui | Blocks | Free | no deps · 12 files | |
| internalsinternals | 100xui | Blocks | Free | no deps · 4 files | |
| iPhone 3D mockupiphone-3d-mockup | 100xui | Blocks | Free | no deps | |
| Menu wheelmenu-wheel | 100xui | Blocks | Free | 1 dep | |
| Morph modalmorph-modal | 100xui | Blocks | Free | 1 dep | |
| Motion Dockmotion-dock | 100xui | Blocks | Free | 1 dep · 3 files |
