Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

Accordion with Icons and Plus/Minus Toggle for Ark UI

Workspace rows with a category icon and a plus that turns into a minus, with Documents open first.

Documents, Projects, Workspace settings, and Team members each have an icon, and a plus on the right that turns into a minus. Documents starts open.

Use it when both the category and the toggle need to be obvious. For one section, use a Collapsible. In React, Ark UI does not supply the category icon.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Anatomy

Accordion anatomy: root, item, item trigger, item content, item indicator

Usage

<Accordion
  className="w-full max-w-md -space-y-px"
  defaultValue={["documents"]}
>
  {items.map((item) => (
    <AccordionItem
      className="overflow-hidden border bg-background px-4 first:rounded-t-lg last:rounded-b-lg"
      key={item.value}
      value={item.value}
    >
      <AccordionTrigger className="hover:no-underline **:data-[slot=accordion-trigger-icon]:hidden">
        <span className="flex w-full items-center justify-between gap-3">
          <span className="flex items-center gap-3">
            <item.icon
              aria-hidden="true"
              className="size-4 shrink-0 text-muted-foreground"
            />
            <span className="text-start">{item.title}</span>
          </span>
          <span className="relative size-4 shrink-0">
            <PlusIcon
              aria-hidden="true"
              className="absolute inset-0 size-4 text-muted-foreground transition-opacity duration-200 group-aria-expanded/accordion-trigger:opacity-0"
            />
            <MinusIcon
              aria-hidden="true"
              className="absolute inset-0 size-4 text-muted-foreground opacity-0 transition-opacity duration-200 group-aria-expanded/accordion-trigger:opacity-100"
            />
          </span>
        </span>
      </AccordionTrigger>
{/* The rest of the file is under Installation. */}

FAQ

Where do the category icons come from?

Each item stores FileTextIcon, FolderIcon, SettingsIcon or UsersIcon at size-4, with text-muted-foreground and aria-hidden, in a gap-3 row before the title.

How does the plus turn into a minus?

**:data-[slot=accordion-trigger-icon]:hidden on AccordionTrigger hides the built-in chevron. PlusIcon and MinusIcon share one relative size-4 box, and group-aria-expanded/accordion-trigger fades the plus out and the minus in over duration-200. Both icons are aria-hidden and text-muted-foreground.

Why is the answer indented?

ps-7 on AccordionContent matches the 16px icon plus the 12px gap-3, so the answer lines up under the title.

Why does Documents start open?

defaultValue={["documents"]} opens Documents on first render. The string matches that item's value.

How do I let several items stay open at once?

One open item is the default. Add multiple to Accordion to let several stay open, and list every item that should start open in the defaultValue array.

How do the row borders meet?

-space-y-px on Accordion pulls the rows together so neighboring borders share one line. Each AccordionItem has border, px-4, first:rounded-t-lg and last:rounded-b-lg.

API Reference

Accordion

Sets defaultValue={["documents"]} and value={item.value}. The rest is on the Accordion page.