"use client" import * as React from "react" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" type ButtonProps = React.ComponentProps export type ButtonGroupItem = Omit & { key: string label: React.ReactNode description?: React.ReactNode } export type ButtonGroupProps = React.ComponentProps<"div"> & { items?: ButtonGroupItem[] attached?: boolean size?: ButtonProps["size"] variant?: ButtonProps["variant"] activeVariant?: ButtonProps["variant"] orientation?: "horizontal" | "vertical" fullWidth?: boolean allowDeselect?: boolean value?: string defaultValue?: string onValueChange?: (value: string) => void } function ButtonGroup({ items, attached = true, size = "sm", variant = "outline", activeVariant = "default", orientation = "horizontal", fullWidth = false, allowDeselect = false, value, defaultValue, onValueChange, className, children, ...props }: ButtonGroupProps) { const isVertical = orientation === "vertical" const isControlled = value !== undefined const [internalValue, setInternalValue] = React.useState(defaultValue) const currentValue = isControlled ? value : internalValue const groupId = React.useId() const itemRefs = React.useRef>([]) const updateValue = (nextValue: string) => { const resolvedValue = allowDeselect && currentValue === nextValue ? "" : nextValue if (!isControlled) setInternalValue(resolvedValue) onValueChange?.(resolvedValue) } return (
{items?.map(({ key, label, description, className: itemClassName, size: itemSize, variant: itemVariant, onClick, "aria-label": itemAriaLabel, ...item }, index) => { const selected = currentValue === key const descriptionId = description ? `${groupId}-${key}-description` : undefined const resolvedAriaLabel = itemAriaLabel ?? (description && typeof label === "string" ? label : undefined) return ( )})} {children}
) } export { ButtonGroup }