Components

Collapsible

Headless disclosure primitives for showing and hiding one section of content.

When to Use

Use Collapsible when one control reveals one related block, such as advanced settings, extra details, or a filter panel. Use Accordion when several named sections belong together and users move between them. Use Dialog when the content must interrupt the page in a separate modal layer.

Features

  • Supports controlled and uncontrolled open state.
  • Connects Trigger and Content with generated ARIA IDs.
  • Supports disabled triggers and custom trigger rendering.
  • Keeps Content mounted on request for exit animations.
  • Exposes open state and measured content height for consumer-owned animation.

Import

import { Collapsible } from "@flowstack-ui/atom";

Anatomy

<Collapsible.Root>
  <Collapsible.Trigger />
  <Collapsible.Content />
</Collapsible.Root>

API Reference

Root

Owns the disclosure state and shares it with Trigger and Content. It renders a div by default and accepts native div props.

PropTypeDefault
openboolean-
defaultOpenbooleanfalse
onOpenChange(open: boolean) => void-
disabledbooleanfalse
asChildbooleanfalse
renderRenderProp-
Data attributeValues
[data-slot]"collapsible"
[data-state]"open" | "closed"
[data-disabled]Present when disabled

Trigger

Toggles Content. It renders a native button by default and preserves button keyboard behavior; custom elements receive button semantics.

PropTypeDefault
asChildbooleanfalse
renderRenderProp-
ARIA attributeValues
role"button" for a custom rendered element
aria-expandedCurrent open state
aria-controlsGenerated Content ID
aria-disabled"true" when Root is disabled
Data attributeValues
[data-slot]"collapsible-trigger"
[data-state]"open" | "closed"
[data-disabled]Present when disabled

Content

Contains the disclosed region and identifies Trigger as its accessible label. It unmounts after closing by default, while keepMounted leaves a hidden copy available for consumer-owned exit animation.

PropTypeDefault
keepMountedbooleanfalse
ARIA attributeValues
role"region"
aria-labelledbyGenerated Trigger ID
Data attributeValues
[data-slot]"collapsible-content"
[data-state]"open" | "closed"

Content also sets --content-height to its measured height for optional consumer-owned animation.

Examples

Basic Disclosure

import { Collapsible } from "@flowstack-ui/atom";

export function AdvancedSettings() {
  return (
    <Collapsible.Root>
      <Collapsible.Trigger>Advanced settings</Collapsible.Trigger>
      <Collapsible.Content>
        These settings are only needed for custom configurations.
      </Collapsible.Content>
    </Collapsible.Root>
  );
}

Controlled State

import { useState } from "react";
import { Collapsible } from "@flowstack-ui/atom";

export function ControlledDetails() {
  const [open, setOpen] = useState(false);

  return (
    <Collapsible.Root open={open} onOpenChange={setOpen}>
      <Collapsible.Trigger>
        {open ? "Hide details" : "Show details"}
      </Collapsible.Trigger>
      <Collapsible.Content>Additional account information.</Collapsible.Content>
    </Collapsible.Root>
  );
}

Accessibility

Collapsible follows the WAI-ARIA Disclosure pattern. Trigger exposes whether Content is open and points to it with aria-controls. Content is a named region. Give Trigger clear text that tells the user what will be revealed.

KeyDescription
EnterToggles Content while the native or custom button has focus.
SpaceToggles Content while the native or custom button has focus.

Changelog

See CHANGELOG.md.