{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "flex-navbar",
  "type": "registry:ui",
  "title": "Flex Navbar",
  "description": "A modern navbar with smooth expansion, media panels, and theme controls.",
  "author": "Ahdeetai <https://aditya.is-cool.dev>",
  "registryDependencies": ["@scrollxui/theme-switch"],
  "dependencies": [
    "motion",
    "clsx",
    "tailwind-merge",
    "lucide-react",
    "next-themes"
  ],
  "files": [
    {
      "type": "registry:ui",
      "path": "components/ui/flex-navbar.tsx",
      "content": "'use client';\nimport React, { useState } from 'react';\nimport { motion, AnimatePresence, Easing } from 'motion/react';\nimport { Laptop, Moon, Sun } from 'lucide-react';\nimport { ThemeSwitch } from '@/components/ui/theme-switch';\nimport { cn } from '@/lib/utils';\n\ninterface NavLink {\n  label: string;\n  href: string;\n}\n\ninterface MediaContent {\n  type: 'image' | 'video';\n  src: string;\n  alt?: string;\n  poster?: string;\n  autoplay?: boolean;\n  link?: string;\n  linkTarget?: '_blank' | '_self';\n}\n\ninterface FlexNavbarProps {\n  logo?: React.ReactNode;\n  brandName?: string;\n  tagline?: string;\n  launchText?: string;\n  navLinks?: NavLink[];\n  media?: MediaContent;\n  mediaButtonText?: string;\n  onMediaClick?: () => void;\n  collapsedWidth?: string;\n  collapsedMaxWidth?: string;\n  collapsedHeight?: string;\n  expandedWidth?: string;\n  expandedMaxWidth?: string;\n  expandedHeight?: string;\n  expandedHeightMobile?: string;\n  animationDuration?: number;\n  animationEasing?: Easing | Easing[];\n  showThemeToggle?: boolean;\n  onExpand?: (isExpanded: boolean) => void;\n}\n\nconst FlexNavbar: React.FC<FlexNavbarProps> = ({\n  logo = (\n    <svg\n      xmlns='http://www.w3.org/2000/svg'\n      viewBox='0 0 24 24'\n      className={cn(\n        'shrink-0 w-6 h-6 sm:w-6 sm:h-6 md:w-7 md:h-7 text-black dark:text-white',\n      )}\n    >\n      <path\n        fill='currentColor'\n        d='M5.999 17a3 3 0 0 1-1.873-.658a2.98 2.98 0 0 1-1.107-2.011a2.98 2.98 0 0 1 .639-2.206l4-5c.978-1.225 2.883-1.471 4.143-.523l1.674 1.254l2.184-2.729a3 3 0 1 1 4.682 3.747l-4 5c-.977 1.226-2.882 1.471-4.143.526l-1.674-1.256l-2.184 2.729A2.98 2.98 0 0 1 5.999 17M10 8a1 1 0 0 0-.781.374l-4 5.001a1 1 0 0 0-.213.734c.03.266.161.504.369.67a.996.996 0 0 0 1.406-.155l3.395-4.244L13.4 12.8c.42.316 1.056.231 1.381-.176l4-5.001a1 1 0 0 0 .213-.734a1 1 0 0 0-.369-.67a.996.996 0 0 0-1.406.156l-3.395 4.242L10.6 8.2A1 1 0 0 0 10 8m9 13H5a1 1 0 1 1 0-2h14a1 1 0 1 1 0 2'\n      />\n    </svg>\n  ),\n  brandName = 'STARTUP',\n  tagline = 'The helpful software company',\n  launchText = 'Launching 2026',\n  navLinks = [\n    { label: 'Technology', href: '#technology' },\n    { label: 'Company', href: '#company' },\n    { label: 'Careers', href: '#careers' },\n    { label: 'Journal', href: '#journal' },\n    { label: 'Beta', href: '#beta' },\n  ],\n  media = {\n    type: 'video',\n    src: 'https://www.pexels.com/download/video/3254009/',\n    alt: 'Our story',\n  },\n  mediaButtonText = 'Our story',\n  onMediaClick,\n  collapsedWidth = '90vw',\n  collapsedMaxWidth = '20rem',\n  collapsedHeight = '3.75rem',\n  expandedWidth = '95vw',\n  expandedMaxWidth = '48.75rem',\n  expandedHeight = '28rem',\n  expandedHeightMobile = '33rem',\n  animationDuration = 0.5,\n  animationEasing = [0.4, 0, 0.2, 1],\n  showThemeToggle = true,\n  onExpand,\n}) => {\n  const [isExpanded, setIsExpanded] = useState(false);\n  const [isMobile, setIsMobile] = useState(false);\n  const [isVideoPlaying, setIsVideoPlaying] = useState(false);\n  const [showMediaControls, setShowMediaControls] = useState(true);\n  const videoRef = React.useRef<HTMLVideoElement>(null);\n\n  React.useEffect(() => {\n    const checkMobile = () => {\n      setIsMobile(window.innerWidth < 768);\n    };\n\n    checkMobile();\n    window.addEventListener('resize', checkMobile);\n    return () => window.removeEventListener('resize', checkMobile);\n  }, []);\n\n  const handleToggle = () => {\n    const newState = !isExpanded;\n    setIsExpanded(newState);\n\n    if (!newState && media.type === 'video' && videoRef.current) {\n      videoRef.current.pause();\n      setIsVideoPlaying(false);\n      setShowMediaControls(true);\n    }\n\n    onExpand?.(newState);\n  };\n\n  const closeNavbar = () => {\n    setIsExpanded(false);\n    onExpand?.(false);\n  };\n\n  const handleMediaClick = () => {\n    if (media.link && (media.type === 'image' || !isVideoPlaying)) {\n      window.open(media.link, media.linkTarget || '_blank');\n      return;\n    }\n\n    if (media.type === 'video' && videoRef.current) {\n      if (isVideoPlaying) {\n        videoRef.current.pause();\n        setIsVideoPlaying(false);\n        setShowMediaControls(true);\n      } else {\n        videoRef.current.play();\n        setIsVideoPlaying(true);\n        setShowMediaControls(false);\n      }\n    }\n    if (onMediaClick) {\n      onMediaClick();\n    }\n  };\n\n  return (\n    <>\n      <AnimatePresence>\n        {isExpanded && (\n          <motion.div\n            initial={{ opacity: 0 }}\n            animate={{ opacity: 1 }}\n            exit={{ opacity: 0 }}\n            transition={{ duration: 0.4 }}\n            className={cn('fixed inset-0 bg-black/50 z-40')}\n            onClick={() => setIsExpanded(false)}\n          />\n        )}\n      </AnimatePresence>\n\n      <motion.nav\n        initial={false}\n        animate={\n          isExpanded\n            ? {\n                width: expandedWidth,\n                maxWidth: expandedMaxWidth,\n                minHeight: isMobile ? expandedHeightMobile : expandedHeight,\n                borderRadius: '0.5rem',\n              }\n            : {\n                width: collapsedWidth,\n                maxWidth: collapsedMaxWidth,\n                height: collapsedHeight,\n                borderRadius: '0.875rem',\n              }\n        }\n        transition={{ duration: animationDuration, ease: animationEasing }}\n        className={cn(\n          'fixed top-4 sm:top-8 left-1/2 -translate-x-1/2 bg-white dark:bg-black shadow-lg z-50 overflow-hidden',\n        )}\n        style={{ top: isMobile ? '1rem' : '2rem' }}\n      >\n        <div\n          className={cn('absolute z-10')}\n          style={{\n            top: isMobile ? '0.75rem' : '1rem',\n            left: isMobile ? '1rem' : '1.5rem',\n            right: isMobile ? '1rem' : '1.5rem',\n          }}\n        >\n          <div className={cn('flex justify-between items-center relative')}>\n            <div className={cn('shrink-0')}>{logo}</div>\n\n            <div\n              className={cn(\n                'absolute left-1/2 -translate-x-1/2 font-medium tracking-tight text-black dark:text-white',\n              )}\n              style={{ fontSize: isMobile ? '1rem' : '1.125rem' }}\n            >\n              {brandName}\n            </div>\n\n            <motion.button\n              onClick={handleToggle}\n              className={cn(\n                'flex items-center justify-center shrink-0 relative',\n              )}\n              style={{ width: '2rem', height: '2rem' }}\n              aria-label={isExpanded ? 'Close menu' : 'Open menu'}\n            >\n              <motion.span\n                className={cn('absolute w-full bg-black dark:bg-white')}\n                style={{ height: '0.125rem' }}\n                animate={{\n                  rotate: isExpanded ? 45 : 0,\n                  y: isExpanded ? 0 : -3,\n                }}\n                transition={{ duration: 0.3 }}\n              />\n              <motion.span\n                className={cn('absolute w-full bg-black dark:bg-white')}\n                style={{ height: '0.125rem' }}\n                animate={{\n                  opacity: isExpanded ? 0 : 1,\n                }}\n                transition={{ duration: 0.2 }}\n              />\n              <motion.span\n                className={cn('absolute w-full bg-black dark:bg-white')}\n                style={{ height: '0.125rem' }}\n                animate={{\n                  rotate: isExpanded ? -45 : 0,\n                  y: isExpanded ? 0 : 3,\n                }}\n                transition={{ duration: 0.3 }}\n              />\n            </motion.button>\n          </div>\n        </div>\n\n        <AnimatePresence>\n          {isExpanded && (\n            <motion.div\n              initial={{ opacity: 0 }}\n              animate={{ opacity: 1 }}\n              exit={{ opacity: 0 }}\n              transition={{ delay: 0.2, duration: 0.4 }}\n              style={{\n                paddingTop: isMobile ? '4rem' : '5rem',\n                paddingLeft: isMobile ? '1.5rem' : '3.75rem',\n                paddingRight: isMobile ? '1.5rem' : '3.75rem',\n                paddingBottom: isMobile ? '2.5rem' : '2.5rem',\n              }}\n            >\n              <div\n                className={cn('flex flex-col')}\n                style={{ gap: isMobile ? '1rem' : '1.5rem' }}\n              >\n                <div\n                  className={cn('flex flex-col md:flex-row')}\n                  style={{ gap: isMobile ? '1.5rem' : '5rem' }}\n                >\n                  <div\n                    className={cn('flex flex-col')}\n                    style={{ gap: isMobile ? '0.75rem' : '1rem' }}\n                  >\n                    {navLinks.map((link, index) => (\n                      <a\n                        key={index}\n                        href={link.href}\n                        onClick={() => {\n                          setTimeout(closeNavbar, 150);\n                        }}\n                        className={cn(\n                          'font-medium text-gray-900 dark:text-gray-50 hover:text-gray-600 dark:hover:text-gray-300 transition-colors whitespace-nowrap',\n                        )}\n                        style={{ fontSize: isMobile ? '1.25rem' : '1.875rem' }}\n                      >\n                        {link.label}\n                      </a>\n                    ))}\n                  </div>\n\n                  <div className={cn('flex-1 min-w-0')}>\n                    <div\n                      className={cn(\n                        'relative rounded-xl overflow-hidden bg-slate-700 dark:bg-slate-800 aspect-video w-full cursor-pointer',\n                      )}\n                      onMouseEnter={() => setShowMediaControls(true)}\n                      onMouseLeave={() =>\n                        isVideoPlaying && setShowMediaControls(false)\n                      }\n                      onClick={() => {\n                        if (media.type === 'image' || !isVideoPlaying) {\n                          handleMediaClick();\n                        } else {\n                          setShowMediaControls(true);\n                        }\n                      }}\n                    >\n                      {media.type === 'video' ? (\n                        <>\n                          <video\n                            ref={videoRef}\n                            src={media.src}\n                            poster={media.poster}\n                            className={cn('w-full h-full object-cover')}\n                            loop\n                            muted\n                            playsInline\n                            preload='auto'\n                            autoPlay={media.autoplay}\n                            onPlay={() => setIsVideoPlaying(true)}\n                            onPause={() => setIsVideoPlaying(false)}\n                          />\n                          <AnimatePresence>\n                            {showMediaControls && (\n                              <motion.button\n                                initial={{ opacity: 0 }}\n                                animate={{ opacity: 1 }}\n                                exit={{ opacity: 0 }}\n                                transition={{ duration: 0.2 }}\n                                onClick={(e: React.MouseEvent) => {\n                                  e.stopPropagation();\n                                  handleMediaClick();\n                                }}\n                                className={cn(\n                                  'absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white/95 dark:bg-white/90 hover:bg-white text-black dark:text-black rounded-full font-medium flex items-center transition-colors',\n                                )}\n                                style={{\n                                  paddingLeft: isMobile ? '1.25rem' : '1.75rem',\n                                  paddingRight: isMobile\n                                    ? '1.25rem'\n                                    : '1.75rem',\n                                  paddingTop: isMobile ? '0.5rem' : '0.75rem',\n                                  paddingBottom: isMobile\n                                    ? '0.5rem'\n                                    : '0.75rem',\n                                  fontSize: isMobile ? '0.75rem' : '0.875rem',\n                                  gap: '0.5rem',\n                                }}\n                              >\n                                <span style={{ fontSize: '0.75rem' }}>\n                                  {isVideoPlaying ? '⏸' : '▶'}\n                                </span>\n                                {mediaButtonText}\n                              </motion.button>\n                            )}\n                          </AnimatePresence>\n                        </>\n                      ) : (\n                        <>\n                          <img\n                            src={media.src}\n                            alt={media.alt || 'Media content'}\n                            className={cn('w-full h-full object-cover')}\n                          />\n                          {media.link && (\n                            <div\n                              className={cn(\n                                'absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-white/95 dark:bg-white/90 hover:bg-white text-black dark:text-black rounded-full font-medium flex items-center transition-colors',\n                              )}\n                              style={{\n                                paddingLeft: isMobile ? '1.25rem' : '1.75rem',\n                                paddingRight: isMobile ? '1.25rem' : '1.75rem',\n                                paddingTop: isMobile ? '0.5rem' : '0.75rem',\n                                paddingBottom: isMobile ? '0.5rem' : '0.75rem',\n                                fontSize: isMobile ? '0.75rem' : '0.875rem',\n                                gap: '0.5rem',\n                              }}\n                            >\n                              {mediaButtonText}\n                            </div>\n                          )}\n                        </>\n                      )}\n                    </div>\n                  </div>\n                </div>\n\n                <div\n                  className={cn(\n                    'flex flex-row justify-between items-center w-full gap-2 sm:gap-4 text-gray-400 dark:text-gray-500 text-xs sm:text-sm',\n                  )}\n                >\n                  <div className={cn('hidden sm:block shrink-0')}>\n                    {tagline}\n                  </div>\n                  <div className={cn('shrink-0')}>{launchText}</div>\n                  {showThemeToggle && (\n                    <div className={cn('shrink-0')}>\n                      <ThemeSwitch\n                        variant='icon-click'\n                        modes={['light', 'dark', 'system']}\n                        icons={[\n                          <Sun key='sun-icon' size={16} />,\n                          <Moon key='moon-icon' size={16} />,\n                          <Laptop key='laptop-icon' size={16} />,\n                        ]}\n                        showInactiveIcons='all'\n                      />\n                    </div>\n                  )}\n                </div>\n              </div>\n            </motion.div>\n          )}\n        </AnimatePresence>\n      </motion.nav>\n    </>\n  );\n};\n\nexport { FlexNavbar };\n"
    },
    {
      "type": "registry:ui",
      "path": "components/ui/theme-switch.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { useTheme } from 'next-themes';\nimport { cn } from '@/lib/utils';\n\ninterface ThemeSwitchProps extends React.HTMLAttributes<HTMLDivElement> {\n  modes?: string[];\n  icons?: React.ReactNode[];\n  showActiveIconOnly?: boolean;\n  showInactiveIcons?: 'all' | 'none' | 'next';\n  variant?: 'default' | 'icon-click';\n}\n\nconst ThemeSwitch = React.forwardRef<HTMLDivElement, ThemeSwitchProps>(\n  (\n    {\n      className,\n      modes = ['light', 'dark', 'system'],\n      icons = [],\n      showActiveIconOnly = false,\n      showInactiveIcons = 'all',\n      variant = 'default',\n      ...props\n    },\n    ref,\n  ) => {\n    const { theme, setTheme } = useTheme();\n\n    const currentModeIndex = React.useMemo(() => {\n      const index = modes.indexOf(theme || '');\n      return index !== -1 ? index : 0;\n    }, [theme, modes]);\n\n    const handleToggle = React.useCallback(() => {\n      const nextIndex = (currentModeIndex + 1) % modes.length;\n      setTheme(modes[nextIndex]);\n    }, [currentModeIndex, modes, setTheme]);\n\n    const [isClient, setIsClient] = React.useState(false);\n    React.useEffect(() => {\n      setIsClient(true);\n    }, []);\n\n    if (!isClient) return null;\n\n    const switchWidth = modes.length === 2 ? 'w-14' : 'w-20';\n\n    const isIconVisible = (index: number) => {\n      if (index === currentModeIndex) return true;\n      switch (showInactiveIcons) {\n        case 'none':\n          return false;\n        case 'next':\n          return index === (currentModeIndex + 1) % modes.length;\n        case 'all':\n        default:\n          return true;\n      }\n    };\n\n    return (\n      <div\n        className={cn(\n          'relative inline-flex h-8 rounded-full border border-input bg-background p-1 shadow-xs transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring',\n          switchWidth,\n          className,\n        )}\n        onClick={variant === 'default' ? handleToggle : undefined}\n        ref={ref}\n        {...props}\n      >\n        {showActiveIconOnly ? (\n          <div className='absolute inset-0 flex items-center justify-center'>\n            <div className='flex h-6 w-6 items-center justify-center rounded-full bg-foreground text-background z-10'>\n              {icons[currentModeIndex]}\n            </div>\n          </div>\n        ) : (\n          <>\n            <div className='flex w-full h-full items-center justify-between'>\n              {icons.map((icon, idx) => {\n                const key = `theme-icon-${idx}`;\n                const visible = isIconVisible(idx);\n\n                return (\n                  <div\n                    key={key}\n                    className={cn(\n                      'flex h-6 w-6 cursor-pointer items-center justify-center rounded-full z-10 transition-opacity duration-200',\n                      currentModeIndex === idx\n                        ? 'text-background'\n                        : 'text-muted-foreground',\n                      visible ? 'opacity-100' : 'opacity-0',\n                    )}\n                    onClick={(e) => {\n                      if (variant === 'icon-click') {\n                        e.stopPropagation();\n                        setTheme(modes[idx]);\n                      }\n                    }}\n                  >\n                    {React.isValidElement(icon)\n                      ? React.cloneElement(icon, { key: `icon-element-${idx}` })\n                      : icon}\n                  </div>\n                );\n              })}\n            </div>\n\n            <div\n              className={cn(\n                'absolute top-1 h-6 w-6 rounded-full bg-foreground transition-all duration-200 ease-in-out',\n                currentModeIndex === 0\n                  ? 'left-1'\n                  : currentModeIndex === 1\n                    ? modes.length === 2\n                      ? 'left-7'\n                      : 'left-[calc(50%-12px)]'\n                    : 'left-[calc(100%-28px)]',\n              )}\n            />\n          </>\n        )}\n      </div>\n    );\n  },\n);\n\nThemeSwitch.displayName = 'ThemeSwitch';\n\nexport { ThemeSwitch };\n"
    },
    {
      "type": "registry:lib",
      "path": "lib/utils.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}"
    }
  ]
}
