Toolbar 工具栏
@lark-ui/core
import { InputGroup, Toolbar } from "@lark-ui/core";
import { FunnelSimpleIcon, GearSixIcon, MagnifyingGlassIcon } from "@phosphor-icons/react";

/** 基础工具栏(Toolbar),包含一个 InputGroup 和相邻的操作按钮。 */
export function ToolbarDemo() {
  return (
    <Toolbar className="w-full max-w-md">
      <Toolbar.InputGroup aria-label="搜索 DNS 记录" className="flex-1">
        <InputGroup.Addon>
          <MagnifyingGlassIcon />
        </InputGroup.Addon>
        <InputGroup.Input placeholder="搜索 DNS 记录" />
      </Toolbar.InputGroup>
      <Toolbar.Button icon={FunnelSimpleIcon} aria-label="筛选" />
      <Toolbar.Button icon={GearSixIcon} aria-label="设置" />
    </Toolbar>
  );
}

安装

统一导出

import { Toolbar } from "@lark-ui/core";

按需导出

import { Toolbar } from "@lark-ui/core/components/toolbar";

用法

当多个控件需要呈现为一个紧凑的工具栏(Toolbar)或筛选卡片时,请使用 Toolbar。 可直接使用 Toolbar.Button、Toolbar.Link、Toolbar.Input 和 Toolbar.InputGroup。 也可以通过 render 属性,把选择器(Select)和组合框(Combobox)的触发器与这些工具栏控件组合起来。

import { InputGroup, Toolbar } from "@lark-ui/core";
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.TriggerValue 传入 render={<Toolbar.Button />},可得到按钮样式的工具栏组合框。
  • 选择器和组合框在加入工具栏方向键导航的同时,仍保留各自的值行为、弹窗挂载、筛选能力和表单输入。
  • 相邻的工具栏条目共享边框,只有 Toolbar 的外角是圆角。
  • 如果选择器或组合框没有渲染成 Toolbar 控件,它会保持独立的呈现方式,也不会加入工具栏的漫游焦点顺序。

示例

选择器(Select)

选择器(Select)保留常规的根属性,包括 items。它的 render 属性会替换触发器, 因此渲染为 Toolbar.Button 后,该触发器就成了一个工具栏条目,而不会替换掉 Select 的根元素。

import { Select, Toolbar } from "@lark-ui/core";
import { FunnelSimpleIcon, GearSixIcon } from "@phosphor-icons/react";

/** 选择器通过 Toolbar.Button 组合出其触发器。 */
export function ToolbarSelectDemo() {
  return (
    <Toolbar>
      <Toolbar.Button icon={FunnelSimpleIcon}>筛选</Toolbar.Button>
      <Select
        aria-label="排序记录"
        defaultValue="name"
        items={{ name: "名称", created: "创建日期", status: "状态" }}
        render={<Toolbar.Button />}
      />
      <Toolbar.Button icon={GearSixIcon} aria-label="查看设置" />
    </Toolbar>
  );
}

组合框(Combobox)

用 Toolbar.Input 组合出可编辑的组合框(Combobox)触发器。对于不可编辑的值触发器, 请从 Combobox.TriggerValue 渲染 Toolbar.Button。弹窗部分仍使用常规的 Combobox.* 组件组合。 在水平工具栏中,请把可编辑的触发器放在最后,这样左右方向键就能继续稳定地同时服务于文本光标和工具栏导航。

import { Combobox, Toolbar } from "@lark-ui/core";
import { FunnelSimpleIcon } from "@phosphor-icons/react";

/** 组合框通过 Toolbar.Input 组合出其可编辑触发器。 */
export function ToolbarComboboxDemo() {
  return (
    <Toolbar className="w-full max-w-md">
      <Toolbar.Button icon={FunnelSimpleIcon}>状态</Toolbar.Button>
      <Combobox items={toolbarComboboxItems}>
        <Combobox.TriggerInput
          aria-label="筛选状态"
          className="flex-1"
          placeholder="筛选状态……"
          render={<Toolbar.Input />}
        />
        <Combobox.Content>
          <Combobox.List>
            {(item: string) => (
              <Combobox.Item key={item} value={item}>
                {item}
              </Combobox.Item>
            )}
          </Combobox.List>
          <Combobox.Empty>没有匹配的状态。</Combobox.Empty>
        </Combobox.Content>
      </Combobox>
    </Toolbar>
  );
}

输入框简写

对于不需要附加元素的简单文本输入,请使用 Toolbar.Input。

import { Toolbar } from "@lark-ui/core";
import { FunnelSimpleIcon, GearSixIcon } from "@phosphor-icons/react";

/** 工具栏可以使用更简洁的 Input 简写形式。 */
export function ToolbarMixedControlsDemo() {
  return (
    <Toolbar className="w-full max-w-md">
      <Toolbar.Input
        aria-label="搜索 DNS 记录"
        placeholder="搜索 DNS 记录"
        className="flex-1"
      />
      <Toolbar.Button icon={FunnelSimpleIcon} aria-label="筛选" />
      <Toolbar.Button icon={GearSixIcon} aria-label="设置" />
    </Toolbar>
  );
}

输入框组

当某个工具栏条目需要自己的行内附加元素或后缀时,请使用 Toolbar.InputGroup。

import { InputGroup, Toolbar } from "@lark-ui/core";

/** 工具栏可以将 InputGroup 与相邻操作组合在一起。 */
export function ToolbarInputGroupDemo() {
  return (
    <Toolbar className="w-full max-w-lg">
      <Toolbar.InputGroup aria-label="Worker 子域名" className="flex-1">
        <InputGroup.Input placeholder="my-worker" />
        <InputGroup.Suffix>.workers.dev</InputGroup.Suffix>
      </Toolbar.InputGroup>
      <Toolbar.Button>访问</Toolbar.Button>
    </Toolbar>
  );
}

已弃用的尺寸

为兼容起见,size 属性仍支持 xs、sm、base 和 lg,但它已被弃用, 并将在未来的主版本中移除。请省略它以使用默认的 base 尺寸。

xs
sm
base
lg
import { Toolbar } from "@lark-ui/core";

/** @deprecated 工具栏尺寸自定义仅为兼容性而保留。 */
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-lark-subtle">{size}</span>
          <Toolbar size={size} className="w-fit">
            <Toolbar.Input aria-label={`${size} 搜索`} placeholder="搜索……" />
            <Toolbar.Button>应用</Toolbar.Button>
          </Toolbar>
        </div>
      ))}
    </div>
  );
}

按钮操作

工具栏按钮使用低调的样式,让成组的操作在视觉上保持安静且一致。

import { Toolbar } from "@lark-ui/core";
import { DownloadSimpleIcon, UploadSimpleIcon } from "@phosphor-icons/react";

/** 工具栏按钮始终使用低调的工具栏样式。 */
export function ToolbarActionsDemo() {
  return (
    <Toolbar>
      <Toolbar.Button icon={UploadSimpleIcon}>上传</Toolbar.Button>
      <Toolbar.Button icon={DownloadSimpleIcon}>下载</Toolbar.Button>
    </Toolbar>
  );
}

链接

导航类操作请使用 Toolbar.Link。它接受 LinkButton 的属性,但 size 和 variant 除外——这两者由 Toolbar 统一控制。

import { Toolbar } from "@lark-ui/core";
import { BookOpenIcon, DownloadSimpleIcon } from "@phosphor-icons/react";

/** 工具栏链接使用 LinkButton 实现导航,并采用工具栏样式。 */
export function ToolbarLinksDemo() {
  return (
    <Toolbar>
      <Toolbar.Link href="/components/button" icon={BookOpenIcon}>
        按钮文档
      </Toolbar.Link>
      <Toolbar.Button icon={DownloadSimpleIcon}>下载</Toolbar.Button>
    </Toolbar>
  );
}

无障碍标签

对于没有可见标签的紧凑控件,请使用 aria-label 或 aria-labelledby。 选择器的触发器以及每个组合框触发器仍然需要具备无障碍名称。 对于可编辑输入,只有当光标已位于相应的文本边界时,工具栏焦点才会移动;当弹窗处于打开状态时,方向键会改为在弹窗选项之间导航。

import { Toolbar } from "@lark-ui/core";
import { MagnifyingGlassIcon } from "@phosphor-icons/react";

/** 工具栏条目使用 aria-label 提供紧凑的无障碍名称。 */
export function ToolbarLabelsDemo() {
  return (
    <Toolbar className="w-full max-w-lg">
      <Toolbar.Input
        aria-label="搜索记录"
        className="flex-1"
        placeholder="搜索"
      />
      <Toolbar.Button icon={MagnifyingGlassIcon} aria-label="搜索" />
    </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.Button 或 Toolbar.Input 上设置 focusableWhenDisabled, 用于控制被禁用的触发器是否仍留在工具栏的漫游焦点顺序中。