{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hero-dithering",
  "type": "registry:ui",
  "description": "Split-layout hero section with responsive dithering shader visuals, CTA, and tech stack badges",
  "dependencies": [
    "@paper-design/shaders-react"
  ],
  "registryDependencies": [
    "badge",
    "button"
  ],
  "files": [
    {
      "path": "registry/default/ui/hero-dithering.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport type { SVGProps } from \"react\"\nimport { Dithering } from \"@paper-design/shaders-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Badge } from \"@/components/ui/badge\"\nimport { Button } from \"@/components/ui/button\"\n\nconst MemoizedDithering = React.memo(Dithering)\n\ntype DitheringProps = React.ComponentProps<typeof Dithering>\ntype DitheringIcon = React.ComponentType<SVGProps<SVGSVGElement>>\n\nexport interface HeroDitheringTechItem {\n  name: string\n  version?: string\n  icon?: DitheringIcon\n}\n\nexport interface HeroDitheringCTAProps {\n  label: React.ReactNode\n  href: string\n  target?: React.HTMLAttributeAnchorTarget\n  rel?: string\n  onClick?: React.MouseEventHandler<HTMLAnchorElement>\n  className?: string\n  buttonClassName?: string\n}\n\nexport interface HeroDitheringRootProps\n  extends Omit<React.ComponentPropsWithoutRef<\"section\">, \"title\"> {\n  srTitle?: string\n  title?: React.ReactNode\n  subtitle?: React.ReactNode\n  description?: React.ReactNode\n  showCta?: boolean\n  ctaProps?: Partial<HeroDitheringCTAProps>\n  renderCta?: (defaultCta: React.ReactNode) => React.ReactNode\n  showBadges?: boolean\n  techStack?: HeroDitheringTechItem[]\n  renderBadge?: (\n    tech: HeroDitheringTechItem,\n    index: number,\n    defaultBadge: React.ReactNode\n  ) => React.ReactNode\n  desktopShaderProps?: Partial<DitheringProps>\n  mobileShaderProps?: Partial<DitheringProps>\n}\n\nexport interface HeroDitheringHeadingProps\n  extends Omit<React.ComponentPropsWithoutRef<\"div\">, \"title\"> {\n  title?: React.ReactNode\n  subtitle?: React.ReactNode\n  headingClassName?: string\n}\n\nexport interface HeroDitheringDescriptionProps\n  extends React.ComponentPropsWithoutRef<\"div\"> {\n  description?: React.ReactNode\n  descriptionClassName?: string\n}\n\nexport interface HeroDitheringActionsProps\n  extends React.ComponentPropsWithoutRef<\"div\"> {\n  showCta?: boolean\n  ctaProps?: Partial<HeroDitheringCTAProps>\n  renderCta?: (defaultCta: React.ReactNode) => React.ReactNode\n}\n\nexport interface HeroDitheringBadgesProps\n  extends React.ComponentPropsWithoutRef<\"div\"> {\n  showBadges?: boolean\n  techStack?: HeroDitheringTechItem[]\n  renderBadge?: (\n    tech: HeroDitheringTechItem,\n    index: number,\n    defaultBadge: React.ReactNode\n  ) => React.ReactNode\n}\n\nexport interface HeroDitheringVisualProps\n  extends React.ComponentPropsWithoutRef<\"div\"> {\n  desktopShaderProps?: Partial<DitheringProps>\n  desktopClassName?: string\n}\n\nexport interface HeroDitheringMobileVisualProps\n  extends React.ComponentPropsWithoutRef<\"div\"> {\n  mobileShaderProps?: Partial<DitheringProps>\n}\n\nexport interface HeroDitheringProps extends HeroDitheringRootProps {\n  containerClassName?: string\n  contentClassName?: string\n  headingWrapClassName?: string\n  headingClassName?: string\n  descriptionWrapClassName?: string\n  descriptionClassName?: string\n  ctaWrapClassName?: string\n  badgesWrapClassName?: string\n  visualClassName?: string\n  mobileVisualClassName?: string\n}\n\ninterface HeroDitheringContextValue {\n  srTitle: string\n  title: React.ReactNode\n  subtitle: React.ReactNode\n  description: React.ReactNode\n  showCta: boolean\n  mergedCtaProps: HeroDitheringCTAProps\n  renderCta?: (defaultCta: React.ReactNode) => React.ReactNode\n  showBadges: boolean\n  techStack: HeroDitheringTechItem[]\n  renderBadge?: HeroDitheringBadgesProps[\"renderBadge\"]\n  mergedDesktopShaderProps: Partial<DitheringProps>\n  mergedMobileShaderProps: Partial<DitheringProps>\n}\n\nconst defaultDesktopShaderProps: Partial<DitheringProps> = {\n  width: 1280,\n  height: 720,\n  colorBack: \"#000000\",\n  colorFront: \"#00b3ff\",\n  shape: \"swirl\",\n  type: \"4x4\",\n  size: 2,\n  speed: 1,\n  scale: 0.6,\n}\n\nconst defaultMobileShaderProps: Partial<DitheringProps> = {\n  colorBack: \"#00000000\",\n  colorFront: \"#00b3ff\",\n  shape: \"swirl\",\n  size: 2,\n  speed: 0.85,\n  scale: 0.52,\n  type: \"4x4\",\n  style: { height: \"100%\", width: \"100%\" },\n}\n\nconst defaultCtaProps: HeroDitheringCTAProps = {\n  label: \"Check it out today \",\n  href: \"https://aisdkagents.com\",\n  target: \"_blank\",\n  rel: \"noopener noreferrer\",\n}\n\nconst defaultDescription = (\n  <>\n    Full-stack vercel ai sdk patterns for workflows, tool calling, and agent\n    orchestration. Built with{\" \"}\n    <span className=\"font-medium tracking-tight\">ai sdk v6</span> and{\" \"}\n    <span className=\"font-medium tracking-tight\">shadcn/ui</span>.\n    <span className=\"hidden sm:inline\"> Headless, themable, practical.</span>\n  </>\n)\n\nconst defaultTechStack: HeroDitheringTechItem[] = [\n  {\n    name: \"Next.js\",\n    version: \"v16\",\n    icon: NextjsIcon,\n  },\n  {\n    name: \"AI SDK\",\n    version: \"v6\",\n    icon: AISDKIcon,\n  },\n]\n\nconst HeroDitheringContext = React.createContext<\n  HeroDitheringContextValue | undefined\n>(undefined)\n\nfunction useHeroDitheringContext() {\n  const context = React.useContext(HeroDitheringContext)\n  if (!context) {\n    throw new Error(\n      \"HeroDithering components must be used within HeroDitheringRoot\"\n    )\n  }\n  return context\n}\n\nexport function useHeroDithering() {\n  return useHeroDitheringContext()\n}\n\nexport const HeroDitheringRoot = React.forwardRef<\n  HTMLElement,\n  HeroDitheringRootProps\n>(\n  (\n    {\n      className,\n      children,\n      srTitle = \"AI SDK Agents\",\n      title = <span className=\"font-pixel-square\">AI SDK Agents</span>,\n      subtitle = \"Copy and Paste\",\n      description = defaultDescription,\n      showCta = true,\n      ctaProps,\n      renderCta,\n      showBadges = true,\n      techStack = defaultTechStack,\n      renderBadge,\n      desktopShaderProps,\n      mobileShaderProps,\n      ...props\n    },\n    ref\n  ) => {\n    const mergedCtaProps = React.useMemo(\n      () => ({\n        ...defaultCtaProps,\n        ...ctaProps,\n      }),\n      [ctaProps]\n    )\n\n    const mergedDesktopShaderProps = React.useMemo(\n      () => ({\n        ...defaultDesktopShaderProps,\n        ...desktopShaderProps,\n      }),\n      [desktopShaderProps]\n    )\n\n    const mergedMobileShaderProps = React.useMemo(\n      () => ({\n        ...defaultMobileShaderProps,\n        ...mobileShaderProps,\n        style: {\n          ...(defaultMobileShaderProps.style as React.CSSProperties),\n          ...(mobileShaderProps?.style as React.CSSProperties | undefined),\n        },\n      }),\n      [mobileShaderProps]\n    )\n\n    const contextValue = React.useMemo<HeroDitheringContextValue>(\n      () => ({\n        srTitle,\n        title,\n        subtitle,\n        description,\n        showCta,\n        mergedCtaProps,\n        renderCta,\n        showBadges,\n        techStack,\n        renderBadge,\n        mergedDesktopShaderProps,\n        mergedMobileShaderProps,\n      }),\n      [\n        srTitle,\n        title,\n        subtitle,\n        description,\n        showCta,\n        mergedCtaProps,\n        renderCta,\n        showBadges,\n        techStack,\n        renderBadge,\n        mergedDesktopShaderProps,\n        mergedMobileShaderProps,\n      ]\n    )\n\n    return (\n      <HeroDitheringContext.Provider value={contextValue}>\n        <section\n          className={cn(\"relative h-full w-full overflow-hidden\", className)}\n          data-slot=\"hero-dithering-root\"\n          ref={ref}\n          {...props}\n        >\n          <h1 className=\"sr-only\">{srTitle}</h1>\n          {children}\n        </section>\n      </HeroDitheringContext.Provider>\n    )\n  }\n)\nHeroDitheringRoot.displayName = \"HeroDitheringRoot\"\n\nexport function HeroDitheringContainer({\n  className,\n  ...props\n}: React.ComponentPropsWithoutRef<\"div\">) {\n  return (\n    <div\n      className={cn(\n        \"relative z-10 container grid gap-6 pb-16 sm:gap-8 sm:pb-20 lg:grid-cols-[1fr_minmax(300px,500px)] lg:items-center lg:gap-12 lg:pb-24 xl:grid-cols-[1fr_1fr]\",\n        className\n      )}\n      data-slot=\"hero-dithering-container\"\n      {...props}\n    />\n  )\n}\n\nexport function HeroDitheringContent({\n  className,\n  ...props\n}: React.ComponentPropsWithoutRef<\"div\">) {\n  return (\n    <div\n      className={cn(\n        \"flex flex-col justify-center gap-4 text-balance sm:gap-5 sm:px-4 md:px-8 lg:gap-6 lg:pr-0 lg:pl-4 xl:pl-8 2xl:pl-0\",\n        className\n      )}\n      data-slot=\"hero-dithering-content\"\n      {...props}\n    />\n  )\n}\n\nexport function HeroDitheringHeading({\n  className,\n  title,\n  subtitle,\n  headingClassName,\n  children,\n  ...props\n}: HeroDitheringHeadingProps) {\n  const context = useHeroDitheringContext()\n  const resolvedTitle = title ?? context.title\n  const resolvedSubtitle = subtitle ?? context.subtitle\n\n  return (\n    <div\n      className={cn(\"pt-4 text-center sm:pt-6 lg:pt-0 lg:text-left\", className)}\n      data-slot=\"hero-dithering-heading-wrap\"\n      {...props}\n    >\n      {children ?? (\n        <div className=\"relative\">\n          <h2\n            className={cn(\n              \"font-pixel-circle relative mb-0 text-3xl font-medium tracking-[-0.04em] text-balance sm:text-4xl md:text-5xl lg:tracking-[-0.06em] xl:text-6xl 2xl:text-7xl\",\n              headingClassName\n            )}\n            data-slot=\"hero-dithering-heading\"\n          >\n            {resolvedTitle} <br />\n            {resolvedSubtitle}\n          </h2>\n        </div>\n      )}\n    </div>\n  )\n}\n\nexport function HeroDitheringDescription({\n  className,\n  description,\n  descriptionClassName,\n  children,\n  ...props\n}: HeroDitheringDescriptionProps) {\n  const context = useHeroDitheringContext()\n  const resolvedDescription = description ?? context.description\n\n  return (\n    <div\n      className={cn(\n        \"mx-auto max-w-xl pb-2 text-center sm:pb-4 lg:mx-0 lg:max-w-none lg:pb-0 lg:text-left\",\n        className\n      )}\n      data-slot=\"hero-dithering-description-wrap\"\n      {...props}\n    >\n      {children ?? (\n        <p\n          className={cn(\n            \"text-foreground/70 md:text-foreground/80 mt-0 mb-0 font-sans text-sm sm:text-base lg:text-lg xl:text-xl\",\n            descriptionClassName\n          )}\n          data-slot=\"hero-dithering-description\"\n        >\n          {resolvedDescription}\n        </p>\n      )}\n    </div>\n  )\n}\n\nexport function HeroDitheringActions({\n  className,\n  showCta,\n  ctaProps,\n  renderCta,\n  children,\n  ...props\n}: HeroDitheringActionsProps) {\n  const context = useHeroDitheringContext()\n  const shouldShowCta = showCta ?? context.showCta\n  const resolvedCtaProps = { ...context.mergedCtaProps, ...ctaProps }\n  const resolvedRenderCta = renderCta ?? context.renderCta\n\n  if (!shouldShowCta) {\n    return null\n  }\n\n  const defaultCta = <HeroDitheringCTA {...resolvedCtaProps} />\n\n  return (\n    <div\n      className={cn(\"flex justify-center lg:justify-start\", className)}\n      data-slot=\"hero-dithering-cta-wrap\"\n      {...props}\n    >\n      {children ??\n        (resolvedRenderCta ? resolvedRenderCta(defaultCta) : defaultCta)}\n    </div>\n  )\n}\n\nexport function HeroDitheringCTA({\n  label,\n  href,\n  target,\n  rel,\n  onClick,\n  className,\n  buttonClassName,\n}: HeroDitheringCTAProps) {\n  return (\n    <div\n      className={cn(\n        \"flex items-center justify-center gap-4 pb-4 md:pb-0\",\n        className\n      )}\n      data-slot=\"hero-dithering-cta\"\n    >\n      <Button\n        asChild\n        className={cn(\"font-pixel-square\", buttonClassName)}\n        size=\"lg\"\n      >\n        <a href={href} onClick={onClick} rel={rel} target={target}>\n          {label}\n        </a>\n      </Button>\n    </div>\n  )\n}\n\nexport function HeroDitheringBadges({\n  className,\n  showBadges,\n  techStack,\n  renderBadge,\n  ...props\n}: HeroDitheringBadgesProps) {\n  const context = useHeroDitheringContext()\n  const shouldShowBadges = showBadges ?? context.showBadges\n  const resolvedTechStack = techStack ?? context.techStack\n  const resolvedRenderBadge = renderBadge ?? context.renderBadge\n\n  if (!shouldShowBadges) {\n    return null\n  }\n\n  return (\n    <div\n      className={cn(\n        \"flex flex-wrap items-center justify-center gap-2.5\",\n        className\n      )}\n      data-slot=\"hero-dithering-badges\"\n      {...props}\n    >\n      {resolvedTechStack.map((tech, index) => {\n        const Icon = tech.icon\n        const defaultBadge = (\n          <Badge\n            className={cn(\n              \"group relative px-3.5 py-1.5 font-medium transition-all duration-150\",\n              \"border-border/50 bg-card text-card-foreground border\",\n              \"shadow-[0_1px_3px_rgba(0,0,0,0.08)] dark:shadow-[0_1px_3px_rgba(0,0,0,0.3)]\",\n              \"hover:-translate-y-px hover:shadow-[0_2px_8px_rgba(0,0,0,0.12)] dark:hover:shadow-[0_2px_8px_rgba(0,0,0,0.4)]\"\n            )}\n            data-slot=\"hero-dithering-badge\"\n            key={tech.name}\n            variant=\"outline\"\n          >\n            {Icon ? <Icon className=\"mr-1 size-3.5 opacity-80\" /> : null}\n            <span className=\"font-semibold tracking-tight\">{tech.name}</span>\n            {tech.version ? (\n              <span className=\"font-mono text-xs opacity-50\">\n                {tech.version}\n              </span>\n            ) : null}\n          </Badge>\n        )\n\n        if (resolvedRenderBadge) {\n          return (\n            <React.Fragment key={tech.name}>\n              {resolvedRenderBadge(tech, index, defaultBadge)}\n            </React.Fragment>\n          )\n        }\n\n        return defaultBadge\n      })}\n    </div>\n  )\n}\n\nexport function HeroDitheringVisual({\n  className,\n  desktopClassName,\n  desktopShaderProps,\n  ...props\n}: HeroDitheringVisualProps) {\n  const context = useHeroDitheringContext()\n  const resolvedDesktopShaderProps = {\n    ...context.mergedDesktopShaderProps,\n    ...desktopShaderProps,\n  }\n\n  return (\n    <div\n      className={cn(\n        \"relative hidden h-[350px] lg:block lg:h-[400px] xl:h-[500px]\",\n        className\n      )}\n      data-slot=\"hero-dithering-visual\"\n      {...props}\n    >\n      <div\n        className={cn(\n          \"absolute inset-0 flex items-center justify-center overflow-hidden rounded-full\",\n          desktopClassName\n        )}\n        data-slot=\"hero-dithering-desktop\"\n      >\n        <MemoizedDithering {...resolvedDesktopShaderProps} />\n      </div>\n    </div>\n  )\n}\n\nexport function HeroDitheringMobileVisual({\n  className,\n  mobileShaderProps,\n  ...props\n}: HeroDitheringMobileVisualProps) {\n  const context = useHeroDitheringContext()\n  const resolvedMobileShaderProps = {\n    ...context.mergedMobileShaderProps,\n    ...mobileShaderProps,\n    style: {\n      ...(context.mergedMobileShaderProps.style as React.CSSProperties),\n      ...(mobileShaderProps?.style as React.CSSProperties | undefined),\n    },\n  }\n\n  return (\n    <div\n      className={cn(\n        \"pointer-events-none absolute inset-x-0 -bottom-24 -z-10 h-[360px] overflow-hidden lg:hidden\",\n        className\n      )}\n      data-slot=\"hero-dithering-mobile\"\n      {...props}\n    >\n      <div className=\"from-background via-background/95 absolute inset-x-0 top-0 z-10 h-56 bg-gradient-to-b to-transparent\" />\n      <MemoizedDithering {...resolvedMobileShaderProps} />\n    </div>\n  )\n}\n\nexport function HeroDithering({\n  containerClassName,\n  contentClassName,\n  headingWrapClassName,\n  headingClassName,\n  descriptionWrapClassName,\n  descriptionClassName,\n  ctaWrapClassName,\n  badgesWrapClassName,\n  visualClassName,\n  mobileVisualClassName,\n  ...props\n}: HeroDitheringProps) {\n  return (\n    <HeroDitheringRoot {...props}>\n      <HeroDitheringContainer className={containerClassName}>\n        <HeroDitheringContent className={contentClassName}>\n          <HeroDitheringHeading\n            className={headingWrapClassName}\n            headingClassName={headingClassName}\n          />\n          <HeroDitheringDescription\n            className={descriptionWrapClassName}\n            descriptionClassName={descriptionClassName}\n          />\n          <HeroDitheringActions className={ctaWrapClassName} />\n          <div\n            className={cn(\n              \"flex justify-center lg:justify-start\",\n              badgesWrapClassName\n            )}\n            data-slot=\"hero-dithering-badges-wrap\"\n          >\n            <HeroDitheringBadges />\n          </div>\n        </HeroDitheringContent>\n        <HeroDitheringVisual className={visualClassName} />\n      </HeroDitheringContainer>\n      <HeroDitheringMobileVisual className={mobileVisualClassName} />\n    </HeroDitheringRoot>\n  )\n}\n\nexport function AISDKIcon(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      color=\"currentcolor\"\n      data-testid=\"geist-icon\"\n      height=\"1em\"\n      strokeLinejoin=\"round\"\n      viewBox=\"0 0 16 16\"\n      width=\"1em\"\n      {...props}\n    >\n      <title>AI SDK</title>\n      <path\n        d=\"M2.5.5V0h1v.5a2 2 0 002 2H6v1h-.5a2 2 0 00-2 2V6h-1v-.5a2 2 0 00-2-2H0v-1h.5a2 2 0 002-2zM14.5 4.5V5h-1v-.5a1 1 0 00-1-1H12v-1h.5a1 1 0 001-1V1h1v.5a1 1 0 001 1h.5v1h-.5a1 1 0 00-1 1zM8.407 4.93L8.5 4h1l.093.93a5 5 0 004.478 4.477L15 9.5v1l-.93.093a5 5 0 00-4.477 4.478L9.5 16h-1l-.093-.93a5 5 0 00-4.478-4.477L3 10.5v-1l.93-.093A5 5 0 008.406 4.93z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  )\n}\n\nexport function NextjsIcon(props: SVGProps<SVGSVGElement>) {\n  const id = React.useId()\n  const maskId = `${id}-mask`\n  const paint0Id = `${id}-paint0`\n  const paint1Id = `${id}-paint1`\n\n  return (\n    <svg\n      fill=\"none\"\n      height=\"1em\"\n      viewBox=\"0 0 180 180\"\n      width=\"1em\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...props}\n    >\n      <title>Next.js</title>\n      <mask\n        height={180}\n        id={maskId}\n        maskUnits=\"userSpaceOnUse\"\n        style={{\n          maskType: \"alpha\",\n        }}\n        width={180}\n        x={0}\n        y={0}\n      >\n        <circle cx={90} cy={90} fill=\"black\" r={90} />\n      </mask>\n      <g mask={`url(#${maskId})`}>\n        <circle\n          cx={90}\n          cy={90}\n          fill=\"black\"\n          r={87}\n          stroke=\"white\"\n          strokeWidth={6}\n        />\n        <path\n          d=\"M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z\"\n          fill={`url(#${paint0Id})`}\n        />\n        <rect\n          fill={`url(#${paint1Id})`}\n          height={72}\n          width={12}\n          x={115}\n          y={54}\n        />\n      </g>\n      <defs>\n        <linearGradient\n          gradientUnits=\"userSpaceOnUse\"\n          id={paint0Id}\n          x1={109}\n          x2={144.5}\n          y1={116.5}\n          y2={160.5}\n        >\n          <stop stopColor=\"white\" />\n          <stop offset={1} stopColor=\"white\" stopOpacity={0} />\n        </linearGradient>\n        <linearGradient\n          gradientUnits=\"userSpaceOnUse\"\n          id={paint1Id}\n          x1={121}\n          x2={120.799}\n          y1={54}\n          y2={106.875}\n        >\n          <stop stopColor=\"white\" />\n          <stop offset={1} stopColor=\"white\" stopOpacity={0} />\n        </linearGradient>\n      </defs>\n    </svg>\n  )\n}\n\nexport default HeroDithering\n",
      "type": "registry:ui"
    }
  ]
}