FAQ Section
block / marketing
A frequently-asked-questions section in three layouts, with diacritic-insensitive search that opens the answers it matched inside, category grouping and optional FAQPage structured data.
- type
- block
- files
- 2
- registry deps
- accordion, button, input, skeleton, @automindz/empty-state, @automindz/render-link
- npm deps
- lucide-react
installs
- lib/automindz/faqs.ts
- components/automindz/faq-section.tsx
- Search opens the answers it matched inside, not just the list
- Two columns, two accordion roots, still one open answer
- Grouping inserts a heading level rather than flattening the outline
- FAQPage JSON-LD is opt-in, and escapes its own script-closing seam
- No entries renders nothing — heading included
Edit lib/automindz/faqs.ts, not the component — including FAQ_CATEGORIES, whose order is the group order. answer is plain text and links carries the anchors, deliberately: a config that imports React can no longer be fed by a CMS or serialised into JSON-LD. layout changes everything — single is one measured column, split puts the heading and a contact rail on the left (sticky from lg: it needs lg:self-start, no overflow on an ancestor, and a top that clears your fixed header — override top-24 via className), columns is two columns that still allow only one open answer. searchable filters case- and diacritic-insensitively and expands any answer the query matched inside. jsonLd is **off by default** — turn it on for exactly one FAQ section per page, or the document emits two FAQPage blocks. headingLevel sets the question level (default 3); the section title takes the level above it and grouping inserts one more. Pass renderLink for your router. Empty faqs renders nothing at all.
Variations
one state per section
- 01Single column, grouped
- 02Search that opens what it matched
- 03Two columns, still one open at a time
- 04Split, with a contact rail
- 05Loading
- 06No entries
Single column, grouped
The default: one measured column, and groups because the entries carry categories. Grouping inserts a heading level rather than making the category a peer of the questions under it, so the outline runs h2 → h3 → h4. jsonLd is on here — view source for one FAQPage block with every < escaped, which is what stops an answer containing markup from closing the script tag.
Frequently asked questions
Everything procurement asks before a pilot, answered in the order they ask it.
Plans and billing
A seat is a person who has signed in at least once in the billing period. Adding one mid-cycle is prorated to the day; removing one credits the remainder against your next invoice rather than refunding it. Invited-but-never-signed-in accounts are free.
Accounts and access
Data and security
Search that opens what it matched
Type "net-30": the invoicing answer expands, because the hit is inside a collapsed panel and a hit nobody can see is a broken filter. A hit on the question alone does not expand — try "cancel". Search also forces multiple open, since three matches must be three visible answers. "Securite" finds "Sécurité"-style copy through NFD folding, and "kubernetes" gets the search empty state with the query echoed and a clear action.
Search the answers
Everything procurement asks before a pilot, answered in the order they ask it.
Two columns, still one open at a time
Two accordion roots with one hoisted value: open something on the right and whatever was open on the left closes, which two independent accordions could never do. The alternative — one root split with CSS columns — reflows items between columns as a panel opens, so the answer you clicked moves out from under the cursor. Tab order runs down the left column then down the right.
Support answers
Split, with a contact rail
The rail carries the heading and the escape hatch for the reader the list did not answer, and sticks from lg up — which needs lg:self-start (a stretched grid item is already as tall as its row) and no overflow set on an ancestor. headingLevel is 4 here, so the questions are h5: the published implementations hardcode the accordion header to h3, and the item re-levels it rather than forking the primitive — including removing the level again if the page later renders at 3, which is the half that is invisible without an accessibility-tree inspection. multiple is on, which is what makes the search worth trying twice: open three answers, filter, then clear the field. You get your three back, not defaultOpen.
Questions, answered
Everything procurement asks before a pilot, answered in the order they ask it.
Plans and billing
Accounts and access
Data and security
Loading
Five skeleton rows built from the trigger's own py-4 and 1.5rem line, so the real questions landing under them shift nothing. The section carries aria-busy and the skeleton is out of the accessibility tree — one announcement, not six.
Frequently asked questions
Everything procurement asks before a pilot, answered in the order they ask it.
No entries
Nothing renders — no heading, no rule, no empty box. That is the state: a FAQ heading with nothing under it reads as a failed fetch, and the frame below is deliberately blank.
