Logos

Logos 02 — Grid

Static responsive grid of muted wordmark cells with a centered headline and subtle reveal — supports image logos via props.

$ npx shadcn@latest add @ludusvibe/logos-02
Open in v0

Code

Installed to components/sections/logos-02.tsx — it's yours to edit.

"use client"

import * as React from "react"

import { Reveal } from "@/components/ludus/reveal"
import { cn } from "@/lib/utils"

export type Logo = {
  name: string
  /** Optional image logo — rendered instead of the text wordmark. */
  src?: string
}

export type Logos02Props = {
  headline?: React.ReactNode
  logos?: Logo[]
  /** Heading element — use "h1" when this is the page's main heading. */
  as?: "h1" | "h2"
  className?: string
}

const defaultLogos: Logo[] = [
  { name: "Meridian" },
  { name: "Arclight" },
  { name: "Fathom" },
  { name: "Nimbus" },
  { name: "Polaris" },
  { name: "Vantage" },
]

/** Distinct type treatments so text wordmarks read as different brands. */
const wordmarkStyles = [
  "font-heading text-lg font-bold tracking-tighter",
  "text-sm font-light tracking-[0.3em] uppercase",
  "font-heading text-lg font-semibold italic tracking-tight",
  "text-sm font-semibold tracking-[0.2em] uppercase",
  "font-heading text-lg font-medium tracking-wide",
  "text-base font-extrabold tracking-tight uppercase",
]

export function Logos02({
  headline = "Powering product teams at every stage",
  logos = defaultLogos,
  as: Heading = "h2",
  className,
}: Logos02Props) {
  return (
    <section className={cn("bg-background px-6 py-16 md:py-20", className)}>
      <div className="mx-auto max-w-5xl">
        <Reveal>
          <Heading className="mx-auto max-w-xl text-balance text-center font-heading text-2xl font-semibold tracking-tight md:text-3xl">
            {headline}
          </Heading>
        </Reveal>
        <Reveal delay={0.1} className="mt-10">
          <div className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-6">
            {logos.map((logo, index) => (
              <div
                key={logo.name}
                className="flex h-24 items-center justify-center rounded-xl border bg-card/50 px-4 transition-colors duration-300 hover:border-primary/30"
              >
                {logo.src ? (
                  <img
                    src={logo.src}
                    alt={logo.name}
                    className="h-7 w-auto max-w-full opacity-60 transition-opacity hover:opacity-100"
                  />
                ) : (
                  <span
                    className={cn(
                      "text-center text-muted-foreground/70 transition-colors hover:text-foreground",
                      wordmarkStyles[index % wordmarkStyles.length]
                    )}
                  >
                    {logo.name}
                  </span>
                )}
              </div>
            ))}
          </div>
        </Reveal>
      </div>
    </section>
  )
}