Component
Accordion
Expandable questions or sections with keyboard navigation.
npx -y github:anwarlemu/agentcard-brand-cli#release add accordionIt lets AI agents pay at real checkouts. You fund a card, set what it can buy, and your agent uses it like a person would.
Questions, answered
It lets AI agents pay at real checkouts. You fund a card, set what it can buy, and your agent uses it like a person would.
Usage
Use for FAQs or details that can stay collapsed. The InWindow example adds topic tabs and a containing window.
- Chevrons or typed plus signs
- Bold questions
- Cards around each question
- More than one list open by default
Dependencies: @radix-ui/react-accordion.
Example
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Window } from "@/components/ui/window";
const GENERAL = [
{ q: "What does Agentcard do?", a: "It lets AI agents pay at real checkouts. You fund a card, set what it can buy, and your agent uses it like a person would." },
{ q: "Do I need to write code?", a: "No. Connect your agent with the command line tool or the API, or share a card with an agent you already use." },
{ q: "Is my card number shared with the agent?", a: "Never. The agent gets a token that only works within the limits you set, and you can pause it at any time." },
{ q: "What does it cost?", a: "Starting is free. You pay per card and per purchase as your agents buy more; see the pricing page for details." },
];
function Faq({ items }: { items: { q: string; a: string }[] }) {
return (
<Accordion type="single" collapsible defaultValue="item-0" className="w-full max-w-170">
{items.map((item, i) => (
<AccordionItem key={item.q} value={`item-${i}`}>
<AccordionTrigger>{item.q}</AccordionTrigger>
<AccordionContent>{item.a}</AccordionContent>
</AccordionItem>
))}
</Accordion>
);
}
export function Site() {
return <Faq items={GENERAL} />;
}
export function InWindow() {
return (
<Window name="faq.help / Agentcard" className="mx-auto max-w-198" bodyClassName="flex flex-col items-center px-4 pt-10 pb-12 md:px-14">
<h2 className="text-h2 leading-heading tracking-tighter">Questions, answered</h2>
<Tabs defaultValue="general" className="mt-9 w-full max-w-170 items-center gap-9">
<TabsList className="w-full">
<TabsTrigger value="general">General</TabsTrigger>
<TabsTrigger value="vault">Vault</TabsTrigger>
<TabsTrigger value="issuing">Issuing</TabsTrigger>
</TabsList>
<TabsContent value="general" className="w-full">
<Faq items={GENERAL} />
</TabsContent>
<TabsContent value="vault" className="w-full">
<Faq items={GENERAL.slice(2)} />
</TabsContent>
<TabsContent value="issuing" className="w-full">
<Faq items={GENERAL.slice(1, 3)} />
</TabsContent>
</Tabs>
</Window>
);
}Source
"use client";
import * as React from "react";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { cn } from "@/lib/utils";
// The brand's FAQ list (agentcard.sh /, .faq-list under .v7-page, measured as rendered): a 14 percent ink rule above
// the first question and a 20 percent one under each; the question in the 14px display face at 500 (tracked -0.01em,
// 1.2 leading, 20px by 14px of padding, 6px corners), blue and on a faint wash under the pointer (the wash eases in
// 160ms, the color does not); a drawn + (a bar across and a bar down in a 30px box, not a glyph) that turns an eighth
// into an x when open (220ms ease-out). Open, the question and its mark stay blue. The answer is 14px Inter at 1.8
// leading, 68 percent ink at 80 percent opacity, 540px wide; it slides open in 200ms ease-out (and shut in 200ms) and
// fades down 4px into place (240ms, 40ms late). Reduced motion opens it at once.
function Accordion(props: React.ComponentProps<typeof AccordionPrimitive.Root>) {
return <AccordionPrimitive.Root data-slot="accordion" {...props} />;
}
function AccordionItem({ className, ...props }: React.ComponentProps<typeof AccordionPrimitive.Item>) {
return <AccordionPrimitive.Item data-slot="accordion-item" className={cn("border-b border-b-line-mid first:border-t first:border-t-line", className)} {...props} />;
}
/** The FAQ's mark: a 12px plus drawn in two 1.5px bars, in a 30px box so a column of them lines up. */
function AccordionMark({ className }: { className?: string }) {
return (
<span aria-hidden data-slot="accordion-mark" className={cn("grid h-3.5 w-7.5 shrink-0 place-items-center self-center text-fg-faint transition-[rotate,color] duration-220 ease-out motion-reduce:transition-none", className)}>
<svg viewBox="0 0 12 12" className="size-3 fill-none stroke-current [stroke-width:1.5]">
<path d="M0 6h12M6 0v12" />
</svg>
</span>
);
}
function AccordionTrigger({ className, children, icon, ...props }: React.ComponentProps<typeof AccordionPrimitive.Trigger> & { icon?: React.ReactNode | null }) {
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
data-slot="accordion-trigger"
className={cn(
"group flex flex-1 cursor-pointer items-center justify-between gap-3.75 rounded-sm px-3.5 py-5 text-left font-display text-body-sm font-medium [letter-spacing:-0.01em] [line-height:1.2] text-fg transition-[background-color] duration-160 ease-out outline-none hover:bg-wash-hover hover:text-fg-brand focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid focus-visible:outline-focus-ring disabled:pointer-events-none disabled:opacity-50 data-[state=open]:text-fg-brand motion-reduce:transition-none",
className,
)}
{...props}
>
{children}
{icon === undefined ? <AccordionMark className="group-hover:text-fg-brand group-data-[state=open]:rotate-45 group-data-[state=open]:text-fg-brand" /> : icon}
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);
}
function AccordionContent({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Content>) {
return (
<AccordionPrimitive.Content
data-slot="accordion-content"
className="overflow-hidden text-body-sm [line-height:1.8] text-fg-muted data-[state=closed]:animate-accordion-up data-[state=closed]:[animation-duration:var(--ds-duration-base)] data-[state=open]:animate-accordion-down motion-reduce:animate-none"
{...props}
>
<div className={cn("max-w-135 px-3.5 pb-5.5 opacity-80 transition-[opacity,translate] delay-40 duration-240 ease-out starting:-translate-y-1 starting:opacity-0 motion-reduce:transition-none", className)}>{children}</div>
</AccordionPrimitive.Content>
);
}
export { Accordion, AccordionContent, AccordionItem, AccordionMark, AccordionTrigger };Reference: agentcard-website src/app/globals.css (.faq-list, .v7-page summary, .v7-page details > p); live https://www.agentcard.sh/ (#faq .faq-list, computed).