{ "$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\ntype DitheringIcon = React.ComponentType>\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\n className?: string\n buttonClassName?: string\n}\n\nexport interface HeroDitheringRootProps\n extends Omit, \"title\"> {\n srTitle?: string\n title?: React.ReactNode\n subtitle?: React.ReactNode\n description?: React.ReactNode\n showCta?: boolean\n ctaProps?: Partial\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\n mobileShaderProps?: Partial\n}\n\nexport interface HeroDitheringHeadingProps\n extends Omit, \"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\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\n desktopClassName?: string\n}\n\nexport interface HeroDitheringMobileVisualProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n mobileShaderProps?: Partial\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\n mergedMobileShaderProps: Partial\n}\n\nconst defaultDesktopShaderProps: Partial = {\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 = {\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 ai sdk v6 and{\" \"}\n shadcn/ui.\n Headless, themable, practical.\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 = AI SDK Agents,\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(\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 \n \n

{srTitle}

\n {children}\n \n
\n )\n }\n)\nHeroDitheringRoot.displayName = \"HeroDitheringRoot\"\n\nexport function HeroDitheringContainer({\n className,\n ...props\n}: React.ComponentPropsWithoutRef<\"div\">) {\n return (\n \n )\n}\n\nexport function HeroDitheringContent({\n className,\n ...props\n}: React.ComponentPropsWithoutRef<\"div\">) {\n return (\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 \n {children ?? (\n
\n \n {resolvedTitle}
\n {resolvedSubtitle}\n \n
\n )}\n \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 \n {children ?? (\n \n {resolvedDescription}\n

\n )}\n \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 = \n\n return (\n \n {children ??\n (resolvedRenderCta ? resolvedRenderCta(defaultCta) : defaultCta)}\n \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 \n \n \n {label}\n \n \n \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 \n {resolvedTechStack.map((tech, index) => {\n const Icon = tech.icon\n const defaultBadge = (\n \n {Icon ? : null}\n {tech.name}\n {tech.version ? (\n \n {tech.version}\n \n ) : null}\n \n )\n\n if (resolvedRenderBadge) {\n return (\n \n {resolvedRenderBadge(tech, index, defaultBadge)}\n \n )\n }\n\n return defaultBadge\n })}\n \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