{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"dusk-testimonials-2","type":"registry:block","title":"Testimonials 2","description":"Tailark Dusk testimonials variant 2 block","registryDependencies":["@tailark-oss/dusk-button","@tailark-oss/core-claude-ai","@tailark-oss/core-gemini","@tailark-oss/core-openai"],"meta":{"aspect-ratio":"90/42","width":686,"height":320},"files":[{"path":"dusk/blocks/testimonials/two.tsx","type":"registry:component","target":"@components/testimonials-2.tsx","content":"'use client'\n\nimport { Button } from '@/components/ui/button'\nimport { ClaudeAI } from '@/components/ui/svgs/claude-ai'\nimport { Gemini } from '@/components/ui/svgs/gemini'\nimport { Openai } from '@/components/ui/svgs/openai'\nimport { useState, type ComponentType, type SVGProps } from 'react'\nimport { AnimatePresence, motion } from 'motion/react'\n\nconst testimonials: {\n    quote: string\n    highlight: string\n    author: string\n    role: string\n    Logo: ComponentType\n}[] = [\n    {\n        quote: 'Tailark helped our revenue team move from scattered updates to one shared CRM view.',\n        highlight: 'We finally know which accounts need attention before deals stall.',\n        author: 'Maya Patel',\n        role: 'VP of Revenue, Claude',\n        Logo: ClaudeAI,\n    },\n    {\n        quote: 'Our account managers use Tailark every morning to review pipeline health, open tasks, and customer history.',\n        highlight: 'The workflow feels focused without hiding the details teams need.',\n        author: 'Ethan Brooks',\n        role: 'Head of Customer Operations, Gemini',\n        Logo: Gemini,\n    },\n    {\n        quote: 'Tailark gives our sales and success teams a cleaner way to coordinate follow-up across every account.',\n        highlight: 'It turns customer signals into clear next steps.',\n        author: 'Sofia Ramirez',\n        role: 'Revenue Operations Lead, OpenAI',\n        Logo: Openai,\n    },\n]\n\nexport default function Testimonials() {\n    const [activeIndex, setActiveIndex] = useState(0)\n    const activeTestimonial = testimonials[activeIndex]\n    const Logo = activeTestimonial.Logo\n\n    const previousTestimonial = () => {\n        setActiveIndex((index) => (index - 1 + testimonials.length) % testimonials.length)\n    }\n\n    const nextTestimonial = () => {\n        setActiveIndex((index) => (index + 1) % testimonials.length)\n    }\n\n    return (\n        <section className=\"py-16 md:py-20\">\n            <div className=\"mx-auto max-w-5xl px-6\">\n                <div className=\"mx-auto max-w-3xl\">\n                    <div className=\"mb-20 flex gap-2\">\n                        <Button\n                            variant=\"outline\"\n                            size=\"sm\"\n                            className=\"h-7 px-4\"\n                            aria-label=\"read previous testimonial\"\n                            onClick={previousTestimonial}\n                            disabled={activeIndex === 0}\n                        >\n                            <ArrowIcon className=\"size-3!\" />\n                        </Button>\n                        <Button\n                            variant=\"outline\"\n                            size=\"sm\"\n                            className=\"h-7 px-4\"\n                            aria-label=\"read next testimonial\"\n                            onClick={nextTestimonial}\n                            disabled={activeIndex === testimonials.length - 1}\n                        >\n                            <ArrowIcon className=\"size-3! rotate-180\" />\n                        </Button>\n                    </div>\n                    <AnimatePresence mode=\"popLayout\">\n                        <motion.div\n                            key={activeIndex}\n                            initial={{ opacity: 0 }}\n                            animate={{ opacity: 1 }}\n                            exit={{ opacity: 0 }}\n                            transition={{ duration: 0.3 }}\n                        >\n                            <p className=\"text-muted-foreground mb-20 text-2xl font-medium leading-snug md:text-4xl md:leading-tight\">\n                                {activeTestimonial.quote} <span className=\"rounded bg-emerald-500/10 px-1.5 text-emerald-500\">{activeTestimonial.highlight}</span>\n                            </p>\n                        </motion.div>\n\n                        <motion.div\n                            key={`${activeIndex}-author`}\n                            initial={{ opacity: 0 }}\n                            animate={{ opacity: 1 }}\n                            exit={{ opacity: 0 }}\n                            transition={{ duration: 0.3 }}\n                            className=\"flex items-center gap-4\"\n                        >\n                            <Logo className=\"size-10\" />\n                            <div className=\"border-l pl-4\">\n                                <p className=\"font-medium\">{activeTestimonial.author}</p>\n                                <p className=\"text-muted-foreground text-sm\">{activeTestimonial.role}</p>\n                            </div>\n                        </motion.div>\n                    </AnimatePresence>\n                </div>\n            </div>\n        </section>\n    )\n}\n\nconst ArrowIcon = (props: SVGProps) => {\n    return (\n        <svg\n            {...props}\n            width=\"20\"\n            height=\"16\"\n            viewBox=\"0 0 20 16\"\n            fill=\"none\"\n            xmlns=\"http://www.w3.org/2000/svg\"\n        >\n            <path\n                d=\"M8 1L1 8L8 15M1 8H19\"\n                stroke=\"currentColor\"\n                strokeWidth=\"2\"\n                strokeLinecap=\"round\"\n                strokeLinejoin=\"round\"\n            />\n        </svg>\n    )\n}\n"}]}