Connected 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 connected-faq --settings eyJ0aXRsZXMiOlsiQ2FuIEkgdXNlIHRoaXMgd2l0aCBSZWFjdCBvciBwbGFpbiBIVE1MPyIsIkhvdyBtdWNoIGNhbiBJIGN1c3RvbWl6ZT8iLCJEbyBJIG5lZWQgYW4gYW5pbWF0aW9uIGxpYnJhcnk_IiwiRG9lcyBpdCB3b3JrIHdpdGggYSBrZXlib2FyZD8iLCJDYW4gSSB1c2UgbG9uZ2VyIGFuc3dlcnM_Il0sImRlc2NyaXB0aW9ucyI6WyJUaGUgc2FtZSBpbnRlcmFjdGlvbiBjYW4gbGl2ZSBpbiBlaXRoZXIgZm9ybWF0LiBJbiBSZWFjdCwgcGFzcyB5b3VyIHF1ZXN0aW9ucyBhbmQgYW5zd2VycyBhcyBwcm9wcy4gRm9yIGEgcGxhaW4gSFRNTCBwYWdlLCB1c2UgdGhlIHN0YW5kYWxvbmUgbWFya3VwLCBzdHlsZXMgYW5kIHNtYWxsIHNjcmlwdCB0b2dldGhlci4iLCJTdGFydCB3aXRoIHlvdXIgb3duIHF1ZXN0aW9ucyBhbmQgYW5zd2VycywgdGhlbiBhZGp1c3QgdGhlIHR5cGUsIHNwYWNpbmcsIGNvcm5lciByYWRpdXMgYW5kIGNvbG91cnMuIFRoZSBsYXlvdXQgc2hvdWxkIGZpdCB5b3VyIGNvbnRlbnQsIHdoZXRoZXIgYW4gYW5zd2VyIGlzIG9uZSBzZW50ZW5jZSBvciBhIGZldyBzaG9ydCBwYXJhZ3JhcGhzLiIsIlRoZXNlIEZBUSBwcmV2aWV3cyB1c2UgYnJvd3NlciBhbmltYXRpb24gZmVhdHVyZXMgYW5kIGEgc21hbGwgYW1vdW50IG9mIEphdmFTY3JpcHQuIFRoZXJlIGFyZSBubyB0aGlyZC1wYXJ0eSBhbmltYXRpb24gZGVwZW5kZW5jaWVzLCBmb250IHJlcXVlc3RzIG9yIHJlbW90ZSBhc3NldHMuIiwiWWVzLiBUYWIgbW92ZXMgYmV0d2VlbiBxdWVzdGlvbiBidXR0b25zLCBhbmQgRW50ZXIgb3IgU3BhY2Ugb3BlbnMgYW4gYW5zd2VyLiBGb2N1cyBzdGF5cyBvbiB0aGUgcXVlc3Rpb24geW91IGNob3NlLiBQZW9wbGUgd2hvIHByZWZlciByZWR1Y2VkIG1vdGlvbiBzZWUgdGhlIGFuc3dlciBjaGFuZ2Ugd2l0aG91dCB0aGUgYW5pbWF0ZWQgdHJhdmVsLiIsIlllcy4gVGhlIGFuc3dlciBhcmVhIGZvbGxvd3MgaXRzIGNvbnRlbnQgcmF0aGVyIHRoYW4gYSBmaXhlZCBoZWlnaHQuIEtlZXAgZWFjaCBhbnN3ZXIgZm9jdXNlZCwgcHV0IHRoZSB1c2VmdWwgaW5mb3JtYXRpb24gZmlyc3QsIGFuZCB0ZXN0IHlvdXIgbG9uZ2VzdCBhbnN3ZXIgb24gYSBzbWFsbCBzY3JlZW4uIl0sImluaXRpYWxPcGVuIjowLCJ0aGVtZSI6ImRhcmsiLCJtYXhXaWR0aCI6MCwibW90aW9uU2NhbGUiOjEsImFwcGVhcmFuY2UiOiJjb25uZWN0ZWQifQimport { ConnectedFAQ } from "@/components/connected-faq";
export default function Example() {
return <ConnectedFAQ {...{
"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,
"appearance": "connected"
}} />;
}| 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 |
appearanceAppearance Options: connected, bridge, capsules | select | "connected" |
Connected FAQ
A single-open FAQ with three appearances: Connected Cards, Soft Bridge and Floating Capsules. Connected Cards is the default, with a thin left connector and a steady card colour. Soft Bridge groups closed rows and morphs its leading circles into rounded squares. Floating Capsules separates pill-shaped rows as they open.
Use
Pass equally sized titles and descriptions arrays. Each array accepts one to twelve items. Questions allow 80 characters and answers allow 500. Content is plain text; line breaks in an answer are preserved. Invalid paired lists fall back to the example content. Use initialOpen={-1} to start with every answer closed.
import { ConnectedFAQ } from './components/connected-faq';
export default function Example() {
return (
<ConnectedFAQ
titles={['Can I customize the questions?', 'Does it support a keyboard?']}
descriptions={['Yes. Supply your own question and answer lists.', 'Yes. Use Tab, Enter or Space.']}
appearance="connected"
theme="light"
/>
);
}Appearance and layout
Choose connected, bridge or capsules. A maxWidth of zero uses the appearance's natural cap: 384px for Connected/Bridge, 1000px for Capsules. A positive value sets another cap. The component fits its receiving container; Capsules uses compact spacing when that container is at most 480px wide. The heading and description seen on the preview page are separate page content.
Accessibility and motion
Questions are native buttons. Tab reaches each question, Enter/Space toggles it, and Arrow Up/Down, Home and End move focus. Focus stays on the chosen question. Closed answers are hidden and inert. Reduced motion and motionScale={0} change state immediately.
The static render exposes every answer when JavaScript is unavailable. Without the animation API, controls still work and state changes immediately. Pausing or moving offscreen settles active transitions to the current selected state; resuming enables motion for subsequent interaction. No animation library, remote font or external artwork is needed.
Vanilla lifecycle
The core exports defaults, resolveSettings, render and mount. The mounted instance provides update, pause, resume and destroy. Updating existing rows preserves their DOM nodes and focus. Destruction removes observers and listeners and restores readable static answers. Each instance owns its IDs and state.
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, plus Connected, Bridge and Capsules appearances. 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/connected-faq/src/core';
import './components/connected-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.