---
/**
* FaqSplit: headline and a contact prompt pinned on the left, ruled
* questions on the right. Native <details>, FAQPage JSON-LD included.
*
* @example
* <FaqSplit title="Before you" accent="order." contact={{ label: "Write to us", href: "/contact" }} items={[...]} />
*/
interface Item {
q: string;
a: string;
}
interface Link {
label: string;
href: string;
}
interface Props {
title: string;
accent?: string;
intro?: string;
/** A link under the intro for questions not on the list. */
contact?: Link;
items: Item[];
openFirst?: boolean;
schema?: boolean;
as?: "h2" | "h3";
class?: string;
}
const { title, accent, intro, contact, items, openFirst = false, schema = true, as: Heading = "h2", class: className } = Astro.props;
const jsonLd = JSON.stringify({
"@context": "https://schema.org",
"@type": "FAQPage",
mainEntity: items.map((i) => ({ "@type": "Question", name: i.q, acceptedAnswer: { "@type": "Answer", text: i.a } })),
}).replace(/</g, "\\u003c");
---
<section class:list={["vs-faq-split", className]}>
<div class="vs-faq-split__inner">
<header class="vs-faq-split__head">
<Heading class="vs-display vs-faq-split__title">{title}{accent && <> <em>{accent}</em></>}</Heading>
{intro && <p class="vs-faq-split__intro">{intro}</p>}
{
contact && (
<a class="vs-faq-split__contact" href={contact.href}>
{contact.label}
</a>
)
}
</header>
<div class="vs-faq-split__list">
{
items.map((item, i) => (
<details class="vs-faq-split__row" open={openFirst && i === 0}>
<summary>
<span class="vs-faq-split__num" aria-hidden="true">{String(i + 1).padStart(2, "0")}</span>
<span class="vs-faq-split__q">{item.q}</span>
<span class="vs-faq-split__mark" aria-hidden="true" />
</summary>
<p class="vs-faq-split__a">{item.a}</p>
</details>
))
}
</div>
</div>
{schema && <script is:inline type="application/ld+json" set:html={jsonLd} />}
</section>
<style>
.vs-faq-split {
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-faq-split__inner {
display: grid;
gap: clamp(28px, 5cqi, 56px);
max-width: var(--vs-container);
margin-inline: auto;
padding: var(--vs-section-y) var(--vs-gutter);
}
.vs-faq-split__title {
font-size: clamp(2rem, 6.5cqi, 4.25rem);
}
.vs-faq-split__intro {
max-width: 24rem;
margin: 1.25rem 0 0;
font-size: 1rem;
line-height: 1.55;
color: var(--vs-ink-2);
}
.vs-faq-split__contact {
display: inline-block;
margin-top: 1.25rem;
padding-bottom: 2px;
border-bottom: calc(var(--vs-border-w) + 1px) solid var(--vs-accent);
font-size: 0.9375rem;
font-weight: 600;
color: var(--vs-ink);
text-decoration: none;
}
.vs-faq-split__contact:focus-visible {
outline: none;
box-shadow: var(--vs-focus-ring);
}
.vs-faq-split__list {
border-top: calc(var(--vs-border-w) + 1px) solid var(--vs-ink);
}
.vs-faq-split__row {
border-bottom: var(--vs-border-w) solid var(--vs-line-strong);
}
.vs-faq-split__row summary {
display: grid;
grid-template-columns: 2.25rem minmax(0, 1fr) auto;
align-items: center;
gap: 12px;
padding: 20px 4px;
cursor: pointer;
list-style: none;
}
.vs-faq-split__row summary::-webkit-details-marker {
display: none;
}
.vs-faq-split__row summary:focus-visible {
outline: none;
box-shadow: var(--vs-focus-ring);
}
.vs-faq-split__num {
font-size: 0.8125rem;
font-variant-numeric: tabular-nums;
color: var(--vs-ink-3);
}
.vs-faq-split__q {
font-size: 1.0625rem;
font-weight: 600;
line-height: 1.3;
}
.vs-faq-split__a {
margin: 0;
padding: 0 4px 22px calc(2.25rem + 16px);
max-width: 40rem;
font-size: 0.9375rem;
line-height: 1.6;
color: var(--vs-ink-2);
}
.vs-faq-split__mark {
position: relative;
width: 14px;
height: 14px;
}
.vs-faq-split__mark::before,
.vs-faq-split__mark::after {
content: "";
position: absolute;
left: 0;
top: 6px;
width: 14px;
height: 2px;
background: var(--vs-ink);
transition: transform var(--vs-duration) var(--vs-ease-out);
}
.vs-faq-split__mark::after {
transform: rotate(90deg);
}
.vs-faq-split__row[open] .vs-faq-split__mark::after {
transform: rotate(0deg);
}
.vs-faq-split__row[open] .vs-faq-split__num {
color: var(--vs-accent-ink);
}
@container (min-width: 820px) {
.vs-faq-split__inner {
grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
gap: clamp(32px, 6cqi, 88px);
align-items: start;
}
.vs-faq-split__head {
position: sticky;
top: 24px;
}
}
</style>