{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"ecommerce-product-features-before-after-comparison","type":"registry:block","title":"Before After Comparison","files":[{"path":"components/blocks/ecommerce/product-features/before-after-comparison.tsx","content":"import { useState, useRef, MouseEvent, TouchEvent } from 'react';\n\nimport { ArrowLeft, ArrowRight, ChevronLeft, ChevronRight } from 'lucide-react';\nimport { Badge } from '@/components/ui/badge';\nimport { Button } from '@/components/ui/button';\nimport { cn } from '@/lib/utils';\n\ninterface ComparisonFeature {\n  id: string;\n  title: string;\n  beforeImage: string;\n  afterImage: string;\n  beforeLabel: string;\n  afterLabel: string;\n  description: string;\n  improvements: string[];\n}\n\nexport default function BeforeAfterComparison() {\n  const [activeFeature, setActiveFeature] = useState(0);\n  const [sliderPosition, setSliderPosition] = useState(50);\n  const sliderRef = useRef<HTMLDivElement>(null);\n  const isDragging = useRef(false);\n\n  const features: ComparisonFeature[] = [\n    {\n      id: 'camera',\n      title: 'Enhanced Camera System',\n      beforeImage:\n        'https://images.unsplash.com/photo-1564466809058-bf4114d55352?q=80&w=2069&auto=format&fit=crop',\n      afterImage:\n        'https://images.unsplash.com/photo-1584006682522-dc17d6c0d9ac?q=80&w=2073&auto=format&fit=crop',\n      beforeLabel: 'Previous Model',\n      afterLabel: 'New Model',\n      description:\n        'Experience a revolutionary leap in photography with our enhanced camera system, featuring improved low-light performance, higher resolution sensors, and advanced computational photography.',\n      improvements: [\n        '50% larger sensor captures more light for stunning low-light photos',\n        'Improved optical stabilization reduces blur in action shots',\n        'Enhanced portrait mode with depth mapping for professional-looking results',\n        'Computational photography algorithms produce better colors and details',\n      ],\n    },\n    {\n      id: 'design',\n      title: 'Refined Design & Materials',\n      beforeImage:\n        'https://images.unsplash.com/photo-1517420704952-d9f39e95b43e?q=80&w=2070&auto=format&fit=crop',\n      afterImage:\n        'https://images.unsplash.com/photo-1611472173362-3f53dbd65d80?q=80&w=2068&auto=format&fit=crop',\n      beforeLabel: 'Classic Design',\n      afterLabel: 'Modern Design',\n      description:\n        \"We've completely reimagined our product's form factor with premium materials, improved ergonomics, and a sleeker profile that feels better in your hand while maintaining durability.\",\n      improvements: [\n        'Aerospace-grade aluminum provides strength without added weight',\n        'Improved ergonomic grip for extended comfortable use',\n        '30% thinner profile without compromising battery life',\n        'New matte finish resists fingerprints and scratches',\n      ],\n    },\n    {\n      id: 'display',\n      title: 'Revolutionary Display Technology',\n      beforeImage:\n        'https://images.unsplash.com/photo-1506744038136-46273834b3fb?q=10&w=1000&auto=format&fit=crop&blur=10',\n      afterImage:\n        'https://images.unsplash.com/photo-1506744038136-46273834b3fb?q=80&w=2000&auto=format&fit=crop',\n      beforeLabel: 'Standard Display',\n      afterLabel: 'ProMotion XDR',\n      description:\n        'Our new ProMotion XDR display delivers breathtaking color accuracy, incredible brightness, and smoother motion with adaptive refresh rate technology for an immersive viewing experience.',\n      improvements: [\n        '120Hz adaptive refresh rate for smoother scrolling and gameplay',\n        '1000 nits of brightness for easy viewing in direct sunlight',\n        'P3 wide color gamut with 10-bit color depth for true-to-life images',\n        'Reduced blue light emission for comfortable extended viewing',\n      ],\n    },\n  ];\n\n  const handleSliderChange = (clientX: number) => {\n    if (!sliderRef.current) return;\n\n    const rect = sliderRef.current.getBoundingClientRect();\n    const position = ((clientX - rect.left) / rect.width) * 100;\n\n    // Constrain between 0 and 100\n    setSliderPosition(Math.max(0, Math.min(100, position)));\n  };\n\n  const handleMouseDown = (e: MouseEvent) => {\n    isDragging.current = true;\n    handleSliderChange(e.clientX);\n  };\n\n  const handleMouseMove = (e: MouseEvent) => {\n    if (isDragging.current) {\n      handleSliderChange(e.clientX);\n    }\n  };\n\n  const handleMouseUp = () => {\n    isDragging.current = false;\n  };\n\n  const handleTouchStart = (e: TouchEvent) => {\n    isDragging.current = true;\n    handleSliderChange(e.touches[0]!.clientX);\n  };\n\n  const handleTouchMove = (e: TouchEvent) => {\n    if (isDragging.current) {\n      handleSliderChange(e.touches[0]!.clientX);\n    }\n  };\n\n  const handleTouchEnd = () => {\n    isDragging.current = false;\n  };\n\n  const nextFeature = () => {\n    setActiveFeature((prev) => (prev === features.length - 1 ? 0 : prev + 1));\n    setSliderPosition(50); // Reset slider position\n  };\n\n  const prevFeature = () => {\n    setActiveFeature((prev) => (prev === 0 ? features.length - 1 : prev - 1));\n    setSliderPosition(50); // Reset slider position\n  };\n\n  const currentFeature = features[activeFeature]!;\n\n  return (\n    <section className=\"bg-background w-full py-12 md:py-24 lg:py-32\">\n      <div className=\"container mx-auto px-4 md:px-6 2xl:max-w-[1400px]\">\n        <div className=\"mb-8 flex flex-col items-center space-y-4 text-center md:mb-12\">\n          <Badge className=\"px-3.5 py-1.5\">Next Generation</Badge>\n          <h2 className=\"text-3xl font-bold tracking-tighter sm:text-4xl md:text-5xl\">\n            See the difference innovation makes\n          </h2>\n          <p className=\"text-muted-foreground max-w-[600px] md:text-xl/relaxed lg:text-base/relaxed xl:text-xl/relaxed\">\n            Compare our latest advancements with previous generations to\n            experience the remarkable evolution of our products.\n          </p>\n        </div>\n\n        <div className=\"grid items-start gap-8 lg:grid-cols-5 lg:gap-12\">\n          {/* Feature Navigation */}\n          <div className=\"mb-6 flex flex-col space-y-4 lg:col-span-1 lg:mb-0\">\n            <h3 className=\"mb-4 text-lg font-medium\">Innovation Highlights</h3>\n\n            {features.map((feature, idx) => (\n              <button\n                key={feature.id}\n                onClick={() => {\n                  setActiveFeature(idx);\n                  setSliderPosition(50);\n                }}\n                className={cn(\n                  'rounded-lg border px-4 py-3 text-left transition-colors',\n                  activeFeature === idx\n                    ? 'border-primary bg-primary/5 text-primary'\n                    : 'border-border hover:border-primary/50 hover:bg-muted'\n                )}\n              >\n                <div className=\"font-medium\">{feature.title}</div>\n                <div className=\"text-muted-foreground mt-1 line-clamp-2 text-sm\">\n                  {feature.description.substring(0, 80)}...\n                </div>\n              </button>\n            ))}\n\n            <div className=\"mt-4 flex space-x-3 lg:hidden\">\n              <Button variant=\"outline\" size=\"icon\" onClick={prevFeature}>\n                <ChevronLeft className=\"h-4 w-4\" />\n              </Button>\n              <Button variant=\"outline\" size=\"icon\" onClick={nextFeature}>\n                <ChevronRight className=\"h-4 w-4\" />\n              </Button>\n            </div>\n          </div>\n\n          {/* Comparison Slider */}\n          <div className=\"space-y-8 lg:col-span-4\">\n            <div\n              ref={sliderRef}\n              className=\"relative h-[400px] w-full overflow-hidden rounded-lg border select-none\"\n              onMouseDown={handleMouseDown}\n              onMouseMove={handleMouseMove}\n              onMouseUp={handleMouseUp}\n              onMouseLeave={handleMouseUp}\n              onTouchStart={handleTouchStart}\n              onTouchMove={handleTouchMove}\n              onTouchEnd={handleTouchEnd}\n            >\n              {/* Before Image (full width) */}\n              <div className=\"absolute inset-0 h-full w-full\">\n                <img\n                  src={currentFeature.beforeImage}\n                  alt={`Before: ${currentFeature.title}`}\n                  className=\"object-cover\"\n                  sizes=\"(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px\"\n                />\n                <div className=\"bg-background/80 text-foreground absolute bottom-4 left-4 rounded-md px-3 py-1 text-sm font-medium backdrop-blur-sm\">\n                  {currentFeature.beforeLabel}\n                </div>\n              </div>\n\n              {/* After Image (partial width based on slider) */}\n              <div\n                className=\"absolute inset-0 h-full overflow-hidden\"\n                style={{ width: `${sliderPosition}%` }}\n              >\n                <img\n                  src={currentFeature.afterImage}\n                  alt={`After: ${currentFeature.title}`}\n                  className=\"object-cover\"\n                  sizes=\"(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px\"\n                />\n                <div className=\"bg-primary text-primary-foreground absolute right-4 bottom-4 rounded-md px-3 py-1 text-sm font-medium\">\n                  {currentFeature.afterLabel}\n                </div>\n              </div>\n\n              {/* Slider Handle */}\n              <div\n                className=\"absolute top-0 bottom-0 w-1 cursor-ew-resize bg-white\"\n                style={{ left: `${sliderPosition}%`, marginLeft: '-0.5px' }}\n              >\n                <div className=\"absolute top-1/2 flex h-10 w-10 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-white shadow-lg\">\n                  <div className=\"bg-primary flex h-6 w-6 items-center justify-center rounded-full\">\n                    <div className=\"flex items-center space-x-0.5\">\n                      <ArrowLeft className=\"text-primary-foreground h-3 w-3\" />\n                      <ArrowRight className=\"text-primary-foreground h-3 w-3\" />\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n\n            {/* Feature Description */}\n            <div className=\"bg-muted/50 rounded-lg border p-6\">\n              <h3 className=\"mb-4 text-2xl font-bold\">\n                {currentFeature.title}\n              </h3>\n              <p className=\"text-muted-foreground mb-6\">\n                {currentFeature.description}\n              </p>\n\n              <h4 className=\"mb-3 text-sm font-semibold tracking-wide uppercase\">\n                Key Improvements\n              </h4>\n              <ul className=\"space-y-2\">\n                {currentFeature.improvements.map((improvement, idx) => (\n                  <li key={idx} className=\"flex items-start gap-2\">\n                    <div className=\"bg-primary/10 mt-0.5 flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full\">\n                      <div className=\"bg-primary h-2 w-2 rounded-full\" />\n                    </div>\n                    <span>{improvement}</span>\n                  </li>\n                ))}\n              </ul>\n\n              <div className=\"mt-8 flex flex-col gap-4 border-t pt-4 sm:flex-row\">\n                <Button size=\"lg\" asChild>\n                  <a href=\"#\">\n                    Shop new model\n                    <ArrowRight className=\"ml-2 h-4 w-4\" />\n                  </a>\n                </Button>\n                <Button size=\"lg\" variant=\"outline\" asChild>\n                  <a href=\"#\">Compare all models</a>\n                </Button>\n              </div>\n            </div>\n          </div>\n        </div>\n\n        {/* Desktop Navigation */}\n        <div className=\"mt-8 hidden justify-center space-x-3 lg:flex\">\n          <Button\n            variant=\"outline\"\n            onClick={prevFeature}\n            className=\"flex items-center gap-2\"\n          >\n            <ChevronLeft className=\"h-4 w-4\" />\n            Previous feature\n          </Button>\n          <Button\n            variant=\"outline\"\n            onClick={nextFeature}\n            className=\"flex items-center gap-2\"\n          >\n            Next feature\n            <ChevronRight className=\"h-4 w-4\" />\n          </Button>\n        </div>\n      </div>\n    </section>\n  );\n}\n","type":"registry:component","target":"components/blocks/ecommerce/product-features/before-after-comparison.tsx"},{"path":"components/ui/badge.tsx","content":"import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n  \"group/badge inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!\",\n  {\n    variants: {\n      variant: {\n        default: \"bg-primary text-primary-foreground [a]:hover:bg-primary/80\",\n        secondary:\n          \"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80\",\n        destructive:\n          \"bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20\",\n        outline:\n          \"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground\",\n        ghost:\n          \"hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50\",\n        link: \"text-primary underline-offset-4 hover:underline\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n    },\n  }\n)\n\nfunction Badge({\n  className,\n  variant = \"default\",\n  asChild = false,\n  ...props\n}: React.ComponentProps<\"span\"> &\n  VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n  const Comp = asChild ? Slot.Root : \"span\"\n\n  return (\n    <Comp\n      data-slot=\"badge\"\n      data-variant={variant}\n      className={cn(badgeVariants({ variant }), className)}\n      {...props}\n    />\n  )\n}\n\nexport { Badge, badgeVariants }\n","type":"registry:ui","target":"components/ui/badge.tsx"},{"path":"components/ui/button.tsx","content":"import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n  \"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n  {\n    variants: {\n      variant: {\n        default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n        outline:\n          \"border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n        secondary:\n          \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n        ghost:\n          \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n        destructive:\n          \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n        link: \"text-primary underline-offset-4 hover:underline\",\n      },\n      size: {\n        default:\n          \"h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n        xs: \"h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n        sm: \"h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5\",\n        lg: \"h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n        icon: \"size-9\",\n        \"icon-xs\":\n          \"size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3\",\n        \"icon-sm\":\n          \"size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md\",\n        \"icon-lg\": \"size-10\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      size: \"default\",\n    },\n  }\n)\n\nfunction Button({\n  className,\n  variant = \"default\",\n  size = \"default\",\n  asChild = false,\n  ...props\n}: React.ComponentProps<\"button\"> &\n  VariantProps<typeof buttonVariants> & {\n    asChild?: boolean\n  }) {\n  const Comp = asChild ? Slot.Root : \"button\"\n\n  return (\n    <Comp\n      data-slot=\"button\"\n      data-variant={variant}\n      data-size={size}\n      className={cn(buttonVariants({ variant, size, className }))}\n      {...props}\n    />\n  )\n}\n\nexport { Button, buttonVariants }\n","type":"registry:ui","target":"components/ui/button.tsx"}],"description":"A slider that wipes between two product images so buyers see the difference at a glance. Ideal for skincare, editing tools, or cleaning results.","dependencies":["class-variance-authority","lucide-react","radix-ui"]}