import { InputGroup, Toolbar } from "@cloudflare/kumo";
import { FunnelSimpleIcon, GearSixIcon, MagnifyingGlassIcon } from "@phosphor-icons/react";
/** Basic Toolbar with an InputGroup and adjacent action buttons. */
export function ToolbarDemo() {
return (
<Toolbar className="w-full max-w-md">
<Toolbar.InputGroup aria-label="Search DNS records" className="flex-1">
<InputGroup.Addon>
<MagnifyingGlassIcon />
</InputGroup.Addon>
<InputGroup.Input placeholder="Search DNS records" />
</Toolbar.InputGroup>
<Toolbar.Button icon={FunnelSimpleIcon} aria-label="Filter" />
<Toolbar.Button icon={GearSixIcon} aria-label="Settings" />
</Toolbar>
);
}安装
桶式导出
import { Toolbar } from "@cloudflare/kumo";细粒度导入
import { Toolbar } from "@cloudflare/kumo/components/toolbar";用法
当多个控件需要呈现为一个紧凑工具栏或筛选卡片时,请使用 Toolbar。可
直接使用 Toolbar.Button、Toolbar.Link、Toolbar.Input 和
Toolbar.InputGroup。通过 render 属性,可将 Select 与 Combobox 的
触发器与这些工具栏控件组合起来。
import { InputGroup, Toolbar } from "@cloudflare/kumo";
import { FunnelSimpleIcon, MagnifyingGlassIcon } from "@phosphor-icons/react";
export default function Example() {
return (
<Toolbar>
<Toolbar.InputGroup aria-label="Search DNS records">
<InputGroup.Addon>
<MagnifyingGlassIcon />
</InputGroup.Addon>
<InputGroup.Input placeholder="Search DNS records" />
</Toolbar.InputGroup>
<Toolbar.Button icon={FunnelSimpleIcon} aria-label="Filter" />
</Toolbar>
);
}行为
工具栏子组件特意负责分组控件的呈现样式:
- 所有
Toolbar.*控件默认使用base尺寸。 - Toolbar 的
size属性为兼容性而保留,但已废弃;省略它即可使用base尺寸。 Toolbar.Button始终以安静的工具栏按钮样式渲染。Toolbar.Link以安静的工具栏样式渲染LinkButton,并参与方向键导航。Toolbar.InputGroup将属性直接透传给InputGroup,并使用解析后的工具栏尺寸。- 为 Select 传入
render={<Toolbar.Button />},可将其触发器组合进工具栏。 - 为
Combobox.TriggerInput传入render={<Toolbar.Input />},可获得可编辑的工具栏 Combobox。 - 为
Combobox.TriggerValue传入render={<Toolbar.Button />},可获得按钮样式的工具栏 Combobox。 - Select 与 Combobox 在加入工具栏方向键导航的同时,仍保持原有的值行为、弹层 portal、筛选和表单输入功能。
- 相邻的工具栏项目共享边框,只有 Toolbar 的外侧边角是圆角。
- 未渲染工具栏控件的 Select 或 Combobox 保持独立样式,不参与工具栏的巡游焦点顺序。
示例
Select
Select 保留其常规根属性,包括 items。其 render 属性会替换
触发器,因此渲染 Toolbar.Button 会让该触发器成为工具栏项目,
而不会替换 Select 根组件。
import { Select, Toolbar } from "@cloudflare/kumo";
import { FunnelSimpleIcon, GearSixIcon } from "@phosphor-icons/react";
/** Select composes its trigger with Toolbar.Button. */
export function ToolbarSelectDemo() {
return (
<Toolbar>
<Toolbar.Button icon={FunnelSimpleIcon}>Filter</Toolbar.Button>
<Select
aria-label="Sort records"
defaultValue="name"
items={{ name: "Name", created: "Created date", status: "Status" }}
render={<Toolbar.Button />}
/>
<Toolbar.Button icon={GearSixIcon} aria-label="View settings" />
</Toolbar>
);
}Combobox
用 Toolbar.Input 组合可编辑的 Combobox 触发器。对于不可编辑的
值触发器,可从 Combobox.TriggerValue 渲染 Toolbar.Button。弹层仍由
常规的 Combobox.* 组件组合而成。在水平工具栏中,应将可编辑触发器放在
最后,这样左右方向键能继续可预测地同时服务于文本光标与工具栏导航。
import { Combobox, Toolbar } from "@cloudflare/kumo";
import { FunnelSimpleIcon } from "@phosphor-icons/react";
/** Combobox composes its editable trigger with Toolbar.Input. */
export function ToolbarComboboxDemo() {
return (
<Toolbar className="w-full max-w-md">
<Toolbar.Button icon={FunnelSimpleIcon}>Status</Toolbar.Button>
<Combobox items={toolbarComboboxItems}>
<Combobox.TriggerInput
aria-label="Filter status"
className="flex-1"
placeholder="Filter status…"
render={<Toolbar.Input />}
/>
<Combobox.Content>
<Combobox.List>
{(item: string) => (
<Combobox.Item key={item} value={item}>
{item}
</Combobox.Item>
)}
</Combobox.List>
<Combobox.Empty>No matching statuses.</Combobox.Empty>
</Combobox.Content>
</Combobox>
</Toolbar>
);
}输入简洁写法
不需要装饰(addon)的简单文本输入,请使用 Toolbar.Input。
import { Toolbar } from "@cloudflare/kumo";
import { FunnelSimpleIcon, GearSixIcon } from "@phosphor-icons/react";
/** Toolbar can use the simpler Input shorthand. */
export function ToolbarMixedControlsDemo() {
return (
<Toolbar className="w-full max-w-md">
<Toolbar.Input
aria-label="Search DNS records"
placeholder="Search DNS records"
className="flex-1"
/>
<Toolbar.Button icon={FunnelSimpleIcon} aria-label="Filter" />
<Toolbar.Button icon={GearSixIcon} aria-label="Settings" />
</Toolbar>
);
}输入组
当某个工具栏项目需要自带内联装饰或后缀时,请使用 Toolbar.InputGroup。
import { InputGroup, Toolbar } from "@cloudflare/kumo";
/** Toolbar can compose an InputGroup with adjacent actions. */
export function ToolbarInputGroupDemo() {
return (
<Toolbar className="w-full max-w-lg">
<Toolbar.InputGroup aria-label="Worker subdomain" className="flex-1">
<InputGroup.Input placeholder="my-worker" />
<InputGroup.Suffix>.workers.dev</InputGroup.Suffix>
</Toolbar.InputGroup>
<Toolbar.Button>Visit</Toolbar.Button>
</Toolbar>
);
}已废弃的尺寸
为兼容起见,size 属性仍支持 xs、sm、base 和 lg,但它已废弃,将在
未来的主版本中移除。省略它即可使用默认的 base 尺寸。
import { Toolbar } from "@cloudflare/kumo";
/** @deprecated Toolbar size customization remains for compatibility. */
export function ToolbarSizesDemo() {
return (
<div className="grid gap-3">
{(["xs", "sm", "base", "lg"] as const).map((size) => (
<div key={size} className="flex items-center gap-3">
<span className="w-10 text-sm text-kumo-subtle">{size}</span>
<Toolbar size={size} className="w-fit">
<Toolbar.Input
aria-label={`${size} search`}
placeholder="Search..."
/>
<Toolbar.Button>Apply</Toolbar.Button>
</Toolbar>
</div>
))}
</div>
);
}按钮操作
工具栏按钮使用安静的样式,让成组的操作保持视觉上的低调与一致。
import { Toolbar } from "@cloudflare/kumo";
import { DownloadSimpleIcon, UploadSimpleIcon } from "@phosphor-icons/react";
/** Toolbar buttons always use quiet toolbar styling. */
export function ToolbarActionsDemo() {
return (
<Toolbar>
<Toolbar.Button icon={UploadSimpleIcon}>Upload</Toolbar.Button>
<Toolbar.Button icon={DownloadSimpleIcon}>Download</Toolbar.Button>
</Toolbar>
);
}链接
导航类操作请使用 Toolbar.Link。它接受 LinkButton 除 size 和 variant
之外的所有属性,这两个属性由 Toolbar 控制。
import { Toolbar } from "@cloudflare/kumo";
import { BookOpenIcon, DownloadSimpleIcon } from "@phosphor-icons/react";
/** Toolbar links use LinkButton for navigation with toolbar styling. */
export function ToolbarLinksDemo() {
return (
<Toolbar>
<Toolbar.Link href="/components/button" icon={BookOpenIcon}>
Button documentation
</Toolbar.Link>
<Toolbar.Button icon={DownloadSimpleIcon}>Download</Toolbar.Button>
</Toolbar>
);
}无障碍标签
对于没有可见标签的紧凑控件,请使用 aria-label 或 aria-labelledby。
Select 触发器与每个 Combobox 触发器仍需有可访问的名称。对于可编辑输入框,
只有光标已位于相关文本边界处时,工具栏焦点才会移动;弹层打开时,方向键则
用于在其选项间导航。
import { Toolbar } from "@cloudflare/kumo";
import { MagnifyingGlassIcon } from "@phosphor-icons/react";
/** Toolbar items use aria-label for compact accessible names. */
export function ToolbarLabelsDemo() {
return (
<Toolbar className="w-full max-w-lg">
<Toolbar.Input
aria-label="Search records"
className="flex-1"
placeholder="Search"
/>
<Toolbar.Button icon={MagnifyingGlassIcon} aria-label="Search" />
</Toolbar>
);
}API 参考
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
children | ReactNode | - | 以分组卡片形式渲染的工具栏控件。 |
size 已废弃 | ”xs” | “sm” | “base” | “lg" | "base” | 设置所有支持的项目尺寸。省略此已废弃属性即可使用默认的 base 尺寸。 |
className | string | - | 合并到工具栏根元素上的额外 CSS 类。 |
Select 组合
为 Select 传入 render={<Toolbar.Button />}。在渲染出的工具栏控件上
配置禁用状态下的焦点行为:
<Select
aria-label="Sort records"
disabled
items={{ name: "Name" }}
render={<Toolbar.Button focusableWhenDisabled={false} />}
/>Combobox 组合
为 Combobox.TriggerInput 传入 render={<Toolbar.Input />},或从
Combobox.TriggerValue 渲染 Toolbar.Button:
<Combobox items={items}>
<Combobox.TriggerInput
aria-label="Filter records"
render={<Toolbar.Input />}
/>
<Combobox.Content>...</Combobox.Content>
</Combobox>在渲染出的 Toolbar.Button 或 Toolbar.Input 上设置 focusableWhenDisabled,
可控制禁用的触发器是否仍保留在工具栏的巡游焦点顺序中。