{
  "title": "Tabs",
  "description": "A set of layered sections of content-known as tab panels-that are displayed one at a time with layout-aware spring indicator animations.",
  "name": "motion-tabs",
  "dependencies": [
    "motion",
    "@base-ui/react",
    "class-variance-authority",
    "lucide-react"
  ],
  "registryDependencies": [],
  "type": "registry:ui",
  "files": [
    {
      "path": "components/paceui/motion/tabs.tsx",
      "type": "registry:ui",
      "content": "import * as React from \"react\";\n\nimport { Tabs as TabsPrimitive } from \"@base-ui/react/tabs\";\nimport { type VariantProps, cva } from \"class-variance-authority\";\nimport type { Transition } from \"motion/react\";\nimport { AnimatePresence, motion } from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst defaultTransition: Transition = { type: \"spring\", stiffness: 400, damping: 30 };\n\nconst TabsContext = React.createContext<{\n    layoutId?: string;\n    variant?: \"default\" | \"line\" | \"card\";\n    transition?: Transition;\n}>({});\n\nexport interface TabsProps extends TabsPrimitive.Root.Props {\n    layoutId?: string;\n    transition?: Transition;\n}\n\nfunction Tabs({ className, orientation = \"horizontal\", layoutId: customLayoutId, transition, children, ...props }: TabsProps) {\n    const defaultLayoutId = React.useId();\n    const layoutId = customLayoutId ?? defaultLayoutId;\n\n    return (\n        <TabsContext.Provider value={{ layoutId, transition }}>\n            <TabsPrimitive.Root\n                data-slot=\"tabs\"\n                data-orientation={orientation}\n                className={cn(\"group/tabs flex gap-2 data-[orientation=horizontal]:flex-col\", className)}\n                {...props}>\n                {children}\n            </TabsPrimitive.Root>\n        </TabsContext.Provider>\n    );\n}\n\nconst tabsListVariants = cva(\n    \"rounded-md p-[3px] group-data-horizontal/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col relative\",\n    {\n        variants: {\n            variant: {\n                default: \"bg-muted\",\n                line: \"gap-1 bg-transparent\",\n                card: \"bg-card\",\n            },\n        },\n        defaultVariants: {\n            variant: \"default\",\n        },\n    },\n);\n\nexport interface TabsListProps extends TabsPrimitive.List.Props, VariantProps<typeof tabsListVariants> {}\n\nfunction TabsList({ className, variant = \"default\", children, ...props }: TabsListProps) {\n    const parentContext = React.useContext(TabsContext);\n\n    return (\n        <TabsContext.Provider value={{ ...parentContext, variant: variant ?? \"default\" }}>\n            <TabsPrimitive.List\n                data-slot=\"tabs-list\"\n                data-variant={variant}\n                className={cn(tabsListVariants({ variant }), className)}\n                {...props}>\n                {children}\n            </TabsPrimitive.List>\n        </TabsContext.Provider>\n    );\n}\n\nexport interface TabsTriggerProps extends TabsPrimitive.Tab.Props {\n    indicatorClassName?: string;\n    transition?: Transition;\n}\n\nfunction TabsTrigger({ className, indicatorClassName, transition: triggerTransition, children, ...props }: TabsTriggerProps) {\n    const parentContext = React.useContext(TabsContext);\n    const layoutId = parentContext.layoutId;\n    const variant = parentContext.variant ?? \"default\";\n    const transition = triggerTransition ?? parentContext.transition ?? defaultTransition;\n\n    return (\n        <TabsPrimitive.Tab\n            data-slot=\"tabs-trigger\"\n            {...props}\n            render={(tabProps, state) => (\n                <button\n                    {...tabProps}\n                    className={cn(\n                        \"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative z-10 inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-colors outline-none group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n                        state.active && \"text-foreground dark:text-foreground font-medium\",\n                        className,\n                    )}>\n                    {state.active &&\n                        (variant === \"line\" ? (\n                            <motion.div\n                                layoutId={`${layoutId}-indicator`}\n                                className={cn(\n                                    \"bg-foreground absolute group-data-[orientation=horizontal]/tabs:inset-x-0 group-data-[orientation=horizontal]/tabs:-bottom-px group-data-[orientation=horizontal]/tabs:h-0.5 group-data-[orientation=vertical]/tabs:inset-y-0 group-data-[orientation=vertical]/tabs:-right-px group-data-[orientation=vertical]/tabs:w-0.5\",\n                                    indicatorClassName,\n                                )}\n                                transition={transition}\n                            />\n                        ) : (\n                            <motion.div\n                                layoutId={`${layoutId}-pill`}\n                                className={cn(\n                                    \"absolute inset-0 -z-10 rounded-md\",\n                                    variant === \"card\"\n                                        ? \"bg-card border border-border shadow-xs\"\n                                        : \"bg-background dark:bg-input/30 shadow-xs\",\n                                    indicatorClassName,\n                                )}\n                                transition={transition}\n                            />\n                        ))}\n                    <span className=\"relative z-10 flex items-center justify-center gap-1.5\">{children}</span>\n                </button>\n            )}\n        />\n    );\n}\n\nexport interface TabsContentProps extends TabsPrimitive.Panel.Props {}\n\nfunction TabsContent({ className, children, ...props }: TabsContentProps) {\n    return (\n        <TabsPrimitive.Panel\n            data-slot=\"tabs-content\"\n            keepMounted\n            {...props}\n            render={(panelProps, state) => (\n                <div {...panelProps} className={cn(\"flex-1 text-sm outline-none\", className)}>\n                    <AnimatePresence mode=\"wait\" initial={false}>\n                        {!state.hidden && (\n                            <motion.div\n                                key={props.value ?? \"tab-panel\"}\n                                initial={{ opacity: 0, y: 8, filter: \"blur(4px)\" }}\n                                animate={{ opacity: 1, y: 0, filter: \"blur(0px)\" }}\n                                exit={{ opacity: 0, y: -4, filter: \"blur(2px)\" }}\n                                transition={{ duration: 0.2, ease: \"easeOut\" }}>\n                                {children}\n                            </motion.div>\n                        )}\n                    </AnimatePresence>\n                </div>\n            )}\n        />\n    );\n}\n\nexport { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };\n"
    }
  ],
  "mcp": {
    "description": "A set of layered sections of content displayed one at a time. Provides active tab spring indicator morphing and smooth panel cross-fades.",
    "tags": [
      "component",
      "tabs",
      "paceui",
      "animation",
      "navigation"
    ]
  }
}