A container that groups a set of buttons sticked together.
Installation
npx shadcn@latest add @caprice/button-groupnpm install @caprice-ui/reactInstall the following dependencies:
npm install @base-ui/react lucide-reactAdd a cn helper
import { defineConfig, type VariantProps } from 'cva';import { twMerge } from 'tailwind-merge';export const { compose, cva, cx: cn,} = defineConfig({ hooks: { onComplete: (className: string) => twMerge(className), },});export type { VariantProps };Copy and paste the following code into your project.
import { mergeProps, useRender } from '@base-ui/react';import { Separator as SeparatorComponent } from '@/components/caprice-ui/separator';import { cn, cva, type VariantProps } from '@/lib/utils';const buttonGroupVariants = cva({ base: "flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1", variants: { orientation: { horizontal: '[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none', vertical: 'flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none', }, }, defaultVariants: { orientation: 'horizontal', },});/** * A group of buttons that allows users to select one or more options. * Renders a `<fieldset>` element. * * Documentation: [Caprice UI Button Group](https://caprice-ui.com/docs/components/button-group) */export namespace Root { export type Props = useRender.ComponentProps<'fieldset'> & VariantProps<typeof buttonGroupVariants>;}export function Root({ className, render, orientation, ...props }: Root.Props) { const defaultProps: useRender.ElementProps<'fieldset'> & { 'data-slot'?: string } = { 'data-slot': 'button-group', className: buttonGroupVariants({ orientation, className }), }; return useRender({ render, state: { orientation }, defaultTagName: 'fieldset', stateAttributesMapping: { orientation: (value) => (value ? { 'data-orientation': value } : null), }, props: mergeProps<'fieldset'>(defaultProps, props), });}/** * Displays text within a button group * Renders a `<div>` element. * * Documentation: [Caprice UI Button Group](https://caprice-ui.com/docs/components/button-group) */export namespace Text { export type Props = useRender.ComponentProps<'div'>;}export function Text({ className, render, ...props }: Text.Props) { const defaultProps: useRender.ElementProps<'div'> & { 'data-slot'?: string } = { 'data-slot': 'button-group-text', className: cn( "flex items-center gap-2 rounded-md border bg-muted px-4 font-medium text-sm shadow-xs [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none", className ), }; return useRender({ render, defaultTagName: 'div', props: mergeProps<'div'>(defaultProps, props), });}/** * A separator that visually separates buttons in a button group. * Renders a `<div>` element. * * Documentation: [Caprice UI Button Group](https://caprice-ui.com/docs/components/button-group) */export namespace Separator { export interface State extends SeparatorComponent.State {} export interface Props extends React.ComponentProps<typeof SeparatorComponent> {}}export function Separator({ className, orientation = 'vertical', ...props }: Separator.Props) { return ( <SeparatorComponent className={cn( 'relative m-0! self-stretch bg-input data-[orientation=vertical]:h-auto', className )} data-slot="button-group-separator" orientation={orientation} {...props} /> );}Update the import paths to match your project setup.
Usage
import * as ButtonGroup from "@/components/caprice-ui/button-group"import { Button } from "@/components/caprice-ui/button"import * as ButtonGroup from "@caprice-ui/react/button-group"import { Button } from "@caprice-ui/react/button"Examples
API Reference
Root
Prop
Type