direction-aware-tabs
cult-ui/direction-aware-tabsUnverifiedComponent
Tab component with direction-aware animations and smooth transitions
Install it
npx shadcn@latest add https://raw.githubusercontent.com/nolly-studio/cult-ui/HEAD/apps/www/direction-aware-tabs.jsonSource
1"use client"23import { ReactNode, useMemo, useState } from "react"4import { AnimatePresence, motion, MotionConfig } from "motion/react"5import useMeasure from "react-use-measure"67import { cn } from "@/lib/utils"89type Tab = {10 id: number11 label: string12 content: ReactNode13}1415interface OgImageSectionProps {16 tabs: Tab[]17 className?: string18 /** Outer container radius (e.g. `rounded-lg`) */19 rounded?: string20 /** Inner tab/bubble radius — should be outer radius minus container padding (~3px) */21 roundedInner?: string22 onChange?: () => void23}2425function DirectionAwareTabs({26 tabs,27 className,28 rounded,29 roundedInner,30 onChange,31}: OgImageSectionProps) {32 const [activeTab, setActiveTab] = useState(0)33 const [direction, setDirection] = useState(0)34 const [isAnimating, setIsAnimating] = useState(false)35 const [ref, bounds] = useMeasure()3637 const content = useMemo(() => {38 const activeTabContent = tabs.find((tab) => tab.id === activeTab)?.content39 return activeTabContent || null40 }, [activeTab, tabs])4142 const handleTabClick = (newTabId: number) => {43 if (newTabId !== activeTab && !isAnimating) {44 const newDirection = newTabId > activeTab ? 1 : -145 setDirection(newDirection)46 setActiveTab(newTabId)47 onChange ? onChange() : null48 }49 }5051 const variants = {52 initial: (direction: number) => ({53 x: 300 * direction,54 opacity: 0,55 filter: "blur(4px)",56 }),57 active: {58 x: 0,59 opacity: 1,60 filter: "blur(0px)",61 },62 exit: (direction: number) => ({63 x: -300 * direction,64 opacity: 0,65 filter: "blur(4px)",66 }),67 }6869 return (70 <div className=" flex flex-col items-center w-full">71 <div72 className={cn(73 "flex space-x-1 border border-none rounded-full cursor-pointer bg-neutral-600 px-[3px] py-[3.2px] shadow-inner-shadow",74 className,75 rounded76 )}77 >78 {tabs.map((tab) => (79 <button80 key={tab.id}81 onClick={() => handleTabClick(tab.id)}82 className={cn(83 "relative rounded-full px-3.5 py-1.5 text-xs sm:text-sm font-medium text-neutral-200 transition focus-visible:outline-1 focus-visible:ring-1 focus-visible:outline-none flex gap-2 items-center ",84 activeTab === tab.id85 ? "text-white"86 : "hover:text-neutral-300/60 text-neutral-200/80",87 rounded ? roundedInner : undefined88 )}89// … truncated
What it pulls in
npm packages
Files it writes
More from cult/ui
All 157 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| ai-instructionsai-instructions | cult/ui | Components | Unverified | 2 deps | |
| ai-instructions-demoai-instructions-demo | cult/ui | Components | Unverified | no deps | |
| animated-numberanimated-number | cult/ui | Components | Unverified | 1 dep | |
| animated-number-demoanimated-number-demo | cult/ui | Components | Unverified | no deps | |
| bg-animate-buttonbg-animate-button | cult/ui | Components | Unverified | no deps | |
| bg-animate-button-demobg-animate-button-demo | cult/ui | Components | Unverified | no deps | |
| bg-animated-fractal-dot-gridbg-animated-fractal-dot-grid | cult/ui | Components | Unverified | 1 dep | |
| bg-animated-fractal-dot-grid-demobg-animated-fractal-dot-grid-demo | cult/ui | Components | Unverified | no deps |
