الانتقال إلى المحتوى

مجموعة تبديل

مجموعات أزرار ذات حالتين لشريط أدوات المحرر، ومبدلات العرض، وأشرطة التصفية — مع تطبيق أسلوب «النيوبروتاليست» في الحدود والظلال.

import { Bold, Italic, Underline } from "lucide-react"

import {

مجموعة التبديل عبارة عن صف من الأزرار ذات الحالتين، حيث يمكن الضغط على زر واحد (الوضع الافتراضي) أو عدة أزرار (multiple) في آن واحد. وهي مبنية على مكون Base UI Toggle Group ومصممة وفقًا لنهج «النيوبروتالية»: حدود سميكة، وظلال حادة، وخط عريض.

استخدمه عندما:

  • أشرطة أدوات المحرر — الخط العريض/المائل/التسطير، ومحاذاة النص، وأنماط القوائم باستخدام multiple.
  • مبدلات العرض — الشبكة مقابل القائمة، والرسم البياني مقابل الجدول، واليوم/الأسبوع/الشهر؛ حيث يُبقي الإعداد الافتراضي على نشاط عنصر واحد كحد أقصى.
  • أشرطة التصفية — العلامات أو الفئات أو المعايير التي يمكن للمستخدم تفعيلها أو إلغاء تفعيلها.

التثبيت

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

ثبّت التبعيات التالية:

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

انسخ الكود التالي والصقه في مشروعك.

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 }

حدّث مسارات الاستيراد لتطابق إعداد مشروعك.

الاستخدام

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>

التركيب

استخدم التركيب التالي لبناء ToggleGroup:

ToggleGroup
├── ToggleGroupItem
└── ToggleGroupItem

أمثلة

إطار

استخدم variant="outline" للحصول على نمط بإطار.

import {
  ToggleGroup,
  ToggleGroupItem,

الحجم

استخدم الخاصية size لتغيير حجم مجموعة التبديل.

import {
  ToggleGroup,
  ToggleGroupItem,

التباعد

استخدم spacing لإضافة تباعد بين عناصر مجموعة التبديل.

import {
  ToggleGroup,
  ToggleGroupItem,

عمودي

استخدم orientation="vertical" لمجموعات التبديل العمودية.

import { BoldIcon, ItalicIcon, UnderlineIcon } from "lucide-react"

import {

معطّل

import { Bold, Italic, Underline } from "lucide-react"

import {

مخصّص

مثال على مجموعة تبديل مخصّصة.

"use client"

import * as React from "react"

RTL

لتفعيل RTL في Neobrutalism، راجع دليل إعداد RTL.

"use client"

import * as React from "react"

إمكانية الوصول

كل عنصر هو زر تبديل وفقًا لـ WAI-ARIA Button pattern: حيث تعرض المجموعة role="group"، ويكون كل عنصر عبارة عن <button> حقيقي مع aria-pressed، سواء في الوضع الفردي أو المتعدد. يستخدم التركيز مؤشر تبويب متنقل، لذا فإن المجموعة بأكملها تمثل نقطة توقف واحدة لـ Tab. العناصر التي تحتوي على أيقونة فقط تحتاج إلى aria-label.

تفاعلات لوحة المفاتيح:

مفتاحالإجراء
Tab / Shift + Tabنقل التركيز إلى المجموعة وخارجها
Space / Enterتبديل العنصر الذي يقع عليه التركيز
ArrowRight / ArrowDownنقل التركيز إلى العنصر التالي
ArrowLeft / ArrowUpنقل التركيز إلى العنصر السابق
Home / Endالانتقال إلى العنصر الأول / الأخير

مرجع API

لمزيد من المعلومات، راجع وثائق Base UI.

سجل التغييرات

2026-05-17 التباعد الافتراضي

تم تغيير القيمة الافتراضية لـ spacing من 0 إلى 2 بحيث تُعرض مجموعات التبديل مع تباعد بين العناصر افتراضياً. استخدم spacing={0} للعناصر المتّصلة.