FAQ
The FAQ module: 4–15 independent questions and answers in a ruled Base UI Accordion, under a chapter-stack header.
import {
FAQ,
FAQContact,
FAQHeader,
FAQIntro,
FAQItem,
FAQList,
FAQTitle,
} from '@fairgarden-private/design/components/FAQ'
Questions are h3 item heads in the display serif; answers are text serif within the reading measure. The first rule is the strong top under the header, and every item closes with a rule. Each question trails the LTA disclosure glyph, which points inward when its answer is open. Several answers may be open at once, and every answer prints expanded. Don't use an FAQ for essential content or for steps, and never open items on hover.
Ruled and barred
Ruled and barred
kind="ruled" is the default. barred adds a --ds-stroke-3 bar at the start of each open item's row, a bolder line and never a fill. kind="keyed" leads each row with a block subject icon (FAQItem icon) and indents the answers; kind="split" puts the header in the left third of the page grid from 1024 px.
Visiting the preserves
Answers to the questions we hear most at the trailhead.
Still have a question? Write to the stewardship team.
import {
FAQ,
FAQContact,
FAQHeader,
FAQIntro,
FAQItem,
FAQList,
FAQTitle,
} from '@fairgarden-private/design/components/FAQ'
import { Link } from '@fairgarden-private/design/components/Link'
import styles from './variants.module.css'
/** The ruled FAQ (default) with header, intro and contact line, and the barred form. */
export function FAQVariants() {
return (
<div className={styles.stack}>
<FAQ>
<FAQHeader>
<FAQTitle>Visiting the preserves</FAQTitle>
<FAQIntro>Answers to the questions we hear most at the trailhead.</FAQIntro>
</FAQHeader>
<FAQList defaultValue={['dogs']}>
<FAQItem value="dogs" question="Can I bring my dog?">
Yes, on a leash no longer than six feet. Please pack out what your dog leaves behind.
</FAQItem>
<FAQItem value="fees" question="Is there an entry fee?">
No. Every FairGarden preserve is free and open from dawn to dusk.
</FAQItem>
<FAQItem value="bikes" question="Are bikes allowed on the trails?">
Only on the gravel service roads, marked with a green post at each junction.
</FAQItem>
<FAQItem value="groups" question="Can our school group book a guided walk?">
Yes. Walks run April to October for groups of up to 30.
</FAQItem>
</FAQList>
<FAQContact>
Still have a question? <Link href="#contact">Write to the stewardship team</Link>.
</FAQContact>
</FAQ>
<FAQ barred>
<FAQList defaultValue={['easement']}>
<FAQItem value="easement" question="What is a conservation easement?">
A legal agreement that limits development on land while it stays in private hands.
</FAQItem>
<FAQItem value="taxes" question="Does an easement change my property taxes?">
It can lower them. Talk to your assessor before you sign.
</FAQItem>
<FAQItem value="sell" question="Can I still sell the land?">
Yes. The easement travels with the deed to every future owner.
</FAQItem>
</FAQList>
</FAQ>
</div>
)
}
Primary and secondary
Primary and secondary
primary recolors rules, questions, glyph and answers. secondary drives only the accent underlines: links inside answers and on the contact line, and a question's hover underline.
Membership
import {
FAQ,
FAQContact,
FAQHeader,
FAQIntro,
FAQItem,
FAQList,
FAQTitle,
} from '@fairgarden-private/design/components/FAQ'
import { Link } from '@fairgarden-private/design/components/Link'
import styles from './color.module.css'
/** `primary` drives rules, questions and glyph; `secondary` only the link underlines in answers. */
export function FAQColor() {
return (
<div className={styles.stack}>
<FAQ primary="slate" secondary="indigo">
<FAQHeader>
<FAQTitle>Membership</FAQTitle>
</FAQHeader>
<FAQList defaultValue={['renew']}>
<FAQItem value="renew" question="When does my membership renew?">
Each spring. <Link href="#renew">Renew online</Link> any time after March 1.
</FAQItem>
<FAQItem value="gift" question="Can I give a membership as a gift?">
Yes, with a printed card mailed to the recipient.
</FAQItem>
</FAQList>
</FAQ>
</div>
)
}
On grounds
On paper and forest
On saturated grounds keep an FAQ to five items with answers of 40 words or fewer.
paper
forest
import {
FAQ,
FAQContact,
FAQHeader,
FAQIntro,
FAQItem,
FAQList,
FAQTitle,
} from '@fairgarden-private/design/components/FAQ'
import { PresetGround } from '@/components/PresetGround'
import styles from './grounds.module.css'
const presets = ['paper', 'forest'] as const
/** Light and deep grounds both hold an FAQ; the rules and glyph re-resolve per ground. */
export function FAQGrounds() {
return (
<div className={styles.row}>
{presets.map((preset) => (
<PresetGround key={preset} preset={preset} className={styles.face}>
<p className={styles.name}>{preset}</p>
<FAQ>
<FAQList defaultValue={['open']}>
<FAQItem value="open" question="Are the trails open in winter?">
Yes, except after ice storms.
</FAQItem>
<FAQItem value="restrooms" question="Are there restrooms?">
At the north lot, May to October.
</FAQItem>
</FAQList>
</FAQ>
</PresetGround>
))}
</div>
)
}
API Reference
FAQ
The FAQ module: FAQHeader (with FAQTitle and an optional FAQIntro),
FAQList holding FAQItems, and an optional closing FAQContact. Place
it on light or deep grounds; on saturated grounds keep to five items with
answers of 40 words or fewer. Every answer prints expanded.
| Prop | Type | Description |
|---|---|---|
barred | | Shows a |
kind | |
|
primary | | Primary Radix scale: rules, questions, glyph and answers. Never defaulted; omitted, it inherits the scope [D133]. |
secondary | | Secondary Radix scale: only the link underlines inside answers and on
the contact link ( |
FAQHeader, FAQTitle and FAQIntro
The module header: the chapter-stack title, then the optional intro (§3.5 Recipe A).
The section head: type-h2 in --role-heading. Renders <h2>.
An optional lede under the title, within --ds-measure-reading.
FAQList and FAQItem
The item list, a Base UI Accordion Root. Several items may be open at once
(multiple, default true); closed answers stay in the DOM
(hiddenUntilFound, default true) for find-in-page and print. Never
open items by hover.
One question and its answer. The question is an h3 wrapping the trigger;
the disclosure glyph trails it, top-aligned to its first line. The answer
is type-body, within --ds-measure-reading. FAQ items are never
disabled.
| Prop | Type | Description |
|---|---|---|
icon | | The leading block icon of the |
panelProps | | Props for the answer panel, such as |
question | | The question: |
FAQContact
The optional closing contact line, e.g. “Still stuck? Write to us.” with a Link.
Additional types
FAQContactProps
Props for FAQContact: paragraph props and render.
type FAQContactProps = useRender.ComponentProps<'p'>FAQHeaderProps
Props for FAQHeader: header props and render.
type FAQHeaderProps = useRender.ComponentProps<'header'>FAQIntroProps
Props for FAQIntro: paragraph props and render.
type FAQIntroProps = useRender.ComponentProps<'p'>FAQItemProps
Props for FAQItem: Base UI Accordion Item props (without disabled) plus the question.
type FAQItemProps = {
/** The question: `type-itemhead` in `--primary12`, inside an `h3`. */
question: React.ReactNode;
/**
* The leading block icon of the `keyed` kind (§6.10 subject symbol,
* Material Symbols Rounded, block tier). Ignored by the other kinds.
*/
icon?:
| 'menu'
| 'search'
| 'circle'
| 'arrow_forward'
| 'arrow_upward'
| 'expand_more'
| 'close'
| 'remove'
| 'add'
| 'check'
| 'chevron_right'
| 'chevron_left'
| 'more_horiz'
| 'play_arrow'
| 'pause'
| 'download'
| 'zoom_in'
| 'zoom_out'
| 'recenter'
| 'help'
| 'mail';
/** Props for the answer panel, such as `keepMounted`. */
panelProps?: Omit<AccordionPanelProps, 'children'>;
}FAQListProps
Props for FAQList: Base UI Accordion Root props.
type FAQListProps<Value = unknown> = AccordionRoot.Props<Value>FAQProps
Props for FAQ: section props, render, and the kind, bar and color axes.
type FAQProps = React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement> &
__type & {
kind?: 'ruled' | 'keyed' | 'split' | null;
barred?: boolean | null;
primary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| null;
secondary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'amber'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow'
| null;
}FAQTitleProps
Props for FAQTitle: heading props and render (default <h2>).
type FAQTitleProps = useRender.ComponentProps<'h2'>Specification: DESIGN-SYSTEM.md §12.5 (FAQ) and §10.13 (accordion).