Kumo is Cloudflare's new design system.
import { Collapsible, Text } from "@cloudflare/kumo";
import { useState } from "react";
/**
* Hero demo using DefaultTrigger and DefaultPanel for classic Kumo styling.
*/
export function CollapsibleHeroDemo() {
const [isOpen, setIsOpen] = useState(true);
return (
<div className="w-full">
<Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>
<Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
<Text>Kumo is Cloudflare's new design system.</Text>
</Collapsible.DefaultPanel>
</Collapsible.Root>
</div>
);
}安装
批量导入
import { Collapsible } from "@cloudflare/kumo";按需导入
import { Collapsible } from "@cloudflare/kumo/components/collapsible";用法
Collapsible 采用复合组件模式,提供完整的组合控制能力。
默认样式
使用 DefaultTrigger 和 DefaultPanel 获得经典的 Kumo 样式:
import { Collapsible } from "@cloudflare/kumo";
export default function Example() {
const [open, setOpen] = useState(false);
return (
<Collapsible.Root open={open} onOpenChange={setOpen}>
<Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
Content with border-left accent styling.
</Collapsible.DefaultPanel>
</Collapsible.Root>
);
}自定义触发器
在 Trigger 上使用 render 属性,即可完全掌控触发器元素:
<Collapsible.Root open={open} onOpenChange={setOpen}>
<Collapsible.Trigger render={<Button variant="ghost" />}>
{open ? "Hide" : "Show"} details
</Collapsible.Trigger>
<Collapsible.Panel className="mt-2 p-4 bg-kumo-tint rounded-lg">
Custom styled panel content.
</Collapsible.Panel>
</Collapsible.Root>示例
基本
import { Collapsible, Text } from "@cloudflare/kumo";
import { useState } from "react";
/**
* Basic usage with default styling components.
*/
export function CollapsibleBasicDemo() {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="w-full">
<Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>
<Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
<Text>Kumo is Cloudflare's new design system.</Text>
</Collapsible.DefaultPanel>
</Collapsible.Root>
</div>
);
}多个可折叠项
import { Collapsible, Text } from "@cloudflare/kumo";
import { useState } from "react";
/**
* Multiple independent collapsibles.
*/
export function CollapsibleMultipleDemo() {
const [open1, setOpen1] = useState(false);
const [open2, setOpen2] = useState(false);
const [open3, setOpen3] = useState(false);
return (
<div className="w-full space-y-2">
<Collapsible.Root open={open1} onOpenChange={setOpen1}>
<Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
<Text>Kumo is Cloudflare's new design system.</Text>
</Collapsible.DefaultPanel>
</Collapsible.Root>
<Collapsible.Root open={open2} onOpenChange={setOpen2}>
<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 open={open3} onOpenChange={setOpen3}>
<Collapsible.DefaultTrigger>
Is it open source?
</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
<Text>Check the repository for license information.</Text>
</Collapsible.DefaultPanel>
</Collapsible.Root>
</div>
);
}自定义触发器
将 Collapsible.Trigger 与 render 属性结合使用即可完全掌控:
import { Button, Collapsible, Text } from "@cloudflare/kumo";
import { useState } from "react";
/**
* Custom trigger using the render prop for full control.
*/
export function CollapsibleCustomTriggerDemo() {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="w-full">
<Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>
<Collapsible.Trigger render={<Button variant="secondary" size="sm" />}>
{isOpen ? "Hide details" : "Show details"}
</Collapsible.Trigger>
<Collapsible.Panel className="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>
);
}保持挂载
在 DefaultPanel(或 Panel)上使用 keepMounted,可在面板折叠时保留内部状态(如表单输入):
Type something below, then collapse and re-open — your input is preserved because the panel stays mounted.
import { Collapsible, Input, Text } from "@cloudflare/kumo";
import { useState } from "react";
/**
* Keep the panel mounted in the DOM when closed to preserve internal state like form inputs.
*/
export function CollapsibleKeepMountedDemo() {
const [isOpen, setIsOpen] = useState(true);
return (
<div className="w-full space-y-4">
<Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>
<Collapsible.DefaultTrigger>Edit details</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel keepMounted>
<Text>
Type something below, then collapse and re-open — your input is
preserved because the panel stays mounted.
</Text>
<Input label="Name" placeholder="Type here…" />
</Collapsible.DefaultPanel>
</Collapsible.Root>
</div>
);
}表单内容
将 DefaultPanel 与表单控件搭配使用,以验证焦点环在动画面板内有足够的空间:
import { Button, Collapsible, Input } from "@cloudflare/kumo";
import { useState } from "react";
/**
* Form controls inside DefaultPanel for testing focus ring clipping.
*/
export function CollapsibleFormDemo() {
const [isOpen, setIsOpen] = useState(true);
return (
<div className="w-full">
<Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>
<Collapsible.DefaultTrigger>
Contact settings
</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
<form
className="flex max-w-sm flex-col gap-4"
onSubmit={(event) => event.preventDefault()}
>
<Input label="Email" placeholder="user@example.com" type="email" />
<Input label="Team name" placeholder="Design engineering" />
<Button type="submit">Save settings</Button>
</form>
</Collapsible.DefaultPanel>
</Collapsible.Root>
</div>
);
}手风琴模式
通过控制展开的条目来实现手风琴效果,即每次只展开一个条目:
Kumo is Cloudflare's new design system built on Base UI and Tailwind CSS v4.
import { Collapsible, Text } from "@cloudflare/kumo";
import { useState } from "react";
/**
* Accordion pattern where only one item can be open at a time.
*/
export function CollapsibleAccordionDemo() {
const [activeIndex, setActiveIndex] = useState<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.",
},
];
return (
<div className="w-full space-y-2">
{items.map((item, i) => (
<Collapsible.Root
key={i}
open={activeIndex === i}
onOpenChange={(open) => setActiveIndex(open ? i : null)}
>
<Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger>
<Collapsible.DefaultPanel>
<Text>{item.content}</Text>
</Collapsible.DefaultPanel>
</Collapsible.Root>
))}
</div>
);
}子组件
| 组件 | 说明 |
|---|---|
Collapsible.Root | 管理展开状态。传入 open 和 onOpenChange 可使用受控模式。 |
Collapsible.Trigger | 切换可见性的按钮。使用 render 属性可自定义元素。 |
Collapsible.Panel | 折叠内容的容器。 |
Collapsible.DefaultTrigger | 预置样式的触发器,含文本标签和动画插入标记图标。 |
Collapsible.DefaultPanel | 预置样式的面板,带左侧边框强调和标准间距。 |
API 参考
Collapsible.Root
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
open | boolean | — | 面板是否可见(受控)。 |
defaultOpen | boolean | false | 初始展开状态(非受控)。 |
onOpenChange | (open: boolean) => void | — | 展开状态变化时的回调。 |
disabled | boolean | false | 是否禁用该折叠组件。 |
Collapsible.Trigger
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
render | ReactElement | — | 作为触发器渲染的自定义元素。 |
className | string | — | 额外的 CSS 类。 |
Collapsible.Panel
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
className | string | — | 额外的 CSS 类。 |
keepMounted | boolean | false | 关闭时是否将面板保留在 DOM 中。 |
Collapsible.DefaultTrigger
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
children | ReactNode | — | 显示在触发器中的标签文本。 |
className | string | — | 额外的 CSS 类。 |
Collapsible.DefaultPanel
除下面列出的属性外,还接受 Collapsible.Panel 的所有属性。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
children | ReactNode | — | 面板内容。 |
className | string | — | 额外的 CSS 类。 |
keepMounted | boolean | false | 关闭时是否将面板保留在 DOM 中。 |