FAQ Accordion
An accessible accordion where one answer opens at a time.
6 个框架中级
An FAQ accordion with a search box that filters the questions as you type.
<!--
Progressive enhancement: with JS off this is a plain <details> list and the
search field simply does nothing visible - every answer is still readable.
The filtering itself is ~10 lines; see the React tabs for the stateful version.
The result count lives in an aria-live="polite" region so a screen-reader user
hears "2 questions" as they type, instead of the list silently reflowing.
-->
<div class="acc-search">
<form class="acc-search__form" role="search" onsubmit="return false">
<label class="acc-search__label" for="faq-search">Search questions</label>
<input class="acc-search__input" id="faq-search" type="search" placeholder="Search questions…" autocomplete="off" />
</form>
<p class="acc-search__count" role="status" aria-live="polite">3 questions</p>
<div class="acc-search__list">
<details class="acc-search__item" name="acc-search" open>
<summary class="acc-search__question">
Can I export my data?
<svg class="acc-search__icon" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path d="m5 7.5 5 5 5-5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</summary>
<div class="acc-search__answer">
<p>Any time, from Settings → Export. You get a ZIP of CSV and JSON - no lock-in and no support ticket.</p>
</div>
</details>
<details class="acc-search__item" name="acc-search">
<summary class="acc-search__question">
Do you have a mobile app?
<svg class="acc-search__icon" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path d="m5 7.5 5 5 5-5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</summary>
<div class="acc-search__answer">
<p>Native apps for iOS and Android, plus an installable web app that works offline.</p>
</div>
</details>
<details class="acc-search__item" name="acc-search">
<summary class="acc-search__question">
Which integrations are supported?
<svg class="acc-search__icon" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path d="m5 7.5 5 5 5-5" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</summary>
<div class="acc-search__answer">
<p>Slack, GitHub, Jira, Zapier and around forty more, all managed from the integrations directory.</p>
</div>
</details>
</div>
</div>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
items必填 | FaqItem[] | - | 要渲染的项目数组。 |
defaultOpenId | string | - | 挂载时默认展开项的 id。 |
className | string | - | 合并到根元素上的额外类名。 |
Filtering matches answers as well as questions, so a search for "refund" finds a question whose title never uses the word - the substring match is the piece to replace first if you outgrow it. The result count sits in an `aria-live="polite"` region so a screen-reader user hears the list change instead of it silently reflowing beneath them, and the label is `sr-only` rather than absent, because a placeholder is not a label. The HTML tabs degrade to a plain `<details>` list: with JavaScript off the field does nothing and every answer stays readable.