blocksection
Logo cloud
A wall of customer logos. Company names are exposed as text, so it reads as a list rather than a run of unlabelled images.
Also ships a motion variant: Logo cloud (motion). The static one is the default.
Preview
Installation
pnpm dlx shadcn@latest add https://facadeui.dev/r/logo-cloud.jsonPulls in container, logo-mark, section, section-header, types, utils. The CLI installs them for you.
Usage
The exact source of the preview above.
import { LogoCloud } from "@registry/sections/logo-cloud"
import { LOGOS } from "./content"
export function Demo() {
return <LogoCloud title="Trusted by teams shipping every day" items={LOGOS} showNames />
}Source
What the CLI copies into your project, byte for byte.
/**
* LogoCloud — a wall of customer or partner logos.
*
* Content-driven: pass `items` and, if you use `next/image` or `next/link`, pass
* those components. The section itself imports no framework.
*
* a11y: the logos are a `<ul>`, because that is what they are — a list of
* companies. Each `LogoMark` exposes its company name as text (visually hidden
* unless `showNames`), so the wall reads as "Northwind, Contoso, …" instead of a
* run of unlabelled images. When `title` is omitted the band renders as a `div`
* rather than adding an unnamed region to the landmark list.
*
* Dependencies: react, @/lib/types, @/lib/utils,
* @/components/ui/container, @/components/ui/logo-mark, @/components/ui/section,
* @/components/ui/section-header.
*/
import type { ElementType } from "react"
import type {
ImageComponent,
LinkComponent,
ListSlotProps,
SectionBaseProps,
} from "@/lib/types"
import { cn, slugId } from "@/lib/utils"
import { Container } from "@/components/ui/container"
import { LogoMark, type LogoItem } from "@/components/ui/logo-mark"
import { Section } from "@/components/ui/section"
import { SectionHeader } from "@/components/ui/section-header"
export interface LogoCloudProps extends SectionBaseProps, ListSlotProps {
items: LogoItem[]
/** Optional heading. Omit for a bare strip under a hero. */
title?: string
eyebrow?: string
description?: string
image?: ImageComponent
link?: LinkComponent
/** Rendered logo height. */
size?: "sm" | "md" | "lg"
/** Show each company name as text beside its mark. */
showNames?: boolean
/** `row` wraps on one line; `grid` gives every logo equal width. */
layout?: "row" | "grid"
/** Desaturate and fade logos until hover or focus. */
muted?: boolean
}
export function LogoCloud({
items,
title,
eyebrow,
description,
image,
link,
size = "md",
showNames = false,
layout = "row",
muted = true,
listAs,
itemAs,
headingLevel = 2,
as,
spacing = "sm",
className,
id,
}: LogoCloudProps) {
const List = (listAs ?? "ul") as ElementType
const Item = (itemAs ?? "li") as ElementType
const titleId = title ? (id ? `${id}-title` : slugId(title)) : undefined
return (
<Section
as={as ?? (title ? "section" : "div")}
spacing={spacing}
labelledBy={titleId}
id={id}
className={className}
>
<Container className="flex flex-col gap-10">
{title ? (
<SectionHeader
align="center"
size="sm"
eyebrow={eyebrow}
title={title}
description={description}
headingLevel={headingLevel}
titleId={titleId}
/>
) : null}
<List
className={cn(
layout === "row"
? "flex flex-wrap items-center justify-center gap-x-10 gap-y-8 sm:gap-x-14"
: "grid grid-cols-2 items-center justify-items-center gap-8 sm:grid-cols-3 lg:grid-cols-5",
)}
>
{items.map((item) => (
<Item key={item.name}>
<LogoMark
{...item}
image={image}
link={link}
size={size}
muted={muted}
showName={showNames}
/>
</Item>
))}
</List>
</Container>
</Section>
)
}Props
LogoCloudProps
Extends SectionBaseProps, ListSlotProps.
| Prop | Type | Default |
|---|---|---|
items*Required | LogoItem[] | — |
titleOptional heading. Omit for a bare strip under a hero. | string | — |
eyebrow | string | — |
description | string | — |
image | ImageComponent | — |
link | LinkComponent | — |
sizeRendered logo height. | "sm" | "md" | "lg" | "md" |
showNamesShow each company name as text beside its mark. | boolean | false |
layout`row` wraps on one line; `grid` gives every logo equal width. | "row" | "grid" | "row" |
mutedDesaturate and fade logos until hover or focus. | boolean | true |