Skip to content
6

FAQ 1

Two-column FAQ: sticky heading + contact card on the left, numbered accordion on the right.

Preview

Installation

npx shadcn@latest add https://hirael.com/r/faq-01.json

Code

components/blocks/faq-01.tsx
'use client';

import * as React from 'react';
import { ArrowUpRight, MessageCircleQuestion } from 'lucide-react';

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from '@/registry/hirael/bases/radix/ui/accordion';
import { Button } from '@/registry/hirael/bases/radix/ui/button';
import { Card, CardContent } from '@/registry/hirael/bases/radix/ui/card';

const FAQS = [
  {
    q: 'How is Hirael different from shadcn/ui?',
    a: 'Hirael is a peer, not a replacement. shadcn/ui covers the canonical primitives: Button, Dialog, Select. Hirael ships the dense, real-world components every product still has to build: multi-select, tag input, year picker, combobox with async loading, password strength. Both registries use the same CLI and the same install URL pattern, so you can mix and match.',
  },
  {
    q: 'Is Hirael a dependency I install?',
    a: 'No. Hirael is a registry, not a package. `npx shadcn add` copies the component source straight into your repo at components/ui/*. You own the code, you can edit it, and there is zero runtime dependency on Hirael.',
  },
  {
    q: 'What is the dual-API contract?',
    a: 'Every Hirael component ships two surface areas in the same file: a compound API (Root + named parts, for full layout control) and a single-prop API (one component, options-as-prop, for the 90% case). They share state; you can drop in either depending on the use case.',
  },
  {
    q: 'Can I theme it?',
    a: 'Yes. Hirael reads the same CSS variables as shadcn/ui. The /theme playground lets you tune the accent live; every component re-skins in place. Drop-in compatible with any shadcn theme.',
  },
  {
    q: 'Does it work with React Server Components?',
    a: "Yes. Components that need client interactivity are marked 'use client' at the top of their file. Static components can render on the server. Both work in App Router and Pages Router.",
  },
  {
    q: 'Is it production-ready?',
    a: "Yes. Every shipped component is typed end-to-end, keyboard-accessible, and SSR-safe. We don't tag a component as stable until it has both API shapes, focus-management coverage, and a working demo in the registry.",
  },
] as const;

const Faq01 = () => {
  return (
    <section className="bg-background py-20 md:py-28">
      <div className="container grid w-full grid-cols-1 gap-12 lg:grid-cols-12 lg:gap-16">
        <div className="flex flex-col gap-6 lg:col-span-5">
          <div className="sticky top-12 flex flex-col gap-6">
            <span className="inline-flex w-fit items-center gap-2 font-mono text-[10px] uppercase tracking-[0.14em] text-foreground">
              <span className="size-1 rounded-full bg-foreground" />
              FAQ · the short answers
            </span>
            <h2 className="font-serif text-4xl font-medium leading-[1.04] tracking-tight sm:text-5xl md:text-6xl">
              Frequently <span className="italic text-foreground">unobvious</span> questions.
            </h2>
            <p className="text-sm text-muted-foreground">
              The questions teams ask in their first ten minutes with Hirael, answered the way we&apos;d want them
              answered. If something isn&apos;t here, the issue tracker is open.
            </p>

            <Card className="mt-2 gap-3 py-5">
              <CardContent className="flex flex-col gap-3">
                <div className="inline-flex items-center gap-2">
                  <MessageCircleQuestion className="size-4 text-foreground" />
                  <span className="font-mono text-[10px] uppercase tracking-[0.12em] text-muted-foreground">
                    still stuck?
                  </span>
                </div>
                <p className="text-sm">Drop a question in the repo. Responses usually within a day.</p>
                <Button asChild variant="outline" size="sm" className="w-fit">
                  <a href="#">
                    Open an issue
                    <ArrowUpRight className="size-3.5" />
                  </a>
                </Button>
              </CardContent>
            </Card>
          </div>
        </div>

        <div className="lg:col-span-7">
          <Accordion type="single" collapsible defaultValue="item-0" className="border-y border-border">
            {FAQS.map((f, i) => (
              <AccordionItem key={f.q} value={`item-${i}`} className="px-1">
                <AccordionTrigger>
                  <span className="flex items-baseline gap-4">
                    <span className="font-mono text-[10px] uppercase tracking-[0.14em] text-muted-foreground">
                      {String(i + 1).padStart(2, '0')}
                    </span>
                    <span>{f.q}</span>
                  </span>
                </AccordionTrigger>
                <AccordionContent>
                  <div className="ms-10 max-w-2xl">{f.a}</div>
                </AccordionContent>
              </AccordionItem>
            ))}
          </Accordion>
        </div>
      </div>
    </section>
  );
};

export default Faq01;

Dependencies

shadcn registry

buttonaccordioncard

npm

lucide-react