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.jsonCode
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'd want them
answered. If something isn'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