安装
pnpm dlx shadcn@latest add https://yiui.dev/r/grid-toolbar.json用法
import { Search } from "lucide-react"
import { BarField } from "@/components/ui/bar-field/bar-field"
import {
GridToolbar,
GridToolbarItem,
} from "@/components/ui/grid-toolbar/grid-toolbar"
import { SegmentedControl } from "@/components/ui/segmented-control/segmented-control"
;<GridToolbar aria-label="筛选">
<GridToolbarItem grow>
<BarField aria-label="搜索" icon={<Search />} placeholder="搜索…" />
</GridToolbarItem>
<GridToolbarItem>
<SegmentedControl aria-label="状态" options={OPTIONS} />
</GridToolbarItem>
</GridToolbar>GridToolbar 是整行,GridToolbarItem 是其中一格。每格高度跟随工具栏,格内控件铺满整格;grow 让这一格占满剩余宽度,通常给搜索框。格子之间默认是虚线;separator="solid" 让这一格左侧用实线,表示从这里开始是另一组(比如列设置和密度之间)。宽度、换行位置、窄屏隐藏都写在 GridToolbarItem 的 className 上,比如 basis-full 让一格独占一行、hidden @min-[40rem]:flex 在窄容器里隐藏。
放进来的控件
方条输入、分段选择、方条下拉放进工具栏时会自动换成无框写法:去掉自己的边框、圆角和底色,高度铺满整格,焦点环画在格子内侧。分段选择还会把每个选项拆成一格,选中项整格铺底色,不再是圆角的滑块。单独使用时保持原样,不需要额外传参数。原理是这三个组件带了 in-data-[slot=grid-toolbar]: 样式,只在祖先是网格工具栏时生效,组件之间没有互相引用。
图标按钮用官方 Button:variant="ghost"、size="icon-lg"(默认高度)或 size="icon"(size="sm" 时),再加 h-full rounded-none focus-visible:ring-inset,就是一个方形的格子。
外框与换行
单独使用时整条带一圈边框(bordered 默认为 true)。放进已经有边线的容器,例如表格顶部,设 bordered={false},由容器画线。格子之间是虚线;换行后,每格都画左线和上线,最外圈的线由外框裁掉,所以不论怎样换行,格子之间都只有一条线。
API
GridToolbar
"default" | "sm" | null | undefined外框:单独使用时整条带边框;放进表格等已有边线的容器时设为 false,由容器画线
类型boolean | undefinedtrueGridToolbarItem
占满剩余宽度(如搜索框)
类型boolean | undefinedfalse这一格左侧的分隔线:同一组内用虚线;solid 表示从这一格开始是新的一组
"dashed" | "solid" | undefined"dashed"导出 GridToolbarProps、GridToolbarItemProps 类型和 gridToolbarVariants。
data-slot
| 部位 | data-slot |
|---|---|
| 整行 | grid-toolbar |
| 内层(负责换行) | grid-toolbar-content |
| 一格 | grid-toolbar-item |
根元素在 bordered 为真时带 data-bordered。
可访问性
工具栏本身只是布局,不接管键盘:格内每个控件保留自己的 Tab 顺序与方向键行为。没有使用 role="toolbar",因为那要求整条只占一个 Tab 位、由方向键切换,与输入框、下拉的键盘习惯冲突。给整行一个 aria-label(如「日志筛选」)方便读屏定位;格内控件各自需要可访问名称。
注意事项
行高对应按钮 icon / icon-lg 档:size="sm" 为 32px,默认 36px,触屏上分别加高到 40 / 44px。工具栏外层是 overflow-hidden(用来裁掉最外圈的线),弹出层都走 Portal,不受影响;如果在格子里放自绘的浮层,请同样用 Portal。