NavigationSimpleApril 8, 2026
Staggered Nav Dock Entrance
Nav dock items stagger in on first page load with a delay after the loading screen completes. Each item fades up with a 1s duration entrance curve and 3s initial delay, 0.08s stagger.
View Full Demo →Preview
Source
demo.jsx
import StaggeredNavDockEntrance from "./index.jsx";
import styles from "./demo.module.css";
const props = {
siteName: "no-5.studio",
links: [
{ label: "Work", href: "#" },
{ label: "Lab", href: "#" },
{ label: "About", href: "#" },
{ label: "Contact", href: "#" },
],
};
export default function StaggeredNavDockEntranceDemo() {
return (
<div className={styles.demo}>
<StaggeredNavDockEntrance {...props} />
<div className={styles.hero}>
<p className={styles.label}>2024 — In Development</p>
<h1 className={styles.heading}>The Lab</h1>
<p className={styles.sub}>Experiments & Prototypes</p>
</div>
</div>
);
}
index.jsx
"use client";
import { useEffect, useRef } from "react";
import { motion } from "framer-motion";
import styles from "./styles.module.css";
const itemVariants = {
hidden: { opacity: 0, y: 12 },
visible: (i) => ({
opacity: 1,
y: 0,
transition: {
duration: 1,
ease: [0.16, 1, 0.3, 1],
delay: 3 + i * 0.08,
},
}),
};
export default function StaggeredNavDockEntrance({ siteName = "", links = [] }) {
return (
<nav className={styles.dock}>
<motion.span
className={styles.logo}
variants={itemVariants}
custom={0}
initial="hidden"
animate="visible"
>
{siteName}
</motion.span>
<ul className={styles.links}>
{links.map((link, i) => (
<motion.li
key={link.label}
variants={itemVariants}
custom={i + 1}
initial="hidden"
animate="visible"
>
<a href={link.href} className={styles.link}>
{link.label}
</a>
</motion.li>
))}
</ul>
</nav>
);
}
demo.module.css
.demo {
min-height: 100vh;
background: #fafafa;
display: flex;
flex-direction: column;
}
.hero {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
padding: 4rem 2rem;
gap: 1rem;
}
.label {
font-size: 0.75rem;
font-weight: 500;
letter-spacing: 0.14em;
text-transform: uppercase;
color: #9b9b9b;
}
.heading {
font-size: clamp(3rem, 8vw, 7rem);
font-weight: 500;
letter-spacing: -0.03em;
line-height: 0.95;
color: #1a1a1a;
}
.sub {
font-size: 1rem;
font-weight: 400;
letter-spacing: 0.08em;
text-transform: uppercase;
color: #9b9b9b;
}
styles.module.css
.dock {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1.25rem 2rem;
background: #fafafa;
border-bottom: 1px solid #e5e5e5;
min-height: 200px;
}
.logo {
font-size: 1rem;
font-weight: 600;
letter-spacing: -0.01em;
color: #1a1a1a;
}
.links {
display: flex;
gap: 2rem;
list-style: none;
padding: 0;
margin: 0;
}
.link {
font-size: 0.875rem;
font-weight: 500;
color: #6b6b6b;
text-decoration: none;
letter-spacing: -0.01em;
transition: color 200ms ease;
}
.link:hover {
color: #1a1a1a;
}
Dependencies
framer-motion