Motion Tabs
edgecom/motion-tabsFreeComponent
The Edgecom Motion Tabs component.
Install it
npx shadcn@latest add https://design.edgecom.ai/r/motion-tabs.jsonSource
1'use client'23import * as React from 'react'45import { motion, type Transition, type HTMLMotionProps } from 'motion/react'67import { cn } from '@/lib/utils'8import { MotionHighlight, MotionHighlightItem } from '@/components/ui/motion-highlight'910type TabsContextType<T extends string> = {11 activeValue: T12 handleValueChange: (value: T) => void13 registerTrigger: (value: T, node: HTMLElement | null) => void14}1516// eslint-disable-next-line @typescript-eslint/no-explicit-any17const TabsContext = React.createContext<TabsContextType<any> | undefined>(undefined)1819function useTabs<T extends string = string>(): TabsContextType<T> {20 const context = React.useContext(TabsContext)2122 if (!context) {23 throw new Error('useTabs must be used within a TabsProvider')24 }2526 return context27}2829type BaseTabsProps = React.ComponentProps<'div'> & {30 children: React.ReactNode31}3233type UnControlledTabsProps<T extends string = string> = BaseTabsProps & {34 defaultValue?: T35 value?: never36 onValueChange?: never37}3839type ControlledTabsProps<T extends string = string> = BaseTabsProps & {40 value: T41 onValueChange?: (value: T) => void42 defaultValue?: never43}4445type TabsProps<T extends string = string> = UnControlledTabsProps<T> | ControlledTabsProps<T>4647function Tabs<T extends string = string>({48 defaultValue,49 value,50 onValueChange,51 children,52 className,53 ...props54}: TabsProps<T>) {55 const [activeValue, setActiveValue] = React.useState<T | undefined>(defaultValue ?? undefined)56 const triggersRef = React.useRef(new Map<string, HTMLElement>())57 const initialSet = React.useRef(false)58 const isControlled = value !== undefined5960 React.useEffect(() => {61 if (!isControlled && activeValue === undefined && triggersRef.current.size > 0 && !initialSet.current) {62 const firstTab = Array.from(triggersRef.current.keys())[0]6364 setActiveValue(firstTab as T)65 initialSet.current = true66 }67 }, [activeValue, isControlled])6869 const registerTrigger = (value: string, node: HTMLElement | null) => {70 if (node) {71 triggersRef.current.set(value, node)7273 if (!isControlled && activeValue === undefined && !initialSet.current) {74 setActiveValue(value as T)75 initialSet.current = true76 }77 } else {78 triggersRef.current.delete(value)79 }80 }8182 const handleValueChange = (val: T) => {83 if (!isControlled) setActiveValue(val)84 else onValueChange?.(val)85 }8687 return (88 <TabsContext.Provider89 value={{90// … truncated
What it pulls in
Other registry items
Files it writes
More from edgecom
All 66 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | edgecom | Components | Free | 2 deps | |
| Alertalert | edgecom | Components | Free | 1 dep | |
| Alert Dialogalert-dialog | edgecom | Components | Free | 1 dep | |
| Avataravatar | edgecom | Components | Free | 1 dep | |
| Badgebadge | edgecom | Components | Free | 2 deps | |
| Bannerbanner | edgecom | Components | Free | 1 dep | |
| Breadcrumbbreadcrumb | edgecom | Components | Free | 2 deps | |
| Buttonbutton | edgecom | Components | Free | 2 deps |
