Page Sections

Team + Logo Wall

A team member grid that staggers in, paired with an infinitely scrolling customer logo marquee — a good fit for the trust block on an about page or a home page.

This is a WebberUI Pro component

The install command below needs a licence to run; without one it returns 401.

How to install Pro components →See the plans →

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add "https://webberui.com/r/team-logo-wall.en.json?t=<install token>"

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

4
40
Active edited usageDefault props
<TeamLogoWall/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add "https://webberui.com/r/team-logo-wall.en.json?t=<install token>"

Or, once registries are configured in components.json, install it as @webberui/team-logo-wall.

Usage

import {
  TeamLogoWall,
  type TeamMemberData,
  type LogoData,
} from "@/components/ui/team-logo-wall";

const members: TeamMemberData[] = [
  { name: "Ada Lovelace", role: "Founder / CEO", avatar: "/team/ada.jpg" },
  { name: "Alan Turing", role: "Chief Technology Officer" },
];

const logos: LogoData[] = [
  { name: "Vercel", src: "/logos/vercel.svg", href: "https://vercel.com" },
  { name: "Linear", src: "/logos/linear.svg" },
];

<TeamLogoWall
  members={members}
  logos={logos}
  eyebrow="Our team"
  title="Building animation-first interfaces"
  logosLabel="Brands that trust us"
/>;

TeamGrid and LogoMarquee can also be imported on their own if you only want one half:

import { TeamGrid, LogoMarquee } from "@/components/ui/team-logo-wall";

<TeamGrid members={members} columns={3} />
<LogoMarquee logos={logos} speed={30} direction="right" />

Props

TeamLogoWall

PropTypeDefaultDescription
membersTeamMemberData[]—The array of team member data
logosLogoData[]—The array of customer/partner brand logo data
eyebrowReact.ReactNode—The kicker above the title
titleReact.ReactNode—The section's main heading
descriptionReact.ReactNode—Descriptive text below the main heading
logosLabelReact.ReactNode—Caption above the logo marquee
columnsnumber4Column count for the team grid (2–6, degrading automatically at low breakpoints)
marqueeSpeednumber40The logo marquee's offset per second (px)
marqueeDirection"left" | "right""left"Direction the marquee travels
pauseOnHoverbooleantruePause the marquee on mouse hover or keyboard focus
labelstring"Team & Partner Brands" (Team and partner brands)Accessible label for the whole region

TeamGrid

PropTypeDefaultDescription
membersTeamMemberData[]—The array of team member data
columnsnumber4Column count (2–6, degrading automatically at low breakpoints)
staggernumber0.08Reveal interval between cards (seconds)
delaynumber0Delay before the reveal starts (seconds)
oncebooleantruePlay only the first time the element enters the viewport
labelstring"Team Members" (Team members)Accessible label for the whole region

LogoMarquee

PropTypeDefaultDescription
logosLogoData[]—The array of customer logo data
speednumber40Offset per second (px)
direction"left" | "right""left"Direction of travel
gapnumber48Spacing between logos (px)
pauseOnHoverbooleantruePause on mouse hover or keyboard focus
labelstring"Partner Brands" (Partner brands)Accessible label for the whole region

TeamMemberData

FieldTypeDescription
namestringMember name
rolestringJob title or role (optional)
avatarstringAvatar image URL; when not provided, the first character of the name is shown
hrefstringLink the card goes to when clicked (optional)

LogoData

FieldTypeDescription
namestringBrand name, also used as the alt / accessible text
srcstringLogo image URL
nodeReact.ReactNodeA custom logo node (an inline SVG, for example), which takes precedence over src
hrefstringLink to go to when clicked (optional)

How it works

  • Two stacked parts: the top half is the team grid, whose cards fade in and float up one after another by stagger when they enter the viewport; the bottom half is the logo marquee, scrolling smoothly and infinitely with requestAnimationFrame.
  • Seamless loop: the marquee renders two identical copies of the content, measures the width of one copy, and cycles the offset within (-distance, 0], so the switch point is imperceptible; a ResizeObserver re-measures whenever the container size changes.
  • Fading at both ends: the marquee uses mask-image so logos dissolve naturally at the left and right boundaries.
  • Greyscale logos: by default they are presented in greyscale at reduced opacity, returning to full color and full opacity when the cursor hovers that logo.
  • Standalone use: TeamGrid, LogoMarquee, and TeamMemberCard can all be imported on their own.
  • Tuning points: the animation durations are based on var(--wb-duration-fast,200ms) and var(--wb-ease-out,cubic-bezier(0.22,1,0.36,1)), so you can override them uniformly through CSS variables.

Accessibility

  • When the user has "reduce motion" enabled at the system level, the team grid is presented statically (with no stagger) and the logo wall switches to a centered wrapping layout that no longer scrolls.
  • The team grid is a role="list" and the member cards are role="listitem", with an aria-label on the region.
  • The marquee's second copy is marked aria-hidden, which keeps assistive technology from announcing it twice.
  • Members and logos with an href are focusable links with a clear focus-visible outline; focusing a link inside the marquee pauses the scrolling (with pauseOnHover), which makes keyboard operation easier.
  • Avatar alt is left empty (decorative) and the name is presented separately as text; a logo image's alt comes from the brand's name.