Inkbox

Component

Accordion

Sections that open in place: 14px ink labels with a caret at the right, ruled by the faint lilac line.

npx -y github:anwarlemu/inkbox-brand-cli#release add accordion
Preview

It gives each agent a stable hostname (acme.inkboxwire.com) and routes inbound traffic to wherever the agent runs, with TLS at the edge or passed through.

Multiple

acme-support@inboxmail.com receives and sends mail for this agent.

Any state. Calls and SMS are on; RCS needs a dedicated line.

Usage

Use for settings or answers people open one at a time (advanced options, FAQs). Pass type="single" collapsible for one open at a time, type="multiple" for several. Keep the label a short phrase; the content is 14px secondary text or a group of fields.

Avoid

  • Bold or purple trigger labels
  • A chevron at the left
  • Boxing each item in a card
  • Opening animation longer than 200ms

Exports: Accordion, AccordionContent, AccordionItem, AccordionTrigger. This component is a client component.

Dependencies: radix-ui, @phosphor-icons/react.

Example

examples/accordion.tsx
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";​export function Preview() {  return (    <Accordion type="single" collapsible defaultValue="tunnel" className="w-full max-w-120">      <AccordionItem value="tunnel">        <AccordionTrigger>What does the tunnel do?</AccordionTrigger>        <AccordionContent>It gives each agent a stable hostname (acme.inkboxwire.com) and routes inbound traffic to wherever the agent runs, with TLS at the edge or passed through.</AccordionContent>      </AccordionItem>      <AccordionItem value="phone">        <AccordionTrigger>Can one agent have a phone number and iMessage?</AccordionTrigger>        <AccordionContent>Yes. Turn on Phone Number for calls and SMS, and iMessage for a shared or dedicated line. Each channel keeps its own contact rules.</AccordionContent>      </AccordionItem>      <AccordionItem value="vault">        <AccordionTrigger>Who can read the vault?</AccordionTrigger>        <AccordionContent>Only people with the vault key. Encryption and decryption happen in the browser, so the server never sees your secrets.</AccordionContent>      </AccordionItem>    </Accordion>  );}​export function Multiple() {  return (    <Accordion type="multiple" defaultValue={["email", "calls"]} className="w-full max-w-120">      <AccordionItem value="email">        <AccordionTrigger>Email</AccordionTrigger>        <AccordionContent>acme-support@inboxmail.com receives and sends mail for this agent.</AccordionContent>      </AccordionItem>      <AccordionItem value="calls">        <AccordionTrigger>Calls and texts</AccordionTrigger>        <AccordionContent>Any state. Calls and SMS are on; RCS needs a dedicated line.</AccordionContent>      </AccordionItem>      <AccordionItem value="a2a" disabled>        <AccordionTrigger>Agent2Agent (not enabled)</AccordionTrigger>        <AccordionContent>Turn on Agent2Agent to publish this identity&apos;s Agent Card.</AccordionContent>      </AccordionItem>    </Accordion>  );}

Source

components/ui/accordion.tsx
"use client";​import * as React from "react";import { Accordion as AccordionPrimitive } from "radix-ui";import { CaretDownIcon } from "@phosphor-icons/react/ssr";​import { cn } from "@/lib/utils";​// Sections that open in place, drawn as the dialog's Advanced settings row (Figma 427:2715, Create Agent Identity): a// 14px regular ink label with a 20px caret at the right, items ruled by the faint lilac line. The panel opens with its// height (200ms, the strong ease-out; closing is quicker) and the caret turns to point up.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-line-subtle last:border-b-0", className)} {...props} />;}​function AccordionTrigger({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {  return (    <AccordionPrimitive.Header className="flex">      <AccordionPrimitive.Trigger        data-slot="accordion-trigger"        className={cn(          "group/accordion-trigger flex flex-1 items-center justify-between gap-4 rounded-control py-3.5 text-left font-sans text-body leading-body text-fg outline-none transition-colors duration-150 ease-out hover:text-fg-brand focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-ring disabled:pointer-events-none disabled:text-fg-muted motion-reduce:transition-none",          className,        )}        {...props}      >        {children}        <CaretDownIcon aria-hidden data-slot="accordion-trigger-icon" weight="bold" className="size-4 shrink-0 text-icon-default transition-transform duration-200 ease-out group-data-[state=open]/accordion-trigger:rotate-180 motion-reduce:transition-none" />      </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 leading-body text-fg-secondary data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down" {...props}>      <div className={cn("pb-4", className)}>{children}</div>    </AccordionPrimitive.Content>  );}​export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };

Reference: Figma 427:2715: Create Agent Identity (Advanced settings - tunnel mode, phone state, line sharing).