BetaUnder active development — content may be incomplete or change without notice.

Testimonial 2

A section with header and two side-by-side testimonials.

0px
Loading Preview...

Testimonial 2 is a section with a centered header and description at the top, followed by two side-by-side testimonials in a 2-column grid (stacks on mobile). Each testimonial includes a company logo, quote, avatar, name, and position.

Fields Reference

Field NameTypeRequiredLocalizedDescription
headertextYesYesThe main header text for the testimonials section.
descriptionrichtextNoYesA description or subtitle for the testimonials section.
testimonialsarrayYesYesAn array of 1-2 testimonial items.
testimonials.logouploadNoNoCompany logo image referencing the media collection.
testimonials.quoterichtextYesYesThe testimonial quote text.
testimonials.avataruploadNoNoAuthor's avatar image referencing the media collection.
testimonials.nametextYesYesThe author's name.
testimonials.positiontextNoYesThe author's position and company name.

Code

import React from 'react'
import { Image as ImageIcon } from "lucide-react"
import RichText from '@/components/cms/RichText'
import { Testimonial2Type } from '@/payload-types'

const Testimonial2Component: React.FC<Testimonial2Type> = ({ header, description, testimonials }: Testimonial2Type) => {
    return (
        <section className="w-full min-h-screen bg-background py-16 px-6 md:py-24 lg:py-32">
            <div className="max-w-7xl mx-auto flex flex-col items-center">

                {/* Section Header */}
                <div className="text-center mb-16 md:mb-20 max-w-3xl">
                    <h1 className="text-4xl md:text-5xl lg:text-6xl font-semibold tracking-tight text-foreground mb-6">
                        {header}
                    </h1>
                    {description && (
                        <RichText
                            data={description}
                            enableGutter={false}
                            className="mx-0 [&_p]:text-muted-foreground [&_p]:text-lg [&_p]:md:text-xl"
                        />
                    )}
                </div>

                {/* Testimonials Grid */}
                <div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-16 w-full">
                    {testimonials?.map((testimonial, index) => (
                        <div key={index} className="flex flex-col items-center text-center gap-8">
                            {/* Logo */}
                            {testimonial.logo && typeof testimonial.logo === 'object' && testimonial.logo.url && (
                                <div className="flex items-center justify-center">
                                    <a
                                        href="#"
                                        className="transition-opacity hover:opacity-80"
                                    >
                                        <img
                                            src={testimonial.logo.url}
                                            alt={testimonial.logo.alt || 'Company Logo'}
                                            style={{ width: '150px' }}
                                            className="h-auto object-contain dark:invert"
                                        />
                                    </a>
                                </div>
                            )}

                            {/* Quote */}
                            <blockquote className="text-lg md:text-xl font-semibold leading-relaxed text-foreground max-w-md mx-0">
                                <RichText
                                    data={testimonial.quote}
                                    enableGutter={false}
                                    className="[&_p]:text-lg [&_p]:md:text-xl [&_p]:font-semibold [&_p]:leading-relaxed [&_p]:text-foreground"
                                />
                            </blockquote>

                            {/* User Info */}
                            <div className="flex flex-col items-center gap-4">
                                {/* Avatar */}
                                <div className="w-14 h-14 rounded-full bg-muted flex items-center justify-center border border-border overflow-hidden">
                                    {testimonial.avatar && typeof testimonial.avatar === 'object' && testimonial.avatar.url ? (
                                        <img
                                            src={testimonial.avatar.url}
                                            alt={testimonial.avatar.alt || testimonial.name}
                                            className="w-full h-full object-cover"
                                        />
                                    ) : (
                                        <ImageIcon className="w-6 h-6 text-muted-foreground/40" />
                                    )}
                                </div>
                                <div>
                                    <cite className="not-italic font-semibold text-foreground block">
                                        {testimonial.name}
                                    </cite>
                                    {testimonial.position && (
                                        <p className="text-muted-foreground text-sm">
                                            {testimonial.position}
                                        </p>
                                    )}
                                </div>
                            </div>
                        </div>
                    ))}
                </div>
            </div>
        </section>
    )
}

export default Testimonial2Component