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/ui/accordion";
import { Button } from "@/registry/hirael/ui/button";
import { Card, CardContent } from "@/registry/hirael/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;

export default function 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>
  );
}

Dependencies

shadcn registry

buttonaccordioncard

npm

@radix-ui/react-accordionlucide-react