Elastic Underline Nav
A nav underline that stretches with the distance it travels and settles back to width.
- Category
- Components
- Added
- 2026-09-20
- Deps
- 1
- Updated
- 2026-09-20
This is a viberdy Pro component
The live preview, the props panel and the write-up are open to everyone. The full source, the AI prompt and CLI install are part of Pro.
Props
"use client";
import { useEffect, useRef, useState } from "react";
import { motion } from "framer-motion";
/**
* Gate the scheme before a caller-supplied string reaches an href.
* A javascript: or data:text/html URL executes on click, so any link list
* fed from a CMS, a database or user submissions is an XSS sink without this.
*/
const SAFE_HREF = /^(?:https?:|mailto:|tel:|\/|#|\.)/i;
const safeHref = (h: string) => (SAFE_HREF.test(h.trim()) ? h : "#");
export function ElasticUnderlineNav({
items,
stretch = 0.5,
thickness = 2,
// ---------------------------------------------------------------
// Full source available with a viberdy Pro subscription.
// https://viberdy.dev/pricing
// ---------------------------------------------------------------
}About this component
A shared `layoutId` pill slides between nav items at a constant width, which is smooth and entirely inert. Squash-and-stretch is what animators have used for a century to make motion read as physical: a body deforms in proportion to how fast it is moving and recovers on arrival. Deriving the bar's horizontal scale from the distance between the previous and new positions reproduces exactly that — a jump to the neighbouring item barely deforms, a jump across the whole nav stretches noticeably, and the difference is legible without being cartoonish. Two supporting choices carry it. The travel and the stretch use separate springs, with the stretch looser, so the bar recovers its width slightly after it arrives rather than in lockstep, which is what keeps the settle from feeling mechanical. And positions come from measuring each item's real rect rather than dividing the container by item count, so labels of different lengths — the normal case — track correctly. Focus mirrors hover, so the underline is not a mouse-only affordance.
Curator’s note
Built for viberdy 2.1. Scaling by distance travelled is squash-and-stretch — the detail a shared-layoutId pill structurally cannot do.
Pairs well with
Matched on shared tags and category — the entries most likely to be used alongside this one.
Cursor Label Follower
componentsA contextual chip that trails the pointer and names whatever it is over.
Snapping Cursor
componentsA cursor dot that latches onto interactive elements and takes their exact shape.
Magnetic Button
componentsA button whose label leans toward the cursor with a springy pull.