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.ButtonToolbar.LinkToolbar.InputToolbar.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 属性仍支持 xssmbaselg,但它已废弃,将在 未来的主版本中移除。省略它即可使用默认的 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。它接受 LinkButtonsizevariant 之外的所有属性,这两个属性由 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-labelaria-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”设置所有支持的项目尺寸。省略此已废弃属性即可使用默认的 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.ButtonToolbar.Input 上设置 focusableWhenDisabled, 可控制禁用的触发器是否仍保留在工具栏的巡游焦点顺序中。