---
/**
* 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>