{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"logo-cloud","type":"registry:ui","title":"LogoCloud","description":"Logo display with animated marquee, static grid, and icon variants","author":"fancy-ui <https://fancy-ui.rama.app>","categories":["data-display"],"registryDependencies":["https://fancy-ui.rama.app/r/utils.json"],"files":[{"path":"react/src/components/logo-cloud/AnimatedLogoCloud.tsx","content":"\"use client\";\n\nimport { cn } from \"../../utils\";\nimport \"./logo-cloud.css\";\n\nexport interface Logo {\n\tname: string;\n\tpath: string;\n}\n\nexport interface AnimatedLogoCloudProps {\n\t/** Additional CSS classes for the scrolling container */\n\tclassName?: string;\n\t/** Optional title displayed above the logos */\n\ttitle?: string;\n\t/** Array of logos with name and image path */\n\tlogos?: Logo[];\n}\n\nexport function AnimatedLogoCloud({ className, title, logos = [] }: AnimatedLogoCloudProps) {\n\treturn (\n\t\t<div className=\"w-full py-12\">\n\t\t\t<div className=\"mx-auto w-full px-4 md:px-8\">\n\t\t\t\t{title ? (\n\t\t\t\t\t<div className=\"text-muted-foreground text-center font-medium\">{title}</div>\n\t\t\t\t) : null}\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\"logo-cloud-mask group relative mt-6 flex gap-6 overflow-hidden p-2\",\n\t\t\t\t\t\tclassName\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{/*\n\t\t\t\t\t\tFive identical tracks, because a seamless marquee needs the\n\t\t\t\t\t\tstrip to be wider than the viewport. Only the first one is\n\t\t\t\t\t\treal content: the other four are the same logos again, so\n\t\t\t\t\t\tthey are hidden from assistive tech (`aria-hidden` plus an\n\t\t\t\t\t\tempty `alt`, since an image with a non-empty alt inside an\n\t\t\t\t\t\taria-hidden subtree can still surface). Without that, a\n\t\t\t\t\t\tscreen reader reads the whole roster five times over.\n\t\t\t\t\t*/}\n\t\t\t\t\t{Array.from({ length: 5 }).map((_, i) => (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\tclassName=\"logo-cloud-scroll flex shrink-0 flex-row justify-around gap-6\"\n\t\t\t\t\t\t\taria-hidden={i > 0 ? \"true\" : undefined}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{logos.map((logo, j) => (\n\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\tkey={j}\n\t\t\t\t\t\t\t\t\tsrc={logo.path}\n\t\t\t\t\t\t\t\t\talt={i === 0 ? logo.name : \"\"}\n\t\t\t\t\t\t\t\t\tclassName=\"h-10 w-28 px-2 brightness-0 dark:invert\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","type":"registry:ui","target":"@ui/fancy/components/logo-cloud/AnimatedLogoCloud.tsx"},{"path":"react/src/components/logo-cloud/IconLogoCloud.tsx","content":"\"use client\";\n\nimport { cn } from \"../../utils\";\nimport type { Logo } from \"./AnimatedLogoCloud\";\n\nexport interface IconLogoCloudProps {\n\t/** Additional CSS classes for the grid container */\n\tclassName?: string;\n\t/** Optional title displayed above the logos */\n\ttitle?: string;\n\t/** Array of logos with name and image path */\n\tlogos?: Logo[];\n}\n\nexport function IconLogoCloud({ className, title, logos = [] }: IconLogoCloudProps) {\n\treturn (\n\t\t<div className=\"w-full py-12\">\n\t\t\t<div className=\"flex w-full flex-col items-center justify-center gap-6 px-4 md:px-8\">\n\t\t\t\t{title ? <div className=\"text-muted-foreground font-medium\">{title}</div> : null}\n\t\t\t\t<div className={cn(\"grid grid-cols-3 md:grid-cols-8 lg:grid-cols-8\", className)}>\n\t\t\t\t\t{logos.map((logo, i) => (\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\tsrc={logo.path}\n\t\t\t\t\t\t\talt={logo.name}\n\t\t\t\t\t\t\tclassName=\"h-7 w-12 px-2 brightness-0 dark:invert\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","type":"registry:ui","target":"@ui/fancy/components/logo-cloud/IconLogoCloud.tsx"},{"path":"react/src/components/logo-cloud/StaticLogoCloud.tsx","content":"\"use client\";\n\nimport type { CSSProperties } from \"react\";\nimport { cn } from \"../../utils\";\nimport type { Logo } from \"./AnimatedLogoCloud\";\n\nexport interface Wordmark {\n\t/** The brand/wordmark text */\n\tname: string;\n\t/** Font size in pixels */\n\tsize: number;\n\t/** Font weight */\n\tweight: 400 | 700 | 900;\n\t/** Letter-spacing in pixels */\n\ttracking?: number;\n\t/** Render in italic */\n\titalic?: boolean;\n\t/** Use a serif font stack instead of the default */\n\tserif?: boolean;\n\t/** CSS text-transform */\n\ttransform?: \"uppercase\" | \"lowercase\";\n}\n\nexport interface StaticLogoCloudProps {\n\t/** Additional CSS classes for the grid container */\n\tclassName?: string;\n\t/** Optional title displayed above the logos */\n\ttitle?: string;\n\t/** Array of logos with name and image path */\n\tlogos?: Logo[];\n\t/** When provided, renders a static typographic row of wordmarks instead of image logos */\n\twordmarks?: Wordmark[];\n}\n\nexport function StaticLogoCloud({\n\tclassName,\n\ttitle,\n\tlogos = [],\n\twordmarks,\n}: StaticLogoCloudProps) {\n\treturn (\n\t\t<div className=\"w-full py-12\">\n\t\t\t<div className=\"flex w-full flex-col items-center justify-center gap-4 px-4 md:px-8\">\n\t\t\t\t{title ? (\n\t\t\t\t\t<div className=\"text-muted-foreground font-medium uppercase\">{title}</div>\n\t\t\t\t) : null}\n\t\t\t\t{wordmarks ? (\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\"flex flex-wrap items-center justify-around gap-x-9 gap-y-5\",\n\t\t\t\t\t\t\tclassName\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{wordmarks.map((mark, i) => {\n\t\t\t\t\t\t\tconst style: CSSProperties = {\n\t\t\t\t\t\t\t\tfontSize: `${mark.size}px`,\n\t\t\t\t\t\t\t\tfontWeight: mark.weight,\n\t\t\t\t\t\t\t\tletterSpacing: mark.tracking !== undefined ? `${mark.tracking}px` : undefined,\n\t\t\t\t\t\t\t\tfontStyle: mark.italic ? \"italic\" : undefined,\n\t\t\t\t\t\t\t\tfontFamily: mark.serif ? 'Georgia, \"Times New Roman\", serif' : undefined,\n\t\t\t\t\t\t\t\ttextTransform: mark.transform,\n\t\t\t\t\t\t\t\topacity: 0.85,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t<span key={i} style={style}>\n\t\t\t\t\t\t\t\t\t{mark.name}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t})}\n\t\t\t\t\t</div>\n\t\t\t\t) : (\n\t\t\t\t\t<div className={cn(\"grid grid-cols-3 gap-x-4 md:grid-cols-5 lg:grid-cols-8\", className)}>\n\t\t\t\t\t\t{logos.map((logo, i) => (\n\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\tkey={i}\n\t\t\t\t\t\t\t\tsrc={logo.path}\n\t\t\t\t\t\t\t\talt={logo.name}\n\t\t\t\t\t\t\t\tclassName=\"h-10 w-28 px-2 brightness-0 dark:invert\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","type":"registry:ui","target":"@ui/fancy/components/logo-cloud/StaticLogoCloud.tsx"},{"path":"react/src/components/logo-cloud/index.ts","content":"\"use client\";\n\nexport { AnimatedLogoCloud } from \"./AnimatedLogoCloud\";\nexport type { AnimatedLogoCloudProps, Logo } from \"./AnimatedLogoCloud\";\nexport { StaticLogoCloud } from \"./StaticLogoCloud\";\nexport type { StaticLogoCloudProps, Wordmark } from \"./StaticLogoCloud\";\nexport { IconLogoCloud } from \"./IconLogoCloud\";\nexport type { IconLogoCloudProps } from \"./IconLogoCloud\";\n","type":"registry:ui","target":"@ui/fancy/components/logo-cloud/index.ts"},{"path":"react/src/components/logo-cloud/logo-cloud.css","content":".logo-cloud-mask {\n\tmask-image: linear-gradient(to left, transparent 0%, black 20%, black 80%, transparent 95%);\n}\n\n.logo-cloud-scroll {\n\tanimation: logo-cloud-scroll 30s linear infinite;\n}\n\n@keyframes logo-cloud-scroll {\n\t0% {\n\t\ttransform: translateX(0);\n\t}\n\t100% {\n\t\ttransform: translateX(calc(-100% - 1.5rem));\n\t}\n}\n","type":"registry:ui","target":"@ui/fancy/components/logo-cloud/logo-cloud.css"}],"meta":{"license":"MIT","package":"fancy-ui-react","version":"0.7.0","source":"https://fancy-ui.rama.app/docs/components/logo-cloud?framework=react"}}