Collapsible
kumo-svelte

Kumo is Cloudflare's new design system.

<script lang="ts">
  import { Collapsible, Text } from '$lib';

  let isOpen = $state(true);
</script>

<div class="w-full">
  <Collapsible.Root bind:open={isOpen}>
    <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>
    <Collapsible.DefaultPanel>
      <Text>Kumo is Cloudflare's new design system.</Text>
    </Collapsible.DefaultPanel>
  </Collapsible.Root>
</div>

Installation

Barrel

import { Collapsible } from 'kumo-svelte';

Granular

import { Collapsible } from 'kumo-svelte/components/collapsible';

Usage

Collapsible uses a compound component pattern for full composition control.

With Default Styling

Use Collapsible.DefaultTrigger and Collapsible.DefaultPanel for the classic Kumo style:

<script lang="ts">  import {    Collapsible  } from 'kumo-svelte';  let open = $state(false);</script><Collapsible.Root bind:open>  <Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger>  <Collapsible.DefaultPanel>    Content with border-left accent styling.  </Collapsible.DefaultPanel></Collapsible.Root>

Custom Trigger

Use Collapsible.Trigger for full control over the trigger element:

<script lang="ts">  import { Collapsible } from 'kumo-svelte';  let open = $state(false);</script><Collapsible.Root bind:open>  <Collapsible.Trigger class="rounded-lg bg-kumo-base px-3 py-2 text-sm ring ring-kumo-line">    {open ? 'Hide' : 'Show'} details  </Collapsible.Trigger>  <Collapsible.Panel class="mt-2 rounded-lg bg-kumo-tint p-4">    Custom styled panel content.  </Collapsible.Panel></Collapsible.Root>

Examples

Basic

<script lang="ts">
  import { Collapsible, Text } from '$lib';

  let isOpen = $state(false);
</script>

<div class="w-full">
  <Collapsible.Root bind:open={isOpen}>
    <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>
    <Collapsible.DefaultPanel>
      <Text>Kumo is Cloudflare's new design system.</Text>
    </Collapsible.DefaultPanel>
  </Collapsible.Root>
</div>

Multiple Items

<script lang="ts">
  import { Collapsible, Text } from '$lib';

  let open1 = $state(false);
  let open2 = $state(false);
  let open3 = $state(false);
</script>

<div class="w-full space-y-2">
  <Collapsible.Root bind:open={open1}>
    <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>
    <Collapsible.DefaultPanel>
      <Text>Kumo is Cloudflare's new design system.</Text>
    </Collapsible.DefaultPanel>
  </Collapsible.Root>

  <Collapsible.Root bind:open={open2}>
    <Collapsible.DefaultTrigger>How do I use it?</Collapsible.DefaultTrigger>
    <Collapsible.DefaultPanel>
      <Text>Install the components and import them into your project.</Text>
    </Collapsible.DefaultPanel>
  </Collapsible.Root>

  <Collapsible.Root bind:open={open3}>
    <Collapsible.DefaultTrigger>Is it open source?</Collapsible.DefaultTrigger>
    <Collapsible.DefaultPanel>
      <Text>Check the repository for license information.</Text>
    </Collapsible.DefaultPanel>
  </Collapsible.Root>
</div>

Custom Trigger

Use Collapsible.Trigger for full control:

<script lang="ts">
  import { Collapsible, Text } from '$lib';

  let isOpen = $state(false);
</script>

<div class="w-full">
  <Collapsible.Root bind:open={isOpen}>
    <Collapsible.Trigger
      class="group flex h-6.5 w-max shrink-0 items-center gap-1 rounded-md border-0 bg-kumo-base px-2 text-xs font-medium !text-kumo-default shadow-xs ring ring-kumo-hairline select-none not-disabled:hover:bg-kumo-tint focus:outline-none focus:ring-kumo-focus/50 focus-visible:ring-2 focus-visible:ring-kumo-brand disabled:cursor-not-allowed disabled:bg-kumo-base/50 disabled:!text-kumo-default/70 data-[state=open]:bg-kumo-base"
    >
      {isOpen ? 'Hide details' : 'Show details'}
    </Collapsible.Trigger>
    <Collapsible.Panel class="mt-3 rounded-lg bg-kumo-tint p-4">
      <Text>
        This panel uses custom styling instead of the default border-left accent.
      </Text>
    </Collapsible.Panel>
  </Collapsible.Root>
</div>

Accordion Pattern

Control which item is open to create an accordion where only one item can be expanded at a time:

Kumo is Cloudflare's new design system built on Base UI and Tailwind CSS v4.

<script lang="ts">
  import { Collapsible, Text } from '$lib';

  let activeIndex = $state<number | null>(0);

  const items = [
    {
      title: 'What is Kumo?',
      content: "Kumo is Cloudflare's new design system built on Base UI and Tailwind CSS v4."
    },
    {
      title: 'How do I install it?',
      content: 'Run `npm install @cloudflare/kumo` and import the components you need.'
    },
    {
      title: 'Is it accessible?',
      content: 'Yes! Kumo is built on Base UI which provides excellent accessibility out of the box.'
    }
  ];
</script>

<div class="w-full space-y-2">
  {#each items as item, i}
    <Collapsible.Root
      open={activeIndex === i}
      onOpenChange={(open) => (activeIndex = open ? i : null)}
    >
      <Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger>
      <Collapsible.DefaultPanel>
        <Text>{item.content}</Text>
      </Collapsible.DefaultPanel>
    </Collapsible.Root>
  {/each}
</div>

Sub-components

ComponentDescription
Collapsible.RootManages open state. Pass open and onOpenChange for controlled mode.
Collapsible.TriggerButton that toggles visibility.
Collapsible.PanelContainer for collapsible content.
Collapsible.DefaultTriggerPre-styled trigger with text label and animated caret icon.
Collapsible.DefaultPanelPre-styled panel with border-left accent and standard spacing.

API Reference

Collapsible

Convenience component that renders the default trigger and panel composition.

PropTypeDefaultDescription
trigger Snippet-trigger prop.
children Snippet-Child snippet rendered by the component.
class string-Additional classes merged onto the root element.
open boolean-Controlled open state.
defaultOpen booleanfalseInitial uncontrolled open state.
title string-Title content.
disabled booleanfalseDisables the component.
onOpenChange (open: boolean) => void-Called when open state changes.
autoScrollOnOpen booleanfalseScrolls newly expanded sidebar content into view after opening.
onOpenChangeComplete (open: boolean) => void-Called after the open-state transition completes.

Collapsible.Root

PropTypeDefaultDescription
open boolean-Controlled open state.
defaultOpen booleanfalseInitial uncontrolled open state.
onOpenChange (open: boolean) => void-Called when open state changes.
disabled booleanfalseDisables the component.
onOpenChangeComplete (open: boolean) => void-Called after the open-state transition completes.

Collapsible.Trigger

PropTypeDefaultDescription
disabled booleanfalseDisables the component.
type 'button' | 'submit' | 'reset'"button"Element or semantic type.

Collapsible.Panel

PropTypeDefaultDescription
keepMounted booleanfalsekeepMounted prop.
forceMount booleanfalseforceMount prop.
hiddenUntilFound booleantruehiddenUntilFound prop.

Collapsible.DefaultTrigger

PropTypeDefaultDescription
disabled booleanfalseDisables the component.

Collapsible.DefaultPanel

Accepts all Collapsible.Panel props in addition to the ones listed below.

PropTypeDefaultDescription
keepMounted booleanfalsekeepMounted prop.
forceMount booleanfalseforceMount prop.
hiddenUntilFound booleantruehiddenUntilFound prop.