Editorial FAQ
An accessible, responsive FAQ with original interruptible motion.
Install the component, then paste your configured usage. Your settings are included in the code below.
npx arclen-ui add editorial-faq --settings eyJ0aXRsZXMiOlsiQ2FuIEkgdXNlIHRoaXMgd2l0aCBSZWFjdCBvciBwbGFpbiBIVE1MPyIsIkhvdyBtdWNoIGNhbiBJIGN1c3RvbWl6ZT8iLCJEbyBJIG5lZWQgYW4gYW5pbWF0aW9uIGxpYnJhcnk_IiwiRG9lcyBpdCB3b3JrIHdpdGggYSBrZXlib2FyZD8iLCJDYW4gSSB1c2UgbG9uZ2VyIGFuc3dlcnM_Il0sImRlc2NyaXB0aW9ucyI6WyJUaGUgc2FtZSBpbnRlcmFjdGlvbiBjYW4gbGl2ZSBpbiBlaXRoZXIgZm9ybWF0LiBJbiBSZWFjdCwgcGFzcyB5b3VyIHF1ZXN0aW9ucyBhbmQgYW5zd2VycyBhcyBwcm9wcy4gRm9yIGEgcGxhaW4gSFRNTCBwYWdlLCB1c2UgdGhlIHN0YW5kYWxvbmUgbWFya3VwLCBzdHlsZXMgYW5kIHNtYWxsIHNjcmlwdCB0b2dldGhlci4iLCJTdGFydCB3aXRoIHlvdXIgb3duIHF1ZXN0aW9ucyBhbmQgYW5zd2VycywgdGhlbiBhZGp1c3QgdGhlIHR5cGUsIHNwYWNpbmcsIGNvcm5lciByYWRpdXMgYW5kIGNvbG91cnMuIFRoZSBsYXlvdXQgc2hvdWxkIGZpdCB5b3VyIGNvbnRlbnQsIHdoZXRoZXIgYW4gYW5zd2VyIGlzIG9uZSBzZW50ZW5jZSBvciBhIGZldyBzaG9ydCBwYXJhZ3JhcGhzLiIsIlRoZXNlIEZBUSBwcmV2aWV3cyB1c2UgYnJvd3NlciBhbmltYXRpb24gZmVhdHVyZXMgYW5kIGEgc21hbGwgYW1vdW50IG9mIEphdmFTY3JpcHQuIFRoZXJlIGFyZSBubyB0aGlyZC1wYXJ0eSBhbmltYXRpb24gZGVwZW5kZW5jaWVzLCBmb250IHJlcXVlc3RzIG9yIHJlbW90ZSBhc3NldHMuIiwiWWVzLiBUYWIgbW92ZXMgYmV0d2VlbiBxdWVzdGlvbiBidXR0b25zLCBhbmQgRW50ZXIgb3IgU3BhY2Ugb3BlbnMgYW4gYW5zd2VyLiBGb2N1cyBzdGF5cyBvbiB0aGUgcXVlc3Rpb24geW91IGNob3NlLiBQZW9wbGUgd2hvIHByZWZlciByZWR1Y2VkIG1vdGlvbiBzZWUgdGhlIGFuc3dlciBjaGFuZ2Ugd2l0aG91dCB0aGUgYW5pbWF0ZWQgdHJhdmVsLiIsIlllcy4gVGhlIGFuc3dlciBhcmVhIGZvbGxvd3MgaXRzIGNvbnRlbnQgcmF0aGVyIHRoYW4gYSBmaXhlZCBoZWlnaHQuIEtlZXAgZWFjaCBhbnN3ZXIgZm9jdXNlZCwgcHV0IHRoZSB1c2VmdWwgaW5mb3JtYXRpb24gZmlyc3QsIGFuZCB0ZXN0IHlvdXIgbG9uZ2VzdCBhbnN3ZXIgb24gYSBzbWFsbCBzY3JlZW4uIl0sImluaXRpYWxPcGVuIjowLCJ0aGVtZSI6ImRhcmsiLCJtYXhXaWR0aCI6MCwibW90aW9uU2NhbGUiOjF9import { EditorialFAQ } from "@/components/editorial-faq";
export default function Example() {
return <EditorialFAQ {...{
"titles": [
"Can I use this with React or plain HTML?",
"How much can I customize?",
"Do I need an animation library?",
"Does it work with a keyboard?",
"Can I use longer answers?"
],
"descriptions": [
"The same interaction can live in either format. In React, pass your questions and answers as props. For a plain HTML page, use the standalone markup, styles and small script together.",
"Start with your own questions and answers, then adjust the type, spacing, corner radius and colours. The layout should fit your content, whether an answer is one sentence or a few short paragraphs.",
"These FAQ previews use browser animation features and a small amount of JavaScript. There are no third-party animation dependencies, font requests or remote assets.",
"Yes. Tab moves between question buttons, and Enter or Space opens an answer. Focus stays on the question you chose. People who prefer reduced motion see the answer change without the animated travel.",
"Yes. The answer area follows its content rather than a fixed height. Keep each answer focused, put the useful information first, and test your longest answer on a small screen."
],
"initialOpen": 0,
"theme": "dark",
"maxWidth": 0,
"motionScale": 1
}} />;
}| Property | Type | Default |
|---|---|---|
titlesQuestions Minimum 1 itemsMaximum 12 itemsUp to 80 characters per item | string-list | ["Can I use this with React or plain HTML?","How much can I customize?","Do I need an animation library?","Does it work with a keyboard?","Can I use longer answers?"] |
descriptionsAnswers Minimum 1 itemsMaximum 12 itemsUp to 500 characters per item | string-list | ["The same interaction can live in either format. In React, pass your questions and answers as props. For a plain HTML page, use the standalone markup, styles and small script together.","Start with your own questions and answers, then adjust the type, spacing, corner radius and colours. The layout should fit your content, whether an answer is one sentence or a few short paragraphs.","These FAQ previews use browser animation features and a small amount of JavaScript. There are no third-party animation dependencies, font requests or remote assets.","Yes. Tab moves between question buttons, and Enter or Space opens an answer. Focus stays on the question you chose. People who prefer reduced motion see the answer change without the animated travel.","Yes. The answer area follows its content rather than a fixed height. Keep each answer focused, put the useful information first, and test your longest answer on a small screen."] |
initialOpenInitially open question -1–11Step 1 | number | 0 |
themeTheme Options: dark, light | select | "dark" |
maxWidthMaximum width (0 uses style default) 0 keeps the style default. Positive widths below 240px resolve to 240px; custom widths still shrink to fit smaller containers. 0–1440Step 8 | number | 0 |
motionScaleMotion duration 0–2Step 0.1 | number | 1 |
Editorial FAQ
Five numbered questions with fine dividers, a single open answer and interruptible motion. It uses system fonts and no external dependencies.
import { EditorialFAQ } from './components/editorial-faq';
export default function Example() {
return (
<EditorialFAQ theme="light" initialOpen={0} />
);
}Pass paired titles and descriptions arrays with 1–12 entries. Questions accept up to 80 characters and answers up to 500. Text is escaped. Invalid or mismatched lists resolve to the default pairs. Set initialOpen to -1 for all closed; an out-of-range index also resolves to all closed.
The inspector controls content, initial selection, theme, maximum width and motion duration. Direct CSS edits can change typography and spacing. The component has no background fill: use a suitable dark or light parent surface. Preview headlines and other page framing are not part of the component.
The layout responds to its receiving container. A maximum width of zero uses 1000px. At 480px or narrower, question size and answer indentation become compact. Long text wraps without a fixed answer height.
Tab reaches every question. Enter and Space toggle an answer; arrow keys wrap focus, and Home/End focus the first/last question. Closed answers are inert immediately. Reduced motion and a motion duration of zero settle instantly. Before JavaScript, every answer is readable and controls are disabled; mounting enables the controls and applies the selected state. Missing animation APIs use immediate changes.
For vanilla use, import render and mount from src/core. The returned controller supports update, pause, resume and destroy. Pause, offscreen and hidden-page changes settle active motion. Destroy removes observers/listeners and restores all-readable static content. Updates preserve matching button nodes and focus. The React component accepts className, style and paused in addition to settings, renders server HTML and shares the same core.
Tweaks and configured delivery
Questions and answers are paired, with 1–12 items, up to 80 characters per question and 500 per answer. The tweaks panel holds invalid or mismatched drafts and shows an error; preview and downloads keep the last valid pair of lists. Reset also clears drafts. Direct configured downloads reject invalid paired content.
Maximum width 0 preserves the style default. Turn off **Use style default width** for a custom 240–1440px cap. Positive values below 240 passed directly to the component resolve to 240; the component still shrinks inside a narrower container. The initially open question uses a zero-based index, with -1 for all closed.
The panel exposes content, initial selection, theme, maximum width and motion duration. Typography, spacing and radius remain direct CSS customization. Preview headings, viewport and playback controls are outside the portable settings. Configured React and HTML use the same accepted values.
Complete vanilla example
After installing the package, use this in a browser module or bundler entry. Remove the created host after destroy() when your page no longer needs it.
import { mount, render, resolveSettings } from './components/editorial-faq/src/core';
import './components/editorial-faq/src/styles.css';
const settings = resolveSettings({
titles: ['Can I use my own content?'],
descriptions: ['Yes. Keep the question and answer lists paired.'],
theme: 'light',
initialOpen: 0,
});
const host = document.createElement('div');
document.body.append(host);
host.innerHTML = render(settings);
const faq = mount(host, settings);
// On page teardown: faq.destroy(); host.remove();
The preview runs the component’s own JavaScript. It respects reduced motion and pauses when off screen. The HTML bundle includes a poster fallback.
Every setting in this panel comes from the component manifest. Preview size, pause and replay stay in the inspector.