"use client"; import * as React from "react"; import {Separator} from "@/components/ui/separator"; import {cn} from "@/lib/utilities"; import styles from "./button-group.module.css"; /** Supported layout directions for {@link ButtonGroup}. */ export type ButtonGroupOrientation = "horizontal" | "vertical"; interface ButtonGroupVariantOptions { /** Orientation used to resolve the root style classes. @default "horizontal" */ orientation?: ButtonGroupOrientation; /** Additional classes merged into the generated variant string. @default undefined */ className?: string; } /** * Props for the {@link ButtonGroup} component. */ export interface ButtonGroupProps extends React.ComponentPropsWithoutRef<"div"> { /** Arrangement of grouped controls. @default "horizontal" */ orientation?: ButtonGroupOrientation; } /** * Props for the {@link ButtonGroupText} component. */ export interface ButtonGroupTextProps extends React.ComponentPropsWithoutRef<"div"> { /** Enables rendering an existing div-compatible child element. @default false */ asChild?: boolean; } /** * Props for the {@link ButtonGroupSeparator} component. */ export type ButtonGroupSeparatorProps = React.ComponentPropsWithoutRef; /** * Returns the CSS class list for a button group root. * * @param options - Variant options used to derive the generated class string. * @returns The merged class name string for the requested orientation. * * @example * ```tsx * const className = buttonGroupVariants({orientation: "vertical"}); * ``` */ function buttonGroupVariants({orientation = "horizontal", className}: Readonly = {}): string { return cn(styles.root, orientation === "vertical" ? styles.vertical : styles.horizontal, className); } /** * Aligns related buttons into a single visual control group. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `
` element * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * * * * * ``` * * @see {@link ButtonGroupProps} for available props */ const ButtonGroup = React.forwardRef( ({className, orientation = "horizontal", ...props}: Readonly, ref): React.JSX.Element => (
), ); /** * Adds descriptive text content within a button group layout. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `
` element by default * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * Actions * ``` * * @see {@link ButtonGroupTextProps} for available props */ const ButtonGroupText = React.forwardRef( ({className, asChild = false, children, ...props}: Readonly, ref): React.JSX.Element => { const mergedClassName = cn(styles.text, className); if (asChild && React.isValidElement(children)) { const child = children as React.ReactElement & {ref?: React.Ref}>; // eslint-disable-next-line react-x/no-clone-element -- replaces Radix Slot while preserving asChild prop merging return React.cloneElement(child, { ...props, ref, className: cn(mergedClassName, child.props.className), }); } return (
{children}
); }, ); /** * Inserts a separator between grouped controls. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a wrapped `Separator` component * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * * ``` * * @see {@link ButtonGroupSeparatorProps} for available props */ const ButtonGroupSeparator = React.forwardRef( ({className, orientation = "vertical", ...props}: Readonly, ref): React.JSX.Element => ( ), ); ButtonGroup.displayName = "ButtonGroup"; ButtonGroupText.displayName = "ButtonGroupText"; ButtonGroupSeparator.displayName = "ButtonGroupSeparator"; export {ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants};