1 GitHub star = 1 new component.

Star the repo
FAQ & Help

FAQ Two Column

Two-column FAQ with sticky intro and native exclusive <details> accordions that work without JS.

faqaccordiondetailssupport
Live Preview

Frequently asked questions

Everything you need to know about the kit. Canโ€™t find an answer? Our team replies within a day.

Contact support
Do I need to install a package?

No. Every component is a standalone .astro file. Copy it into your project, or install the package if you prefer imports.

Do the charts need a JavaScript library?

No. The SVG charts render at build time. A tiny shared script only powers hover tooltips, and every chart includes a data table fallback.

Is it accessible?

Components target WCAG 2.2 AA: semantic HTML, visible focus states, keyboard support and contrast of at least 4.5:1 for text.

Can I use it in commercial projects?

Yes. The kit is MIT licensed. Use it for client work, SaaS products and anything else.

How do I change the colors?

Edit the CSS custom properties in global.css. Every component reads from the same tokens, so one change updates everything.

Usage

Copy and paste this code into your React component:

tsx
import { FaqTwoColumn } from 'react-component-kit-ui/sections';

<FaqTwoColumn items={[
    { q: 'Is it free?', a: 'Yes, MIT licensed.' },
    { q: 'Do I need JS?', a: 'No.' },
  ]} exclusive />

Manual Installation

If you are not using the npm package, create a new file and paste the following code: src/components/sections/FaqTwoColumn.tsx + FaqTwoColumn.css:

FaqTwoColumn.tsx
'use client';

import './FaqTwoColumn.css';

/**
 * FaqTwoColumn โ€” FAQ section with a sticky intro column (heading + support CTA)
 * and native <details> accordions on the right. Works without JavaScript.
 *
 * @param {string} title - Section heading.
 * @param {string} subtitle - Intro copy.
 * @param {Array<{q: string, a: string}>} items - Questions and answers.
 * @param {{label: string, href: string}} support - Support link.
 * @param {boolean} exclusive - Only one item open at a time (uses the `name` attribute).
 * @param {string} variant - Item style (bordered|cards|plain).
 * @param {string} size - Vertical rhythm (sm|md|lg).
 * @param {string} className - Extra CSS class.
 */
export interface FaqTwoColumnProps {
  title?: string;
  subtitle?: string;
  items?: Array<{ q: string; a: string }>;
  support?: { label: string; href: string };
  exclusive?: boolean;
  variant?: 'bordered' | 'cards' | 'plain';
  size?: 'sm' | 'md' | 'lg';
  className?: string;
}

export function FaqTwoColumn({
  title = 'Frequently asked questions',
  subtitle = 'Everything you need to know about the kit. Canโ€™t find an answer? Our team replies within a day.',
  items = [
    { q: 'Do I need to install a package?', a: 'No. Every component is a standalone .astro file. Copy it into your project, or install the package if you prefer imports.' },
    { q: 'Do the charts need a JavaScript library?', a: 'No. The SVG charts render at build time. A tiny shared script only powers hover tooltips, and every chart includes a data table fallback.' },
    { q: 'Is it accessible?', a: 'Components target WCAG 2.2 AA: semantic HTML, visible focus states, keyboard support and contrast of at least 4.5:1 for text.' },
    { q: 'Can I use it in commercial projects?', a: 'Yes. The kit is MIT licensed. Use it for client work, SaaS products and anything else.' },
    { q: 'How do I change the colors?', a: 'Edit the CSS custom properties in global.css. Every component reads from the same tokens, so one change updates everything.' },
  ],
  support = { label: 'Contact support', href: '#' },
  exclusive = true,
  variant = 'bordered',
  size = 'md',
  className = '',
}: FaqTwoColumnProps) {
  const uid = Math.random().toString(36).slice(2, 8);
  const id = `ftc-${uid}`;
  return (
    <>
      <div className="cq-faq-two-column-cq" data-rk-73cab5="">
      <section className={`ftc ftc--${variant} ftc--${size} ${className}`} aria-labelledby={id} data-rk-73cab5="">
        <div className="ftc__inner" data-rk-73cab5="">
          <div className="ftc__intro" data-rk-73cab5="">
            <h2 id={id} className="ftc__title" data-rk-73cab5="">{title}</h2>
            <p className="ftc__subtitle" data-rk-73cab5="">{subtitle}</p>
            {support && (
              <a className="ftc__support" href={support.href} data-rk-73cab5="">
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" data-rk-73cab5=""><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" data-rk-73cab5="" /></svg>
                {support.label}
              </a>
            )}
          </div>
          <div className="ftc__list" data-rk-73cab5="">
            {items.map((it, i) => (
              <details key={i} className="ftc__item" name={exclusive ? `faq-${uid}` : undefined} open={i === 0} data-rk-73cab5="">
                <summary className="ftc__q" data-rk-73cab5="">
                  <span data-rk-73cab5="">{it.q}</span>
                  <svg className="ftc__chev" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true" data-rk-73cab5=""><path d="M12 5v14M5 12h14" data-rk-73cab5="" /></svg>
                </summary>
                <div className="ftc__a" data-rk-73cab5=""><p data-rk-73cab5="">{it.a}</p></div>
              </details>
            ))}
          </div>
        </div>
      </section>
      </div>
    </>
  );
}

export default FaqTwoColumn;
FaqTwoColumn.css
/* FaqTwoColumn โ€” ported from astro-component-kit (sections/FaqTwoColumn.astro) */

.cq-faq-two-column-cq:where([data-rk-73cab5]) { container-type: inline-size; }
.ftc:where([data-rk-73cab5]) {
  --ftc-py: 5.5rem;
  padding: var(--ftc-py) var(--sp-6, 1.5rem);
  background: var(--c-bg, #050505);
}
.ftc--sm:where([data-rk-73cab5]) { --ftc-py: 3.5rem; }
.ftc--lg:where([data-rk-73cab5]) { --ftc-py: 7.5rem; }
.ftc__inner:where([data-rk-73cab5]) { max-width: 1120px; margin: 0 auto; display: grid; grid-template-columns: 1fr 1.6fr; gap: clamp(2rem, 6vw, 5rem); align-items: start; }
.ftc__intro:where([data-rk-73cab5]) { position: sticky; top: 6rem; }
.ftc__title:where([data-rk-73cab5]) { margin: 0 0 1rem; font-size: clamp(1.9rem, 4vw, 2.5rem); font-weight: 800; letter-spacing: -0.03em; line-height: 1.12; color: var(--c-text-1, #fff); }
.ftc__subtitle:where([data-rk-73cab5]) { margin: 0 0 1.75rem; font-size: 1rem; line-height: 1.65; color: var(--c-text-2, #a3a3a3); }
.ftc__support:where([data-rk-73cab5]) { display: inline-flex; align-items: center; gap: 0.5rem; min-height: 46px; padding: 0 1.25rem; border-radius: var(--r-md, 12px); border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.14); color: var(--c-text-1, #fff); font-weight: 600; text-decoration: none; transition: border-color 0.2s ease; }
.ftc__support:hover:where([data-rk-73cab5]) { border-color: rgb(var(--ink-rgb, 255 255 255) / 0.32); color: var(--c-text-1, #fff); }
.ftc__support:focus-visible:where([data-rk-73cab5]) { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 2px; }
.ftc__list:where([data-rk-73cab5]) { display: grid; }
.ftc--cards:where([data-rk-73cab5]) .ftc__list:where([data-rk-73cab5]) { gap: 0.75rem; }
.ftc--bordered:where([data-rk-73cab5]) .ftc__item:where([data-rk-73cab5]) { border-bottom: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08); }
.ftc--bordered:where([data-rk-73cab5]) .ftc__item:first-child:where([data-rk-73cab5]) { border-top: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08); }
.ftc--cards:where([data-rk-73cab5]) .ftc__item:where([data-rk-73cab5]) { border-radius: var(--r-md, 14px); background: rgb(var(--ink-rgb, 255 255 255) / 0.025); border: 1px solid var(--c-border, rgb(var(--ink-rgb, 255 255 255) / 0.07)); padding-inline: 1.25rem; }
.ftc__q:where([data-rk-73cab5]) {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  min-height: 64px;
  padding: 1rem 0;
  cursor: pointer;
  list-style: none;
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--c-text-1, #fff);
}
.ftc__q:where([data-rk-73cab5])::-webkit-details-marker { display: none; }
.ftc__q:focus-visible:where([data-rk-73cab5]) { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 2px; border-radius: 6px; }
.ftc__chev:where([data-rk-73cab5]) { flex-shrink: 0; color: var(--c-text-2, #a3a3a3); transition: transform 0.25s ease; }
.ftc__item[open]:where([data-rk-73cab5]) .ftc__chev:where([data-rk-73cab5]) { transform: rotate(45deg); color: var(--c-primary-light, #d4a017); }
.ftc__a:where([data-rk-73cab5]) { padding: 0 2.5rem 1.25rem 0; }
.ftc__a:where([data-rk-73cab5]) p:where([data-rk-73cab5]) { margin: 0; font-size: 0.9875rem; line-height: 1.7; color: var(--c-text-2, #a3a3a3); }
.ftc__item[open]:where([data-rk-73cab5]) .ftc__a:where([data-rk-73cab5]) { animation: faq-two-column-ftc-in 0.25s ease; }
@keyframes faq-two-column-ftc-in { from { opacity: 0; transform: translateY(-4px); } }
@container (max-width: 820px) {
  .ftc__inner:where([data-rk-73cab5]) { grid-template-columns: 1fr; }
  .ftc__intro:where([data-rk-73cab5]) { position: static; }
}
@media (prefers-reduced-motion: reduce) { .ftc__chev:where([data-rk-73cab5]) { transition: none; } .ftc__item[open]:where([data-rk-73cab5]) .ftc__a:where([data-rk-73cab5]) { animation: none; } }