# Testimonial Spotlight

> One customer quote set large in the display face, with up to three supporting quotes beneath.

- **Slug:** `testimonial-spotlight`
- **Kind:** section · **Category:** Proof
- **Source:** original to Viewership UI
- **Docs page:** https://viewership.ai/ui/components/testimonial-spotlight
- **All files in one bundle:** https://viewership.ai/ui/components/testimonial-spotlight.bundle.txt
- **Structured JSON:** https://viewership.ai/ui/components/testimonial-spotlight.json

## Install

1. Import the foundation tokens once (download: https://viewership.ai/ui/raw/foundation.css.txt):

```astro
---
// src/layouts/Layout.astro
import "../styles/foundation.css";
---
```

2. Copy this file into `src/components/viewership/testimonial-spotlight/`:

   - `TestimonialSpotlight.astro` (raw: https://viewership.ai/ui/raw/testimonial-spotlight/TestimonialSpotlight.astro.txt)

npm packages: none.

## Usage

```astro
---
import TestimonialSpotlight from "../components/viewership/testimonial-spotlight/TestimonialSpotlight.astro";
---

<TestimonialSpotlight />
```

## Example

The gallery demo, verbatim. Use the import path from Usage instead of `./`.

```astro
---
import TestimonialSpotlight from "./TestimonialSpotlight.astro";
---

<TestimonialSpotlight
  items={[
    { quote: "The zip failed on day nine of a twelve-day trip. They fixed it in two days and the pack outlasted the rest of the season.", name: "Maya Ortiz", role: "Guide, Ridgeline Outfitters" },
    { quote: "The first jacket I have owned that came back from a repair looking better than it left.", name: "Daniel Okafor", role: "Trail runner" },
    { quote: "Honest weights on the page, and the pack matched them to the gram.", name: "Priya Raman", role: "Ultralight blogger" },
    { quote: "They asked what went wrong and then actually changed the design.", name: "Lena Voss", role: "Climbing coach" },
  ]}
/>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `items` | `{ quote: string; name: string; role?: string }[]` |  | Quotes. The first leads; the next three sit in the row. |

## Source

### `src/components/viewership/testimonial-spotlight/TestimonialSpotlight.astro`

```astro
---
/**
 * TestimonialSpotlight: one quote set large in the display face, with up to
 * three supporting quotes in a ruled row beneath.
 *
 * Only publish quotes you have permission to use.
 *
 * @example
 * <TestimonialSpotlight items={[{ quote: "Fixed in two days.", name: "Maya Ortiz", role: "Guide" }]} />
 */
interface Item {
  quote: string;
  name: string;
  role?: string;
}
interface Props {
  items: Item[];
  class?: string;
}

const { items, class: className } = Astro.props;
const [lead, ...rest] = items;
const initials = (name: string) =>
  name
    .split(/\s+/)
    .map((p) => p[0])
    .slice(0, 2)
    .join("")
    .toUpperCase();
---

<section class:list={["vs-testimonial-spotlight", className]}>
  <div class="vs-testimonial-spotlight__inner">
    {
      lead && (
        <figure class="vs-testimonial-spotlight__lead">
          <blockquote class="vs-display vs-testimonial-spotlight__quote">
            <p>{lead.quote}</p>
          </blockquote>
          <figcaption class="vs-testimonial-spotlight__by">
            <span class="vs-testimonial-spotlight__avatar" aria-hidden="true">{initials(lead.name)}</span>
            <span>
              <span class="vs-testimonial-spotlight__name">{lead.name}</span>
              {lead.role && <span class="vs-testimonial-spotlight__role">{lead.role}</span>}
            </span>
          </figcaption>
        </figure>
      )
    }
    {
      rest.length > 0 && (
        <ul class="vs-testimonial-spotlight__row">
          {rest.slice(0, 3).map((q) => (
            <li>
              <figure>
                <blockquote>
                  <p>{q.quote}</p>
                </blockquote>
                <figcaption>
                  <span class="vs-testimonial-spotlight__name">{q.name}</span>
                  {q.role && <span class="vs-testimonial-spotlight__role">{q.role}</span>}
                </figcaption>
              </figure>
            </li>
          ))}
        </ul>
      )
    }
  </div>
</section>

<style>
  .vs-testimonial-spotlight {
    container-type: inline-size;
    background: var(--vs-page);
    color: var(--vs-ink);
    font-family: var(--vs-font-sans);
    font-stretch: var(--vs-font-stretch);
  }
  .vs-testimonial-spotlight__inner {
    max-width: var(--vs-container);
    margin-inline: auto;
    padding: var(--vs-section-y) var(--vs-gutter);
  }
  .vs-testimonial-spotlight figure,
  .vs-testimonial-spotlight blockquote,
  .vs-testimonial-spotlight p {
    margin: 0;
  }
  .vs-testimonial-spotlight__quote {
    font-size: clamp(1.75rem, 5.2cqi, 3.5rem);
    line-height: 1.12;
  }
  .vs-testimonial-spotlight__quote p::before {
    content: "\201C";
  }
  .vs-testimonial-spotlight__quote p::after {
    content: "\201D";
  }
  .vs-testimonial-spotlight__by {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 28px;
    font-size: 0.875rem;
  }
  .vs-testimonial-spotlight__by > span:last-child {
    display: flex;
    flex-direction: column;
  }
  .vs-testimonial-spotlight__avatar {
    display: inline-flex;
    width: 44px;
    height: 44px;
    align-items: center;
    justify-content: center;
    border-radius: var(--vs-radius-pill);
    background: var(--vs-accent-tint);
    color: var(--vs-accent-ink);
    font-size: 0.8125rem;
    font-weight: 600;
  }
  .vs-testimonial-spotlight__name {
    display: block;
    font-weight: 600;
  }
  .vs-testimonial-spotlight__role {
    display: block;
    color: var(--vs-ink-3);
  }
  .vs-testimonial-spotlight__row {
    display: grid;
    gap: 24px;
    margin: clamp(36px, 6cqi, 72px) 0 0;
    padding: 28px 0 0;
    list-style: none;
    border-top: calc(var(--vs-border-w) + 1px) solid var(--vs-ink);
  }
  .vs-testimonial-spotlight__row blockquote {
    font-size: 0.9375rem;
    line-height: 1.55;
    color: var(--vs-ink-2);
  }
  .vs-testimonial-spotlight__row figcaption {
    margin-top: 14px;
    font-size: 0.875rem;
  }
  @container (min-width: 700px) {
    .vs-testimonial-spotlight__row {
      grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
      gap: 32px;
    }
  }
</style>
```
