Motion Tabs Menu

A floating bottom tab bar with animated width expansion, direction-aware content transitions, and spring-driven tap feedback.

Installation

CLI installation is not available for Pro components.

File Structure

motion-tabs-menu.tsx

Usage

import MotionTabsMenu from "@/components/unlumen-ui/motion-tabs-menu";

export default function Page() {
  return (
    <div className="flex min-h-screen items-center justify-center">
      <MotionTabsMenu />
    </div>
  );
}

API Reference

This component is fully self-contained and exposes no props. All demo data, tab content, and internal state are managed internally.

Notes

  • Dynamic width — the toolbar width is computed from the number of buttons, gaps, and padding rather than hardcoded. When a tab becomes active, the active label's character count is used to derive the extra horizontal space, so the container never over- or under-shoots.
  • Label delay — the active tab label fades in 80 ms after the width animation starts, giving the container a head start before the text appears. This is achieved by spreading springTransition and overriding delay: 0.08 on the label's motion.span.
  • Direction-aware slides — switching between tabs sets a direction value (+1 or −1) that drives the custom prop of contentVariants, so content always slides in from the correct side.
  • Height measurementreact-use-measure attaches a ResizeObserver to the content wrapper and feeds the live height into the spring animation, so the container snaps to the exact content size with no hardcoded values.
  • AnimatePresence mode="popLayout" — exiting panels are removed from layout flow immediately, preventing double-height artifacts while two panels overlap during a tab switch.
  • Tap feedbackwhileTap applies a vertical squish (scaleY: 0.8) to each button on press, with an automatic spring return on release.
  • Click-outside collapse — a native mousedown listener on a containerRef closes the expanded panel without any third-party hook.

Credits

Built by leo.

Inspired by Skiper UI.

Keep in mind

Most components on this site are inspired by or recreated from existing work across the web. I'm not here to take credit; just to learn, experiment, and sometimes push things a bit further. If something looks familiar and I forgot to mention you, reach out and I'll fix that right away.