Skip to content
← Blocks

Logo Wall

A complete logo wall section, ready to adapt to your product.

Open ↗

Make it yours.

Install the editable source and its dependencies into your React + Tailwind project.

Scroll horizontally for long lines
pnpm dlx shadcn@4.0.8 add http://localhost:3000/r/logo-wall.json

Use it

Scroll horizontally for long lines
"use client";
import { LogoWall } from "@/components/jez-ui/blocks/logo-wall";

export default function Example() {
  return (
    <>
      <LogoWall />
    </>
  );
}

Compose your own

These styled parts are included in the same install. Use children to build your layout; add className only when you want an override.

Scroll horizontally for long lines
"use client";
import {
  LogoWall,
  LogoWallLead,
  LogoWallLogos,
} from "@/components/jez-ui/blocks/logo-wall";

export default function Example() {
  return (
    <LogoWall>
      <LogoWallLead />
      <LogoWallLogos />
    </LogoWall>
  );
}
Scroll horizontally for long lines
import { LogoWall, LogoWallDescription, LogoWallHeader, LogoWallLead, LogoWallLogos } from "@/components/jez-ui/blocks/logo-wall";
Read the composition guide →

Props & types

Scroll horizontally for long lines
export type LogoWallOptions = {
  names?: string[];
  className?: string;
  description?: React.ReactNode;
};

export type LogoWallProps = Omit<
  React.ComponentProps<"section">,
  keyof LogoWallOptions
> &
  LogoWallOptions;

LogoWallProps

Source

View 2 source files

registry/blocks/logo-wall.tsx

Scroll horizontally for long lines
"use client";
import * as React from "react";
import { cn } from "../ui/utils";
export type LogoWallOptions = {
  names?: string[];
  className?: string;
  description?: React.ReactNode;
};
export type LogoWallProps = Omit<
  React.ComponentProps<"section">,
  keyof LogoWallOptions
> &
  LogoWallOptions;

function useLogoWallModel({
  description = "Illustrative brand collection",
  names = ["Forma", "Circa", "Outline", "Common", "Mode"],
  className,
  children,
  ...rootProps
}: LogoWallProps) {
  return { description, names, className, children, rootProps };
}
const LogoWallCompositionContext = React.createContext<ReturnType<
  typeof useLogoWallModel
> | null>(null);
function useLogoWallComposition() {
  const context = React.useContext(LogoWallCompositionContext);
  if (!context) throw new Error("LogoWall parts must be inside LogoWall.");
  return context;
}
export function LogoWall(props: LogoWallProps) {
  const model = useLogoWallModel(props);
  const { className, rootProps, children } = model;
  return (
    <LogoWallCompositionContext.Provider value={model}>
      <section
        {...rootProps}
        className={cn("border-y border-border py-7", className)}
      >
        {children !== undefined ? (
          children
        ) : (
          <>
            <LogoWallLead />
            <LogoWallLogos />
          </>
        )}
      </section>
    </LogoWallCompositionContext.Provider>
  );
}

export function LogoWallDescription({
  className,
  ...props
}: React.ComponentProps<"p">) {
  return (
    <p
      data-slot="logo-wall-description"
      className={cn("mb-5 text-xs text-muted-foreground", className)}
      {...props}
    />
  );
}
export function LogoWallHeader({
  className,
  ...props
}: React.ComponentProps<"div">) {
  return (
    <div
      data-slot="logo-wall-header"
      className={cn(
        "flex flex-wrap items-center justify-between gap-8",
        className,
      )}
      {...props}
    />
  );
}

export function LogoWallLead({
  children,
  ...props
}: Partial<React.ComponentProps<typeof LogoWallDescription>> & {
  children?: React.ReactNode;
}) {
  const { description } = useLogoWallComposition();
  return (
    <LogoWallDescription {...props}>
      {children === undefined ? description : children}
    </LogoWallDescription>
  );
}
export function LogoWallLogos({
  children,
  ...props
}: Partial<React.ComponentProps<typeof LogoWallHeader>> & {
  children?: React.ReactNode;
}) {
  const { names } = useLogoWallComposition();
  return (
    <LogoWallHeader {...props}>
      {children === undefined
        ? names.map((n) => (
            <span key={n} className="font-display text-2xl font-semibold">
              {n}
            </span>
          ))
        : children}
    </LogoWallHeader>
  );
}

registry/ui/utils.ts

Scroll horizontally for long lines
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...values: ClassValue[]) {
  return twMerge(clsx(values));
}

Dependencies

clsx@2.1.1 · tailwind-merge@3.5.0

Accessibility & behaviour

Provide meaningful labels and preserve keyboard focus styles. Check contrast when customising theme colours.

Read the accessibility and performance guide →