Bỏ qua đến nội dung

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.json
npx shadcn@latest add https://neobrutalism.com/r/base/toggle-group.json
yarn dlx shadcn@latest add https://neobrutalism.com/r/base/toggle-group.json
bunx --bun shadcn@latest add https://neobrutalism.com/r/base/toggle-group.json

Cài đặt các dependency sau:

pnpm add @base-ui/react
npm install @base-ui/react
yarn add @base-ui/react
bun add @base-ui/react

Sao chép và dán đoạn mã sau vào dự án của bạn.

components/ui/toggle-group.tsx
"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
└── ToggleGroupItem

Ví 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ímHành động
Tab / Shift + TabDi chuyển focus vào nhóm và ra ngoài
Space / EnterBật/tắt mục đang được focus
ArrowRight / ArrowDownDi chuyển focus đến mục kế tiếp
ArrowLeft / ArrowUpDi chuyển focus đến mục trước đó
Home / EndNhả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.