Nhóm bật/tắt
Các nhóm nút hai trạng thái dành cho thanh công cụ trình soạn thảo, công cụ chuyển đổi chế độ xem và thanh lọc — với hiệu ứng viền và bóng theo phong cách tân thô mộc.
import { Bold, Italic, Underline } from "lucide-react"
import {Toggle group là một hàng nút hai trạng thái, trong đó mỗi lúc có thể nhấn một nút (mặc định) hoặc nhiều nút (multiple). Được xây dựng trên thành phần Base UI Toggle Group và tạo kiểu theo công thức neobrutalist: viền dày, bóng đổ đậm và kiểu chữ đậm.
Nên dùng khi:
- Thanh công cụ trình soạn thảo — đậm/nghiêng/gạch chân, căn lề văn bản, kiểu danh sách với
multiple. - Chuyển chế độ xem — lưới hay danh sách, biểu đồ hay bảng, ngày/tuần/tháng; chế độ mặc định giữ tối đa một mục hoạt động.
- Thanh bộ lọc — tag, danh mục hoặc thuộc tính mà người dùng có thể bật tắt chồng lên nhau.
Cài đặt#
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/toggle-group.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/toggle-group.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/toggle-group.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/toggle-group.json
Cài đặt các dependency sau:
pnpm add @base-ui/reactnpm install @base-ui/reactyarn add @base-ui/reactbun add @base-ui/react
Sao chép và dán đoạn mã sau vào dự án của bạn.
"use client"
import * as React from "react"
import { type VariantProps } from "class-variance-authority"
import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
import { toggleVariants } from "@/components/ui/toggle"
const ToggleGroupContext = React.createContext<
VariantProps<typeof toggleVariants> & {
spacing?: number
orientation?: "horizontal" | "vertical"
}
>({
size: "default",
variant: "default",
spacing: 2,
orientation: "horizontal",
})
function ToggleGroup({
className,
variant,
size,
spacing = 2,
orientation = "horizontal",
children,
...props
}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
VariantProps<typeof toggleVariants> & {
spacing?: number
orientation?: "horizontal" | "vertical"
}) {
return (
<ToggleGroupPrimitive.Root
data-slot="toggle-group"
data-variant={variant}
data-size={size}
data-spacing={spacing}
data-orientation={orientation}
style={{ "--gap": spacing } as React.CSSProperties}
className={cn(
"group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] rounded-lg data-[size=sm]:rounded-[min(var(--radius-md),10px)] data-vertical:flex-col data-vertical:items-stretch",
className
)}
{...props}
>
<ToggleGroupContext.Provider
value={{ variant, size, spacing, orientation }}
>
{children}
</ToggleGroupContext.Provider>
</ToggleGroupPrimitive.Root>
)
}
function ToggleGroupItem({
className,
children,
variant = "default",
size = "default",
...props
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
VariantProps<typeof toggleVariants>) {
const context = React.useContext(ToggleGroupContext)
return (
<ToggleGroupPrimitive.Item
data-slot="toggle-group-item"
data-variant={context.variant || variant}
data-size={context.size || size}
data-spacing={context.spacing}
className={cn(
"shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-end]:pr-1.5 group-data-[spacing=0]/toggle-group:has-data-[icon=inline-start]:pl-1.5 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-lg group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-lg group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t",
toggleVariants({
variant: context.variant || variant,
size: context.size || size,
}),
className
)}
{...props}
>
{children}
</ToggleGroupPrimitive.Item>
)
}
export { ToggleGroup, ToggleGroupItem }
Cập nhật các đường dẫn import cho phù hợp với cấu hình dự án của bạn.
Cách dùng#
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"<ToggleGroup type="single">
<ToggleGroupItem value="a">A</ToggleGroupItem>
<ToggleGroupItem value="b">B</ToggleGroupItem>
<ToggleGroupItem value="c">C</ToggleGroupItem>
</ToggleGroup>Kết hợp#
Dùng cách kết hợp sau để xây dựng một ToggleGroup:
ToggleGroup
├── ToggleGroupItem
└── ToggleGroupItemVí dụ#
Outline#
Dùng variant="outline" cho kiểu viền.
import {
ToggleGroup,
ToggleGroupItem,Kích thước#
Dùng prop size để thay đổi kích thước của toggle group.
import {
ToggleGroup,
ToggleGroupItem,Khoảng cách#
Dùng spacing để thêm khoảng cách giữa các mục trong toggle group.
import {
ToggleGroup,
ToggleGroupItem,Vertical#
Dùng orientation="vertical" cho toggle group dọc.
import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"
import {Vô hiệu hóa#
import { Bold, Italic, Underline } from "lucide-react"
import {Tùy chỉnh#
Một ví dụ về toggle group tùy chỉnh.
"use client"
import * as React from "react"RTL#
Để bật hỗ trợ RTL trong Neobrutalism, xem hướng dẫn cấu hình RTL.
"use client"
import * as React from "react"Khả năng truy cập#
Mỗi mục là một nút bật/tắt theo mẫu Button của WAI-ARIA: nhóm render role="group" và mọi mục đều là một <button> thật với aria-pressed, trong cả chế độ đơn lẫn chế độ nhiều. Focus dùng roving tabindex, nên cả nhóm chỉ là một điểm dừng Tab duy nhất. Các mục chỉ có biểu tượng cần một aria-label.
Tương tác bàn phím:
| Phím | Hành động |
|---|---|
Tab / Shift + Tab | Di chuyển focus vào nhóm và ra ngoài |
Space / Enter | Bật/tắt mục đang được focus |
ArrowRight / ArrowDown | Di chuyển focus đến mục kế tiếp |
ArrowLeft / ArrowUp | Di chuyển focus đến mục trước đó |
Home / End | Nhảy đến mục đầu tiên / cuối cùng |
Tham chiếu API#
Xem tài liệu Base UI Toggle Group.
Nhật ký thay đổi#
2026-05-17 Khoảng cách mặc định#
Giá trị spacing mặc định đã được đổi từ 0 thành 2 để các toggle group hiển thị với khoảng cách giữa các mục theo mặc định. Dùng spacing={0} cho các mục liền nhau.