{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "faq-accordion",
  "dependencies": [],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "./registry/components/accordion/faq.tsx",
      "content": "'use client';\nimport { Plus } from 'lucide-react';\nimport { AnimatePresence, motion } from 'motion/react';\nimport React, { useState } from 'react';\n\nconst tabs = [\n  {\n    title: 'How do UI components improve UX?',\n    description:\n      'UI components can improve UX by providing familiar, consistent interactions that make it easy for users to navigate and interact with an application.',\n    imageUrl:\n      'https://images.unsplash.com/photo-1709949908058-a08659bfa922?q=80&w=1200&auto=format',\n  },\n  {\n    title: 'Common UI component design challenges?',\n    description:\n      'Some common challenges include maintaining consistency across different devices and screen sizes, ensuring compatibility with various browsers and assistive technologies, and balancing flexibility with ease of use.',\n    imageUrl: 'https://images.unsplash.com/photo-1548192746-dd526f154ed9?q=80&w=1200&auto=format',\n  },\n  {\n    title: 'Ensuring UI component responsiveness?',\n    description:\n      '     Developers can ensure the responsiveness of UI components by using techniques such as fluid layouts, flexible grids, and media queries to adapt the components to different screen sizes and orientations.',\n    imageUrl:\n      'https://images.unsplash.com/photo-1693581176773-a5f2362209e6?q=80&w=1200&auto=format',\n  },\n];\nfunction SingleLayout() {\n  const [activeIndex, setActiveIndex] = useState<number | null>(0);\n  const [activeItem, setActiveItem] = useState<\n    | {\n        title: string;\n        description: string;\n        imageUrl: string;\n      }\n    | undefined\n  >(tabs[0]);\n\n  const handleClick = async (index: number) => {\n    setActiveIndex(activeIndex === index ? null : index);\n    const newActiveItem = tabs.find((_, i) => i === index);\n    setActiveItem(newActiveItem);\n  };\n\n  return (\n    <>\n      <div className='container mx-auto pb-10 pt-2'>\n        <h1 className='uppercase text-center text-4xl font-bold pt-2 pb-4'>FAQ</h1>\n        <div className='h-fit border rounded-lg p-2 dark:bg-[#111111] bg-[#F2F2F2]'>\n          {tabs.map((tab, index) => (\n            <motion.div\n              key={tab.title}\n              className={`overflow-hidden ${index !== tabs.length - 1 ? 'border-b' : ''}`}\n              onClick={() => handleClick(index)}\n            >\n              <button\n                className={`p-3 px-2 w-full cursor-pointer sm:text-base text-xs items-center transition-all font-semibold dark:text-white text-black   flex gap-2 \n               `}\n              >\n                <Plus\n                  className={`${\n                    activeIndex === index ? 'rotate-45' : 'rotate-0 '\n                  } transition-transform ease-in-out w-5 h-5  dark:text-neutral-200 text-neutral-600`}\n                />\n                {tab.title}\n              </button>\n              <AnimatePresence mode='sync'>\n                {activeIndex === index && (\n                  <motion.div\n                    initial={{ height: 0, opacity: 0 }}\n                    animate={{ height: 'auto', opacity: 1 }}\n                    exit={{ height: 0, opacity: 0 }}\n                    transition={{\n                      duration: 0.3,\n                      ease: 'easeInOut',\n                      delay: 0.14,\n                    }}\n                  >\n                    <p\n                      className={`dark:text-white text-black p-3 xl:text-base sm:text-sm text-xs pt-0 w-[90%]`}\n                    >\n                      {tab.description}\n                    </p>\n                  </motion.div>\n                )}\n              </AnimatePresence>\n            </motion.div>\n          ))}\n        </div>\n      </div>\n    </>\n  );\n}\n\nexport default SingleLayout;\n",
      "type": "registry:component"
    },
    {
      "path": "./components/ui/accordion.tsx",
      "content": "'use client';\n\nimport { cn } from '@/lib/utils';\nimport { ChevronDown } from 'lucide-react';\nimport { AnimatePresence, motion } from 'motion/react';\nimport React, { type ReactNode, useCallback } from 'react';\n\n/**\n * Interface for AccordionContext values\n */\ninterface AccordionContextType {\n  /**\n   * Whether the accordion item is active\n   */\n  isActive?: boolean;\n  /**\n   * The value of the accordion item\n   */\n  value?: string;\n  /**\n   * Function to change the active index\n   */\n  onChangeIndex?: (value: string) => void;\n}\n\n/**\n * Context for accordion components\n */\nconst AccordionContext = React.createContext<AccordionContextType>({});\n/**\n * Hook to use the accordion context\n */\nconst useAccordion = () => React.useContext(AccordionContext);\n\n/**\n * Container component for accordion items\n */\nexport function AccordionContainer({\n  children,\n  className,\n}: {\n  children: ReactNode;\n  className?: string;\n}) {\n  return <div className={cn('grid grid-cols-2 gap-1', className)}>{children}</div>;\n}\n\n/**\n * Wrapper component for accordion items\n */\nexport function AccordionWrapper({ children }: { children: ReactNode }) {\n  return <div>{children}</div>;\n}\n\n/**\n * Interface for Accordion props\n */\ninterface AccordionProps {\n  /**\n   * Children components\n   */\n  children: ReactNode;\n  /**\n   * Whether multiple items can be active at the same time\n   */\n  multiple?: boolean;\n  /**\n   * Default active index\n   */\n  defaultValue?: string | string[];\n}\n\n/**\n * Accordion component\n */\nexport function Accordion({ children, multiple, defaultValue }: AccordionProps) {\n  /**\n   * State for active index\n   */\n  const [activeIndex, setActiveIndex] = React.useState<string | string[] | null>(\n    multiple ? (Array.isArray(defaultValue) ? defaultValue : []) : defaultValue || null\n  );\n\n  /**\n   * Function to change the active index\n   */\n  const onChangeIndex = useCallback(\n    (value: string) => {\n      setActiveIndex((currentActiveIndex) => {\n        if (!multiple) {\n          return value === currentActiveIndex ? null : value;\n        }\n\n        if (Array.isArray(currentActiveIndex)) {\n          if (currentActiveIndex.includes(value)) {\n            return currentActiveIndex.filter((i) => i !== value);\n          }\n          return [...currentActiveIndex, value];\n        }\n\n        return [value];\n      });\n    },\n    [multiple]\n  );\n\n  return React.Children.map(children, (child) => {\n    if (!React.isValidElement(child)) return null;\n\n    const childProps = child.props as { value: string };\n    const value = childProps.value;\n    const isActive = multiple\n      ? Array.isArray(activeIndex) && activeIndex.includes(value)\n      : activeIndex === value;\n\n    return (\n      <AccordionContext.Provider value={{ isActive, value, onChangeIndex }}>\n        {child}\n      </AccordionContext.Provider>\n    );\n  });\n}\n\n/**\n * Interface for AccordionItem props\n */\ninterface AccordionItemProps {\n  /**\n   * Children components\n   */\n  children: ReactNode;\n  /**\n   * Value of the accordion item\n   */\n  value: string;\n  className?: string;\n}\n\n/**\n * Accordion item component\n */\nexport function AccordionItem({ children, value, className }: AccordionItemProps) {\n  const { isActive } = useAccordion();\n\n  return (\n    <div\n      data-active={isActive || undefined}\n      className={cn(\n        'rounded-lg overflow-hidden mb-2 group border border-neutral-200 dark:border-neutral-800',\n        className\n      )}\n    >\n      {children}\n    </div>\n  );\n}\n\n/**\n * Interface for AccordionHeader props\n */\ninterface AccordionHeaderProps {\n  /**\n   * Children components\n   */\n  children: ReactNode;\n  /**\n   * Icon component\n   */\n  customIcon?: boolean;\n  className?: string;\n}\n\n/**\n * Accordion header component\n */\nexport function AccordionHeader({ children, customIcon, className }: AccordionHeaderProps) {\n  const { isActive, value, onChangeIndex } = useAccordion();\n\n  const handleClick = useCallback(() => {\n    if (value && onChangeIndex) {\n      onChangeIndex(value);\n    }\n  }, [onChangeIndex, value]);\n\n  return (\n    <motion.button\n      type='button'\n      data-active={isActive || undefined}\n      aria-expanded={isActive}\n      className={cn(\n        'p-4 cursor-pointer w-full transition-all font-semibold text-neutral-500 dark:data-active:text-neutral-200 data-active:text-neutral-800 dark:data-active:bg-neutral-800 data-active:bg-neutral-200 hover:bg-neutral-100 hover:text-black flex justify-between gap-2 items-center text-left',\n        className\n      )}\n      onClick={handleClick}\n    >\n      {children}\n      {!customIcon && (\n        <ChevronDown\n          className={cn(\n            'transition-transform shrink-0 text-neutral-500 dark:text-neutral-400',\n            isActive ? 'rotate-180' : 'rotate-0'\n          )}\n          aria-hidden='true'\n        />\n      )}\n    </motion.button>\n  );\n}\n/**\n * Interface for AccordionPanel props\n */\ninterface AccordionPanelProps {\n  /**\n   * Children components\n   */\n  children: ReactNode;\n  /**\n   * className\n   */\n  className?: string;\n  /**\n   * article className\n   */\n  articleClassName?: string;\n}\n\n/**\n * Accordion panel component\n */\nexport function AccordionPanel({ children, className, articleClassName }: AccordionPanelProps) {\n  const { isActive, value } = useAccordion();\n\n  return (\n    <AnimatePresence initial={true}>\n      {isActive && (\n        <motion.div\n          data-active={isActive || undefined}\n          role='region'\n          id={`accordion-panel-${value}`}\n          aria-labelledby={`accordion-header-${value}`}\n          initial={{ height: 0, overflow: 'hidden' }}\n          animate={{ height: 'auto', overflow: 'hidden' }}\n          exit={{ height: 0 }}\n          transition={{ type: 'spring', duration: 0.3, bounce: 0 }}\n          className={cn(\n            'bg-neutral-100 dark:bg-neutral-900 px-2 data-active:bg-neutral-200 dark:data-active:bg-neutral-800 text-black dark:text-white',\n            className\n          )}\n        >\n          <motion.div\n            initial={{ clipPath: 'polygon(0 0, 100% 0, 100% 0, 0 0)' }}\n            animate={{ clipPath: 'polygon(0 0, 100% 0, 100% 100%, 0% 100%)' }}\n            exit={{\n              clipPath: 'polygon(0 0, 100% 0, 100% 0, 0 0)',\n            }}\n            transition={{\n              type: 'spring',\n              duration: 0.4,\n              bounce: 0,\n            }}\n            className={cn('px-3 bg-transparent pb-4 space-y-2', articleClassName)}\n          >\n            {children}\n          </motion.div>\n        </motion.div>\n      )}\n    </AnimatePresence>\n  );\n}\n",
      "type": "registry:component"
    }
  ],
  "type": "registry:component"
}