Components

Collapsible

A panel that a trigger opens and closes

Import
import { Collapsible } from "@nyte-ai/ui/collapsible";

A trigger that shows and hides one panel. Use it for detail a reader opens on demand, such as tool output or earlier messages.

Usage

  • defaultOpen leaves the panel uncontrolled. open with onOpenChange controls it.
  • Use variant="plain" when another styled part, such as Row.Primary, renders the trigger.
  • Collapsible.Root, Collapsible.Panel, and Collapsible.Preview bring no look of their own. Lay them out with xstyle.
  • Collapsible.Panel defaults hiddenUntilFound to true. The closed panel stays in the DOM, and find-in-page can match its text and open it. Pass hiddenUntilFound={false} to unmount it.
  • Use Collapsible.Preview to keep content in view while closed when that content has controls of its own. Closed, a press anywhere in it opens the collapsible, and a collapsible pressed inside it opens without closing. Open, it is a plain container.

Anatomy

<Collapsible.Root>
  <Collapsible.Trigger>
    <Collapsible.Chevron />
  </Collapsible.Trigger>
  <Collapsible.Panel />
  <Collapsible.Preview />
</Collapsible.Root>

Examples

Basic

<Collapsible.Root>
  <Collapsible.Trigger>
    <Collapsible.Chevron />
    Advanced settings
  </Collapsible.Trigger>
  <Collapsible.Panel>
    Tools run without a confirmation prompt while this session is trusted.
  </Collapsible.Panel>
</Collapsible.Root>

Controlled

const [open, setOpen] = useState(false);

<Collapsible.Root open={open} onOpenChange={setOpen}>
  <Collapsible.Trigger>
    Earlier messages
    <Collapsible.Chevron />
  </Collapsible.Trigger>
  <Collapsible.Panel>{messages}</Collapsible.Panel>
</Collapsible.Root>;

A row that opens a panel

<Collapsible.Root open={expanded} onOpenChange={setExpanded}>
  <Row>
    <Row.Primary render={<Collapsible.Trigger variant="plain" />}>
      <Row.Leading>
        <Icon name={expanded ? "folder-open" : "folder"} size={14} />
      </Row.Leading>
      <Row.Label>{name}</Row.Label>
    </Row.Primary>
  </Row>
  <Collapsible.Panel>{sessions}</Collapsible.Panel>
</Collapsible.Root>

A preview that opens on press

const [open, setOpen] = useState(false);

<Collapsible.Root open={open} onOpenChange={setOpen}>
  <Collapsible.Trigger>
    Working
    <Collapsible.Chevron />
  </Collapsible.Trigger>
  <Collapsible.Preview>{steps}</Collapsible.Preview>
</Collapsible.Root>;

Props

Every part takes xstyle, and className and style as plain values, not functions of state. See Theming.

Trigger

PropTypeDefaultDescription
variant"disclosure" | "plain""disclosure"Inline toggle look, or a bare button.

Chevron

Renders a <span> with aria-hidden, holding a chevron-right icon. It takes every <span> prop, plus:

PropTypeDefaultDescription
sizenumber11Icon size in pixels.

Preview

Renders a <div> and takes every <div> prop.

The reference tables below come from Base UI, MIT, © Material-UI SAS.

Root

Groups all parts of the collapsible. Renders a <div> element.

Root Props:

PropTypeDefaultDescription
defaultOpenbooleanfalseWhether the collapsible panel is initially open. To render a controlled collapsible, use the open prop instead.
openboolean-Whether the collapsible panel is currently open. To render an uncontrolled collapsible, use the defaultOpen prop instead.
onOpenChange((open: boolean, eventDetails: Collapsible.Root.ChangeEventDetails) => void)-Event handler called when the panel is opened or closed.
disabledbooleanfalseWhether the component should ignore user interaction.
classNamestring | ((state: Collapsible.Root.State) => string | undefined)-CSS class applied to the element, or a function that returns a class based on the component's state.
styleReact.CSSProperties | ((state: Collapsible.Root.State) => React.CSSProperties | undefined)-Style applied to the element, or a function that returns a style object based on the component's state.
renderReactElement | ((props: HTMLProps, state: Collapsible.Root.State) => ReactElement)-Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.

Root Data Attributes:

AttributeTypeDescription
data-open-Present when the collapsible is open.
data-closed-Present when the collapsible is closed.
data-starting-style-Present when the collapsible begins animating in.
data-ending-style-Present when the collapsible is animating out.

Trigger

A button that opens and closes the collapsible panel. Renders a <button> element.

Trigger Props:

PropTypeDefaultDescription
nativeButtonbooleantrueWhether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).
classNamestring | ((state: Collapsible.Trigger.State) => string | undefined)-CSS class applied to the element, or a function that returns a class based on the component's state.
styleReact.CSSProperties | ((state: Collapsible.Trigger.State) => React.CSSProperties | undefined)-Style applied to the element, or a function that returns a style object based on the component's state.
renderReactElement | ((props: HTMLProps, state: Collapsible.Trigger.State) => ReactElement)-Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.

Trigger Data Attributes:

AttributeTypeDescription
data-panel-open-Present when the collapsible panel is open.

Panel

A panel with the collapsible contents. Renders a <div> element.

Panel Props:

PropTypeDefaultDescription
hiddenUntilFoundbooleanfalseAllows the browser's built-in page search to find and expand the panel contents. Overrides the keepMounted prop and uses hidden="until-found" to hide the element without removing it from the DOM.
classNamestring | ((state: Collapsible.Panel.State) => string | undefined)-CSS class applied to the element, or a function that returns a class based on the component's state.
styleReact.CSSProperties | ((state: Collapsible.Panel.State) => React.CSSProperties | undefined)-Style applied to the element, or a function that returns a style object based on the component's state.
keepMountedbooleanfalseWhether to keep the element in the DOM while the panel is hidden. This prop is ignored when hiddenUntilFound is used.
renderReactElement | ((props: HTMLProps, state: Collapsible.Panel.State) => ReactElement)-Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.

Panel Data Attributes:

AttributeTypeDescription
data-open-Present when the collapsible panel is open.
data-closed-Present when the collapsible panel is closed.
data-starting-style-Present when the panel begins animating in.
data-ending-style-Present when the panel is animating out.

Panel CSS Variables:

VariableTypeDescription
--collapsible-panel-heightnumberThe collapsible panel's height.
--collapsible-panel-widthnumberThe collapsible panel's width.

Accessibility

  • The trigger renders a native <button> with aria-expanded, and aria-controls pointing at the panel while it is open. Enter and Space toggle it.
  • Rendering the trigger as something other than a <button> needs nativeButton={false}.
  • disclosure draws a focus ring. With plain, the rendered part owns focus styling.
  • The preview takes no role and no tab stop. The trigger stays the control, and controls inside the preview keep their own roles.