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。Select 和 Combobox 的触发器通过它们的 render 属性 与这些工具栏控件组合。

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 的各个控件组件有意地承担分组控件的外观呈现:

  • 每个 Toolbar.* 控件默认使用 base 尺寸。
  • Toolbar 的 size 属性为兼容保留,但已弃用;要使用基础尺寸请省略它。
  • Toolbar.Button 始终以安静 (quiet) 样式渲染工具栏按钮。
  • Toolbar.Link 以安静的工具栏样式渲染 LinkButton,并 参与方向键导航。
  • Toolbar.InputGroup 会将属性直接传递给 InputGroup,并使用解析后的工具栏尺寸。
  • 给 Select 传入 render={<Toolbar.Button />},可将其触发器组合进工具栏。
  • 给 Combobox.TriggerInput 传入 render={<Toolbar.Input />},可得到可编辑的工具栏组合框。
  • 给 Combobox.TriggerValue 传入 render={<Toolbar.Button />},可得到按钮样式的工具栏组合框。
  • Select 和 Combobox 在加入工具栏方向键导航的同时,保留各自取值行为、弹层挂载、过滤和表单输入能力。
  • 相邻的工具栏项共享边框,且只有 Toolbar 的外侧圆角是圆的。
  • 未渲染 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>
  );
}

输入简写

对于不需要附加元素的简单文本输入,请使用 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 尺寸。

xs
sm
base
lg
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 参考

属性类型默认值说明
childrenReactNode-渲染为一个分组卡片的工具栏控件。
size 已弃用”xs” | “sm” | “base” | “lg""base”设置所有受支持的项尺寸。省略这个已弃用的属性即使用默认的基础尺寸。
classNamestring-合并到工具栏根节点上的额外 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, 可控制禁用状态的触发器是否仍保留在工具栏的焦点游走顺序中。