Tabs
fluid-functionalism/tabsFreeComponent
Segmented control tabs with sliding active indicator, proximity hover, and spring animations. Built on Radix UI Tabs.
Install it
npx shadcn@latest add https://fluidfunctionalism.com/r/tabs.jsonSource
1"use client";23import {4 useRef,5 useState,6 useCallback,7 useEffect,8 useLayoutEffect,9 createContext,10 useContext,11 forwardRef,12 Children,13 cloneElement,14 isValidElement,15 type ComponentPropsWithoutRef,16} from "react";17import * as TabsPrimitive from "@radix-ui/react-tabs";18import { motion, AnimatePresence } from "framer-motion";19import type { IconComponent } from "@/lib/icon-context";20import { cn } from "@/lib/utils";21import { spring } from "@/lib/springs";22import { fontWeights } from "@/lib/font-weight";23import { useShape } from "@/lib/shape-context";24import { useSurface } from "@/lib/surface-context";25import { surfaceClasses } from "@/lib/surface-classes";26import { useProximityHover } from "@/hooks/use-proximity-hover";2728/* ─────────────────────── Contexts ─────────────────────── */2930interface TabsValueOrderContextValue {31 valueOrder: string[];32 setValueOrder: (order: string[]) => void;33 selectedValue: string | undefined;34}3536const TabsValueOrderContext = createContext<TabsValueOrderContextValue | null>(null);3738interface TabsListContextValue {39 registerTab: (index: number, value: string, el: HTMLElement | null) => void;40 hoveredIndex: number | null;41 selectedValue: string | undefined;42 /** Optimistically set selectedIdx so the indicator moves immediately on click. */43 setOptimisticIdx: (index: number) => void;44}4546const TabsListContext = createContext<TabsListContextValue | null>(null);4748function useTabsList() {49 const ctx = useContext(TabsListContext);50 if (!ctx) throw new Error("TabItem must be used within a TabsList");51 return ctx;52}5354/* ─────────────────────── Tabs (Root) ─────────────────────── */5556interface TabsProps57 extends Omit<58 ComponentPropsWithoutRef<typeof TabsPrimitive.Root>,59 "onValueChange" | "onSelect"60 > {61 /** Controlled value (takes precedence over selectedIndex). */62 value?: string;63 /** Called when the active tab changes. */64 onValueChange?: (value: string) => void;65 /** Index-based controlled alternative. */66 selectedIndex?: number;67 /** Called with the new index when the active tab changes. */68 onSelect?: (index: number) => void;69}7071const Tabs = forwardRef<HTMLDivElement, TabsProps>(72 (73 {74 value,75 onValueChange,76 selectedIndex,77 onSelect,78 defaultValue,79 children,80// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from fluid-functionalism
All 53 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | fluid-functionalism | Components | Free | 3 deps | |
| Accordion (Base UI)accordion-base | fluid-functionalism | Components | Free | 3 deps | |
| Ask User Questionsask-user-questions | fluid-functionalism | Components | Free | 2 deps | |
| Badgebadge | fluid-functionalism | Components | Free | 1 dep | |
| Buttonbutton | fluid-functionalism | Components | Free | 4 deps | |
| Button (Base UI)button-base | fluid-functionalism | Components | Free | 4 deps | |
| Cardcard | fluid-functionalism | Components | Free | 1 dep | |
| Chat Messagechat-message | fluid-functionalism | Components | Free | 1 dep |
