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 { mergePropsN, 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: mergePropsN<'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: mergePropsN<'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
Default
Badge
Display bite-sized snippets of info, like notifications or labels, that you want to stand out from regular text. They're perfect for showing things like unread message counts, status updates or categories without taking up much space.
Button
Renders a button or a component that looks like a button.