Button Groups

Flexible button group components for displaying multiple buttons together. Supports various layouts, sizes, and customization options. previews

Horizontal Layout

Buttons arranged horizontally in a group.

 
<div
  class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-transparent text-slate-900 dark:text-white hover:text-slate-700 dark:hover:text-slate-200 border-slate-300 dark:border-slate-600 hover:border-slate-400 dark:hover:border-slate-500 border px-3 py-2 text-sm rounded-md">
    Button 1
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-transparent text-slate-900 dark:text-white hover:text-slate-700 dark:hover:text-slate-200 border-slate-300 dark:border-slate-600 hover:border-slate-400 dark:hover:border-slate-500 border px-3 py-2 text-sm rounded-md">
    Button 2
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-transparent text-slate-900 dark:text-white hover:text-slate-700 dark:hover:text-slate-200 border-slate-300 dark:border-slate-600 hover:border-slate-400 dark:hover:border-slate-500 border px-3 py-2 text-sm rounded-md">
    Button 3
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup>
<Button variant="outline" color="white">Button 1</Button>
<Button variant="outline" color="white">Button 2</Button>
<Button variant="outline" color="white">Button 3</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Horizontal Layout Solid

Buttons arranged horizontally in a group.

 
<div
  class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-gray-500 hover:bg-gray-600 dark:bg-gray-600 dark:hover:bg-gray-500 text-white dark:text-white hover:text-gray-100 dark:hover:text-gray-200 px-3 py-2 text-sm rounded-md">
    Button 1
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-gray-500 hover:bg-gray-600 dark:bg-gray-600 dark:hover:bg-gray-500 text-white dark:text-white hover:text-gray-100 dark:hover:text-gray-200 px-3 py-2 text-sm rounded-md">
    Button 2
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-gray-500 hover:bg-gray-600 dark:bg-gray-600 dark:hover:bg-gray-500 text-white dark:text-white hover:text-gray-100 dark:hover:text-gray-200 px-3 py-2 text-sm rounded-md">
    Button 3
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup showBorder={false}>
<Button variant="solid" color="gray">Button 1</Button>
<Button variant="solid" color="gray">Button 2</Button>
<Button variant="solid" color="gray">Button 3</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Horizontal Layout with Dividers

Buttons arranged horizontally in a group with dividers.

 
<div
  class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-gray-500 hover:bg-gray-600 dark:bg-gray-600 dark:hover:bg-gray-500 text-white dark:text-white hover:text-gray-100 dark:hover:text-gray-200 px-3 py-2 text-sm rounded-md">
    Button 1
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-gray-500 hover:bg-gray-600 dark:bg-gray-600 dark:hover:bg-gray-500 text-white dark:text-white hover:text-gray-100 dark:hover:text-gray-200 px-3 py-2 text-sm rounded-md">
    Button 2
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-gray-500 hover:bg-gray-600 dark:bg-gray-600 dark:hover:bg-gray-500 text-white dark:text-white hover:text-gray-100 dark:hover:text-gray-200 px-3 py-2 text-sm rounded-md">
    Button 3
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup withDividers={true}>
<Button variant="solid" color="gray">Button 1</Button>
<Button variant="solid" color="gray">Button 2</Button>
<Button variant="solid" color="gray">Button 3</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Vertical Layout

Buttons arranged vertically in a group.

 
<div
  class="inline-flex overflow-hidden flex-col [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-t-md [&#38;>*:last-child]:rounded-b-md [&#38;>*:not(:first-child)]:-mt-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 1
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 2
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 3
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup orientation="vertical">
<Button variant="solid" color="blue">Button 1</Button>
<Button variant="solid" color="blue">Button 2</Button>
<Button variant="solid" color="blue">Button 3</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Vertical Layout with Dividers

Buttons arranged vertically in a group with dividers.

 
<div
  class="inline-flex overflow-hidden flex-col [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center divide-y divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-t-md [&#38;>*:last-child]:rounded-b-md [&#38;>*:not(:first-child)]:-mt-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 1
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 2
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 3
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup orientation="vertical" withDividers={true}>
<Button variant="solid" color="blue">Button 1</Button>
<Button variant="solid" color="blue">Button 2</Button>
<Button variant="solid" color="blue">Button 3</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group Sizes

Button groups with different sizes.

 
<div class="space-y-4 grid grid-cols-1">
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-2 [&#38;>*]:py-1 [&#38;>*]:text-xs [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      XS
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      XS
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      XS
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-2 [&#38;>*]:py-1 [&#38;>*]:text-sm [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      SM
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      SM
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      SM
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      MD
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      MD
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      MD
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-4 [&#38;>*]:py-2 [&#38;>*]:text-base [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      LG
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      LG
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      LG
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-5 [&#38;>*]:py-3 [&#38;>*]:text-lg [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      XL
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      XL
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      XL
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-6 [&#38;>*]:py-4 [&#38;>*]:text-xl [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      2XL
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      2XL
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      2XL
    </button>
  </div>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup size="xs" withDividers={true}>
<Button variant="solid" color="blue">XS</Button>
<Button variant="solid" color="blue">XS</Button>
<Button variant="solid" color="blue">XS</Button>
</ButtonGroup>

<ButtonGroup size="sm" withDividers={true}>
<Button variant="solid" color="blue">SM</Button>
<Button variant="solid" color="blue">SM</Button>
<Button variant="solid" color="blue">SM</Button>
</ButtonGroup>

<ButtonGroup size="md" withDividers={true}>
<Button variant="solid" color="blue">MD</Button>
<Button variant="solid" color="blue">MD</Button>
<Button variant="solid" color="blue">MD</Button>
</ButtonGroup>

<ButtonGroup size="lg" withDividers={true}>
<Button variant="solid" color="blue">LG</Button>
<Button variant="solid" color="blue">LG</Button>
<Button variant="solid" color="blue">LG</Button>
</ButtonGroup>

<ButtonGroup size="xl" withDividers={true}>
<Button variant="solid" color="blue">XL</Button>
<Button variant="solid" color="blue">XL</Button>
<Button variant="solid" color="blue">XL</Button>
</ButtonGroup>

<ButtonGroup size="2xl" withDividers={true}>
<Button variant="solid" color="blue">2XL</Button>
<Button variant="solid" color="blue">2XL</Button>
<Button variant="solid" color="blue">2XL</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group with Different Item Counts

Button groups with 2, 3, 4, 5, and 6 items.

 
<div class="space-y-4 grid grid-cols-1">
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 1
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 2
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 1
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 2
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 3
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 1
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 2
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 3
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 4
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 1
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 2
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 3
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 4
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 5
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 1
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 2
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 3
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 4
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 5
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Button 6
    </button>
  </div>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup items={2} withDividers={true}>
<Button variant="solid" color="blue">Button 1</Button>
<Button variant="solid" color="blue">Button 2</Button>
</ButtonGroup>

<ButtonGroup items={3} withDividers={true}>
<Button variant="solid" color="blue">Button 1</Button>
<Button variant="solid" color="blue">Button 2</Button>
<Button variant="solid" color="blue">Button 3</Button>
</ButtonGroup>

<ButtonGroup items={4} withDividers={true}>
<Button variant="solid" color="blue">Button 1</Button>
<Button variant="solid" color="blue">Button 2</Button>
<Button variant="solid" color="blue">Button 3</Button>
<Button variant="solid" color="blue">Button 4</Button>
</ButtonGroup>

<ButtonGroup items={5} withDividers={true}>
<Button variant="solid" color="blue">Button 1</Button>
<Button variant="solid" color="blue">Button 2</Button>
<Button variant="solid" color="blue">Button 3</Button>
<Button variant="solid" color="blue">Button 4</Button>
<Button variant="solid" color="blue">Button 5</Button>
</ButtonGroup>

<ButtonGroup items={6} withDividers={true}>
<Button variant="solid" color="blue">Button 1</Button>
<Button variant="solid" color="blue">Button 2</Button>
<Button variant="solid" color="blue">Button 3</Button>
<Button variant="solid" color="blue">Button 4</Button>
<Button variant="solid" color="blue">Button 5</Button>
<Button variant="solid" color="blue">Button 6</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Vertical Button Group with Many Items

Vertical button group with multiple items.

 
<div
  class="inline-flex overflow-hidden flex-col [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-t-md [&#38;>*:last-child]:rounded-b-md [&#38;>*:not(:first-child)]:-mt-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 1
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 2
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 3
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 4
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 5
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Button 6
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup orientation="vertical">
<Button variant="solid" color="blue">Button 1</Button>
<Button variant="solid" color="blue">Button 2</Button>
<Button variant="solid" color="blue">Button 3</Button>
<Button variant="solid" color="blue">Button 4</Button>
<Button variant="solid" color="blue">Button 5</Button>
<Button variant="solid" color="blue">Button 6</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group with Icons

Button group with icons in buttons.

 
<div
  class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:inline-flex [&#38;>*]:items-center [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    User
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          d="M17.004 10.407c.138.435-.216.842-.672.842h-3.465a.75.75 0 0 1-.65-.375l-1.732-3c-.229-.396-.053-.907.393-1.004a5.252 5.252 0 0 1 6.126 3.537ZM8.12 8.464c.307-.338.838-.235 1.066.16l1.732 3a.75.75 0 0 1 0 .75l-1.732 3c-.229.397-.76.5-1.067.161A5.23 5.23 0 0 1 6.75 12a5.23 5.23 0 0 1 1.37-3.536ZM10.878 17.13c-.447-.098-.623-.608-.394-1.004l1.733-3.002a.75.75 0 0 1 .65-.375h3.465c.457 0 .81.407.672.842a5.252 5.252 0 0 1-6.126 3.539Z"></path>
        <path
          fill-rule="evenodd"
          d="M21 12.75a.75.75 0 1 0 0-1.5h-.783a8.22 8.22 0 0 0-.237-1.357l.734-.267a.75.75 0 1 0-.513-1.41l-.735.268a8.24 8.24 0 0 0-.689-1.192l.6-.503a.75.75 0 1 0-.964-1.149l-.6.504a8.3 8.3 0 0 0-1.054-.885l.391-.678a.75.75 0 1 0-1.299-.75l-.39.676a8.188 8.188 0 0 0-1.295-.47l.136-.77a.75.75 0 0 0-1.477-.26l-.136.77a8.36 8.36 0 0 0-1.377 0l-.136-.77a.75.75 0 1 0-1.477.26l.136.77c-.448.121-.88.28-1.294.47l-.39-.676a.75.75 0 0 0-1.3.75l.392.678a8.29 8.29 0 0 0-1.054.885l-.6-.504a.75.75 0 1 0-.965 1.149l.6.503a8.243 8.243 0 0 0-.689 1.192L3.8 8.216a.75.75 0 1 0-.513 1.41l.735.267a8.222 8.222 0 0 0-.238 1.356h-.783a.75.75 0 0 0 0 1.5h.783c.042.464.122.917.238 1.356l-.735.268a.75.75 0 0 0 .513 1.41l.735-.268c.197.417.428.816.69 1.191l-.6.504a.75.75 0 0 0 .963 1.15l.601-.505c.326.323.679.62 1.054.885l-.392.68a.75.75 0 0 0 1.3.75l.39-.679c.414.192.847.35 1.294.471l-.136.77a.75.75 0 0 0 1.477.261l.137-.772a8.332 8.332 0 0 0 1.376 0l.136.772a.75.75 0 1 0 1.477-.26l-.136-.771a8.19 8.19 0 0 0 1.294-.47l.391.677a.75.75 0 0 0 1.3-.75l-.393-.679a8.29 8.29 0 0 0 1.054-.885l.601.504a.75.75 0 0 0 .964-1.15l-.6-.503c.261-.375.492-.774.69-1.191l.735.267a.75.75 0 1 0 .512-1.41l-.734-.267c.115-.439.195-.892.237-1.356h.784Zm-2.657-3.06a6.744 6.744 0 0 0-1.19-2.053 6.784 6.784 0 0 0-1.82-1.51A6.705 6.705 0 0 0 12 5.25a6.8 6.8 0 0 0-1.225.11 6.7 6.7 0 0 0-2.15.793 6.784 6.784 0 0 0-2.952 3.489.76.76 0 0 1-.036.098A6.74 6.74 0 0 0 5.251 12a6.74 6.74 0 0 0 3.366 5.842l.009.005a6.704 6.704 0 0 0 2.18.798l.022.003a6.792 6.792 0 0 0 2.368-.004 6.704 6.704 0 0 0 2.205-.811 6.785 6.785 0 0 0 1.762-1.484l.009-.01.009-.01a6.743 6.743 0 0 0 1.18-2.066c.253-.707.39-1.469.39-2.263a6.74 6.74 0 0 0-.408-2.309Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Settings
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M5.25 9a6.75 6.75 0 0 1 13.5 0v.75c0 2.123.8 4.057 2.118 5.52a.75.75 0 0 1-.297 1.206c-1.544.57-3.16.99-4.831 1.243a3.75 3.75 0 1 1-7.48 0 24.585 24.585 0 0 1-4.831-1.244.75.75 0 0 1-.298-1.205A8.217 8.217 0 0 0 5.25 9.75V9Zm4.502 8.9a2.25 2.25 0 1 0 4.496 0 25.057 25.057 0 0 1-4.496 0Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Notifications
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup withIcons>
<Button variant="solid" color="blue" icon="UserIcon">User</Button>
<Button variant="solid" color="blue" icon="CogIcon">Settings</Button>
<Button variant="solid" color="blue" icon="BellIcon">Notifications</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group with Icons and Dividers

Button group with icons in buttons and dividers.

 
<div
  class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:inline-flex [&#38;>*]:items-center [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    User
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          d="M17.004 10.407c.138.435-.216.842-.672.842h-3.465a.75.75 0 0 1-.65-.375l-1.732-3c-.229-.396-.053-.907.393-1.004a5.252 5.252 0 0 1 6.126 3.537ZM8.12 8.464c.307-.338.838-.235 1.066.16l1.732 3a.75.75 0 0 1 0 .75l-1.732 3c-.229.397-.76.5-1.067.161A5.23 5.23 0 0 1 6.75 12a5.23 5.23 0 0 1 1.37-3.536ZM10.878 17.13c-.447-.098-.623-.608-.394-1.004l1.733-3.002a.75.75 0 0 1 .65-.375h3.465c.457 0 .81.407.672.842a5.252 5.252 0 0 1-6.126 3.539Z"></path>
        <path
          fill-rule="evenodd"
          d="M21 12.75a.75.75 0 1 0 0-1.5h-.783a8.22 8.22 0 0 0-.237-1.357l.734-.267a.75.75 0 1 0-.513-1.41l-.735.268a8.24 8.24 0 0 0-.689-1.192l.6-.503a.75.75 0 1 0-.964-1.149l-.6.504a8.3 8.3 0 0 0-1.054-.885l.391-.678a.75.75 0 1 0-1.299-.75l-.39.676a8.188 8.188 0 0 0-1.295-.47l.136-.77a.75.75 0 0 0-1.477-.26l-.136.77a8.36 8.36 0 0 0-1.377 0l-.136-.77a.75.75 0 1 0-1.477.26l.136.77c-.448.121-.88.28-1.294.47l-.39-.676a.75.75 0 0 0-1.3.75l.392.678a8.29 8.29 0 0 0-1.054.885l-.6-.504a.75.75 0 1 0-.965 1.149l.6.503a8.243 8.243 0 0 0-.689 1.192L3.8 8.216a.75.75 0 1 0-.513 1.41l.735.267a8.222 8.222 0 0 0-.238 1.356h-.783a.75.75 0 0 0 0 1.5h.783c.042.464.122.917.238 1.356l-.735.268a.75.75 0 0 0 .513 1.41l.735-.268c.197.417.428.816.69 1.191l-.6.504a.75.75 0 0 0 .963 1.15l.601-.505c.326.323.679.62 1.054.885l-.392.68a.75.75 0 0 0 1.3.75l.39-.679c.414.192.847.35 1.294.471l-.136.77a.75.75 0 0 0 1.477.261l.137-.772a8.332 8.332 0 0 0 1.376 0l.136.772a.75.75 0 1 0 1.477-.26l-.136-.771a8.19 8.19 0 0 0 1.294-.47l.391.677a.75.75 0 0 0 1.3-.75l-.393-.679a8.29 8.29 0 0 0 1.054-.885l.601.504a.75.75 0 0 0 .964-1.15l-.6-.503c.261-.375.492-.774.69-1.191l.735.267a.75.75 0 1 0 .512-1.41l-.734-.267c.115-.439.195-.892.237-1.356h.784Zm-2.657-3.06a6.744 6.744 0 0 0-1.19-2.053 6.784 6.784 0 0 0-1.82-1.51A6.705 6.705 0 0 0 12 5.25a6.8 6.8 0 0 0-1.225.11 6.7 6.7 0 0 0-2.15.793 6.784 6.784 0 0 0-2.952 3.489.76.76 0 0 1-.036.098A6.74 6.74 0 0 0 5.251 12a6.74 6.74 0 0 0 3.366 5.842l.009.005a6.704 6.704 0 0 0 2.18.798l.022.003a6.792 6.792 0 0 0 2.368-.004 6.704 6.704 0 0 0 2.205-.811 6.785 6.785 0 0 0 1.762-1.484l.009-.01.009-.01a6.743 6.743 0 0 0 1.18-2.066c.253-.707.39-1.469.39-2.263a6.74 6.74 0 0 0-.408-2.309Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Settings
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M5.25 9a6.75 6.75 0 0 1 13.5 0v.75c0 2.123.8 4.057 2.118 5.52a.75.75 0 0 1-.297 1.206c-1.544.57-3.16.99-4.831 1.243a3.75 3.75 0 1 1-7.48 0 24.585 24.585 0 0 1-4.831-1.244.75.75 0 0 1-.298-1.205A8.217 8.217 0 0 0 5.25 9.75V9Zm4.502 8.9a2.25 2.25 0 1 0 4.496 0 25.057 25.057 0 0 1-4.496 0Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Notifications
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup withIcons withDividers={true}>
<Button variant="solid" color="blue" icon="UserIcon">User</Button>
<Button variant="solid" color="blue" icon="CogIcon">Settings</Button>
<Button variant="solid" color="blue" icon="BellIcon">Notifications</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group with Icons and Dividers

Button group with icons in buttons and dividers.

 
<div
  class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:inline-flex [&#38;>*]:items-center [&#38;>*]:justify-center divide-x divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-transparent text-blue-500 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-200 hover:bg-blue-200 dark:hover:bg-blue-700 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    User
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-transparent text-blue-500 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-200 hover:bg-blue-200 dark:hover:bg-blue-700 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          d="M17.004 10.407c.138.435-.216.842-.672.842h-3.465a.75.75 0 0 1-.65-.375l-1.732-3c-.229-.396-.053-.907.393-1.004a5.252 5.252 0 0 1 6.126 3.537ZM8.12 8.464c.307-.338.838-.235 1.066.16l1.732 3a.75.75 0 0 1 0 .75l-1.732 3c-.229.397-.76.5-1.067.161A5.23 5.23 0 0 1 6.75 12a5.23 5.23 0 0 1 1.37-3.536ZM10.878 17.13c-.447-.098-.623-.608-.394-1.004l1.733-3.002a.75.75 0 0 1 .65-.375h3.465c.457 0 .81.407.672.842a5.252 5.252 0 0 1-6.126 3.539Z"></path>
        <path
          fill-rule="evenodd"
          d="M21 12.75a.75.75 0 1 0 0-1.5h-.783a8.22 8.22 0 0 0-.237-1.357l.734-.267a.75.75 0 1 0-.513-1.41l-.735.268a8.24 8.24 0 0 0-.689-1.192l.6-.503a.75.75 0 1 0-.964-1.149l-.6.504a8.3 8.3 0 0 0-1.054-.885l.391-.678a.75.75 0 1 0-1.299-.75l-.39.676a8.188 8.188 0 0 0-1.295-.47l.136-.77a.75.75 0 0 0-1.477-.26l-.136.77a8.36 8.36 0 0 0-1.377 0l-.136-.77a.75.75 0 1 0-1.477.26l.136.77c-.448.121-.88.28-1.294.47l-.39-.676a.75.75 0 0 0-1.3.75l.392.678a8.29 8.29 0 0 0-1.054.885l-.6-.504a.75.75 0 1 0-.965 1.149l.6.503a8.243 8.243 0 0 0-.689 1.192L3.8 8.216a.75.75 0 1 0-.513 1.41l.735.267a8.222 8.222 0 0 0-.238 1.356h-.783a.75.75 0 0 0 0 1.5h.783c.042.464.122.917.238 1.356l-.735.268a.75.75 0 0 0 .513 1.41l.735-.268c.197.417.428.816.69 1.191l-.6.504a.75.75 0 0 0 .963 1.15l.601-.505c.326.323.679.62 1.054.885l-.392.68a.75.75 0 0 0 1.3.75l.39-.679c.414.192.847.35 1.294.471l-.136.77a.75.75 0 0 0 1.477.261l.137-.772a8.332 8.332 0 0 0 1.376 0l.136.772a.75.75 0 1 0 1.477-.26l-.136-.771a8.19 8.19 0 0 0 1.294-.47l.391.677a.75.75 0 0 0 1.3-.75l-.393-.679a8.29 8.29 0 0 0 1.054-.885l.601.504a.75.75 0 0 0 .964-1.15l-.6-.503c.261-.375.492-.774.69-1.191l.735.267a.75.75 0 1 0 .512-1.41l-.734-.267c.115-.439.195-.892.237-1.356h.784Zm-2.657-3.06a6.744 6.744 0 0 0-1.19-2.053 6.784 6.784 0 0 0-1.82-1.51A6.705 6.705 0 0 0 12 5.25a6.8 6.8 0 0 0-1.225.11 6.7 6.7 0 0 0-2.15.793 6.784 6.784 0 0 0-2.952 3.489.76.76 0 0 1-.036.098A6.74 6.74 0 0 0 5.251 12a6.74 6.74 0 0 0 3.366 5.842l.009.005a6.704 6.704 0 0 0 2.18.798l.022.003a6.792 6.792 0 0 0 2.368-.004 6.704 6.704 0 0 0 2.205-.811 6.785 6.785 0 0 0 1.762-1.484l.009-.01.009-.01a6.743 6.743 0 0 0 1.18-2.066c.253-.707.39-1.469.39-2.263a6.74 6.74 0 0 0-.408-2.309Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Settings
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-transparent text-blue-500 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-200 hover:bg-blue-200 dark:hover:bg-blue-700 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M5.25 9a6.75 6.75 0 0 1 13.5 0v.75c0 2.123.8 4.057 2.118 5.52a.75.75 0 0 1-.297 1.206c-1.544.57-3.16.99-4.831 1.243a3.75 3.75 0 1 1-7.48 0 24.585 24.585 0 0 1-4.831-1.244.75.75 0 0 1-.298-1.205A8.217 8.217 0 0 0 5.25 9.75V9Zm4.502 8.9a2.25 2.25 0 1 0 4.496 0 25.057 25.057 0 0 1-4.496 0Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Notifications
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup withIcons withDividers={true}>
<Button variant="ghost" color="blue" icon="UserIcon">User</Button>
<Button variant="ghost" color="blue" icon="CogIcon">Settings</Button>
<Button variant="ghost" color="blue" icon="BellIcon">Notifications</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Vertical Button Group with Icons

Vertical button group with icons in buttons.

 
<div
  class="inline-flex overflow-hidden flex-col [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:inline-flex [&#38;>*]:items-center [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-t-md [&#38;>*:last-child]:rounded-b-md [&#38;>*:not(:first-child)]:-mt-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    User
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          d="M17.004 10.407c.138.435-.216.842-.672.842h-3.465a.75.75 0 0 1-.65-.375l-1.732-3c-.229-.396-.053-.907.393-1.004a5.252 5.252 0 0 1 6.126 3.537ZM8.12 8.464c.307-.338.838-.235 1.066.16l1.732 3a.75.75 0 0 1 0 .75l-1.732 3c-.229.397-.76.5-1.067.161A5.23 5.23 0 0 1 6.75 12a5.23 5.23 0 0 1 1.37-3.536ZM10.878 17.13c-.447-.098-.623-.608-.394-1.004l1.733-3.002a.75.75 0 0 1 .65-.375h3.465c.457 0 .81.407.672.842a5.252 5.252 0 0 1-6.126 3.539Z"></path>
        <path
          fill-rule="evenodd"
          d="M21 12.75a.75.75 0 1 0 0-1.5h-.783a8.22 8.22 0 0 0-.237-1.357l.734-.267a.75.75 0 1 0-.513-1.41l-.735.268a8.24 8.24 0 0 0-.689-1.192l.6-.503a.75.75 0 1 0-.964-1.149l-.6.504a8.3 8.3 0 0 0-1.054-.885l.391-.678a.75.75 0 1 0-1.299-.75l-.39.676a8.188 8.188 0 0 0-1.295-.47l.136-.77a.75.75 0 0 0-1.477-.26l-.136.77a8.36 8.36 0 0 0-1.377 0l-.136-.77a.75.75 0 1 0-1.477.26l.136.77c-.448.121-.88.28-1.294.47l-.39-.676a.75.75 0 0 0-1.3.75l.392.678a8.29 8.29 0 0 0-1.054.885l-.6-.504a.75.75 0 1 0-.965 1.149l.6.503a8.243 8.243 0 0 0-.689 1.192L3.8 8.216a.75.75 0 1 0-.513 1.41l.735.267a8.222 8.222 0 0 0-.238 1.356h-.783a.75.75 0 0 0 0 1.5h.783c.042.464.122.917.238 1.356l-.735.268a.75.75 0 0 0 .513 1.41l.735-.268c.197.417.428.816.69 1.191l-.6.504a.75.75 0 0 0 .963 1.15l.601-.505c.326.323.679.62 1.054.885l-.392.68a.75.75 0 0 0 1.3.75l.39-.679c.414.192.847.35 1.294.471l-.136.77a.75.75 0 0 0 1.477.261l.137-.772a8.332 8.332 0 0 0 1.376 0l.136.772a.75.75 0 1 0 1.477-.26l-.136-.771a8.19 8.19 0 0 0 1.294-.47l.391.677a.75.75 0 0 0 1.3-.75l-.393-.679a8.29 8.29 0 0 0 1.054-.885l.601.504a.75.75 0 0 0 .964-1.15l-.6-.503c.261-.375.492-.774.69-1.191l.735.267a.75.75 0 1 0 .512-1.41l-.734-.267c.115-.439.195-.892.237-1.356h.784Zm-2.657-3.06a6.744 6.744 0 0 0-1.19-2.053 6.784 6.784 0 0 0-1.82-1.51A6.705 6.705 0 0 0 12 5.25a6.8 6.8 0 0 0-1.225.11 6.7 6.7 0 0 0-2.15.793 6.784 6.784 0 0 0-2.952 3.489.76.76 0 0 1-.036.098A6.74 6.74 0 0 0 5.251 12a6.74 6.74 0 0 0 3.366 5.842l.009.005a6.704 6.704 0 0 0 2.18.798l.022.003a6.792 6.792 0 0 0 2.368-.004 6.704 6.704 0 0 0 2.205-.811 6.785 6.785 0 0 0 1.762-1.484l.009-.01.009-.01a6.743 6.743 0 0 0 1.18-2.066c.253-.707.39-1.469.39-2.263a6.74 6.74 0 0 0-.408-2.309Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Settings
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M5.25 9a6.75 6.75 0 0 1 13.5 0v.75c0 2.123.8 4.057 2.118 5.52a.75.75 0 0 1-.297 1.206c-1.544.57-3.16.99-4.831 1.243a3.75 3.75 0 1 1-7.48 0 24.585 24.585 0 0 1-4.831-1.244.75.75 0 0 1-.298-1.205A8.217 8.217 0 0 0 5.25 9.75V9Zm4.502 8.9a2.25 2.25 0 1 0 4.496 0 25.057 25.057 0 0 1-4.496 0Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Notifications
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup orientation="vertical" withIcons>
<Button variant="solid" color="blue" icon="UserIcon">User</Button>
<Button variant="solid" color="blue" icon="CogIcon">Settings</Button>
<Button variant="solid" color="blue" icon="BellIcon">Notifications</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group with Different Button Variants

Button group with various button variants.

 
<div
  class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
    Solid
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-transparent text-blue-500 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-200 border-blue-500 dark:border-blue-400 hover:border-blue-700 dark:hover:border-blue-200 border px-3 py-2 text-sm rounded-md">
    Outline
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-transparent text-blue-500 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-200 hover:bg-blue-200 dark:hover:bg-blue-700 px-3 py-2 text-sm rounded-md">
    Ghost
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-100 dark:bg-blue-800 hover:bg-blue-200 dark:hover:bg-blue-700 text-blue-700 dark:text-blue-100 border-blue-200 dark:border-blue-600 px-3 py-2 text-sm rounded-md">
    Soft
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 text-blue-700 dark:text-blue-100 hover:opacity-70 px-3 py-2 text-sm rounded-md">
    Text
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup>
<Button variant="solid" color="blue">Solid</Button>
<Button variant="outline" color="blue">Outline</Button>
<Button variant="ghost" color="blue">Ghost</Button>
<Button variant="soft" color="blue">Soft</Button>
<Button variant="text" color="blue">Text</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group with and without Border

Comparison of ButtonGroup with showBorder prop set to true and false.

 
<div class="space-y-4">
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      With Border
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      With Border
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      With Border
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      No Border
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      No Border
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      No Border
    </button>
  </div>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup showBorder={true}>
<Button variant="solid" color="blue">With Border</Button>
<Button variant="solid" color="blue">With Border</Button>
<Button variant="solid" color="blue">With Border</Button>
</ButtonGroup>

<ButtonGroup showBorder={false}>
<Button variant="solid" color="blue">No Border</Button>
<Button variant="solid" color="blue">No Border</Button>
<Button variant="solid" color="blue">No Border</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group with Custom Classes

ButtonGroup with additional custom classes applied.

 
<div
  class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px shadow-lg rounded-full"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-purple-500 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 text-white dark:text-white hover:text-purple-100 dark:hover:text-purple-200 px-3 py-2 text-sm rounded-md">
    Custom
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-purple-500 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 text-white dark:text-white hover:text-purple-100 dark:hover:text-purple-200 px-3 py-2 text-sm rounded-md">
    Styled
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-purple-500 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 text-white dark:text-white hover:text-purple-100 dark:hover:text-purple-200 px-3 py-2 text-sm rounded-md">
    Group
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup class="shadow-lg rounded-full">
<Button variant="solid" color="purple">Custom</Button>
<Button variant="solid" color="purple">Styled</Button>
<Button variant="solid" color="purple">Group</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Complex Button Group Example

A complex ButtonGroup combining multiple options.

 
<div
  class="inline-flex overflow-hidden flex-col [&#38;>*]:px-4 [&#38;>*]:py-2 [&#38;>*]:text-base [&#38;>*]:inline-flex [&#38;>*]:items-center [&#38;>*]:justify-center divide-y divide-gray-300 dark:divide-gray-600 rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-t-md [&#38;>*:last-child]:rounded-b-md [&#38;>*:not(:first-child)]:-mt-px max-w-xs mx-auto shadow-xl"
  role="group">
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M7.5 6a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM3.751 20.105a8.25 8.25 0 0 1 16.498 0 .75.75 0 0 1-.437.695A18.683 18.683 0 0 1 12 22.5c-2.786 0-5.433-.608-7.812-1.7a.75.75 0 0 1-.437-.695Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Profile
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          d="M17.004 10.407c.138.435-.216.842-.672.842h-3.465a.75.75 0 0 1-.65-.375l-1.732-3c-.229-.396-.053-.907.393-1.004a5.252 5.252 0 0 1 6.126 3.537ZM8.12 8.464c.307-.338.838-.235 1.066.16l1.732 3a.75.75 0 0 1 0 .75l-1.732 3c-.229.397-.76.5-1.067.161A5.23 5.23 0 0 1 6.75 12a5.23 5.23 0 0 1 1.37-3.536ZM10.878 17.13c-.447-.098-.623-.608-.394-1.004l1.733-3.002a.75.75 0 0 1 .65-.375h3.465c.457 0 .81.407.672.842a5.252 5.252 0 0 1-6.126 3.539Z"></path>
        <path
          fill-rule="evenodd"
          d="M21 12.75a.75.75 0 1 0 0-1.5h-.783a8.22 8.22 0 0 0-.237-1.357l.734-.267a.75.75 0 1 0-.513-1.41l-.735.268a8.24 8.24 0 0 0-.689-1.192l.6-.503a.75.75 0 1 0-.964-1.149l-.6.504a8.3 8.3 0 0 0-1.054-.885l.391-.678a.75.75 0 1 0-1.299-.75l-.39.676a8.188 8.188 0 0 0-1.295-.47l.136-.77a.75.75 0 0 0-1.477-.26l-.136.77a8.36 8.36 0 0 0-1.377 0l-.136-.77a.75.75 0 1 0-1.477.26l.136.77c-.448.121-.88.28-1.294.47l-.39-.676a.75.75 0 0 0-1.3.75l.392.678a8.29 8.29 0 0 0-1.054.885l-.6-.504a.75.75 0 1 0-.965 1.149l.6.503a8.243 8.243 0 0 0-.689 1.192L3.8 8.216a.75.75 0 1 0-.513 1.41l.735.267a8.222 8.222 0 0 0-.238 1.356h-.783a.75.75 0 0 0 0 1.5h.783c.042.464.122.917.238 1.356l-.735.268a.75.75 0 0 0 .513 1.41l.735-.268c.197.417.428.816.69 1.191l-.6.504a.75.75 0 0 0 .963 1.15l.601-.505c.326.323.679.62 1.054.885l-.392.68a.75.75 0 0 0 1.3.75l.39-.679c.414.192.847.35 1.294.471l-.136.77a.75.75 0 0 0 1.477.261l.137-.772a8.332 8.332 0 0 0 1.376 0l.136.772a.75.75 0 1 0 1.477-.26l-.136-.771a8.19 8.19 0 0 0 1.294-.47l.391.677a.75.75 0 0 0 1.3-.75l-.393-.679a8.29 8.29 0 0 0 1.054-.885l.601.504a.75.75 0 0 0 .964-1.15l-.6-.503c.261-.375.492-.774.69-1.191l.735.267a.75.75 0 1 0 .512-1.41l-.734-.267c.115-.439.195-.892.237-1.356h.784Zm-2.657-3.06a6.744 6.744 0 0 0-1.19-2.053 6.784 6.784 0 0 0-1.82-1.51A6.705 6.705 0 0 0 12 5.25a6.8 6.8 0 0 0-1.225.11 6.7 6.7 0 0 0-2.15.793 6.784 6.784 0 0 0-2.952 3.489.76.76 0 0 1-.036.098A6.74 6.74 0 0 0 5.251 12a6.74 6.74 0 0 0 3.366 5.842l.009.005a6.704 6.704 0 0 0 2.18.798l.022.003a6.792 6.792 0 0 0 2.368-.004 6.704 6.704 0 0 0 2.205-.811 6.785 6.785 0 0 0 1.762-1.484l.009-.01.009-.01a6.743 6.743 0 0 0 1.18-2.066c.253-.707.39-1.469.39-2.263a6.74 6.74 0 0 0-.408-2.309Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Settings
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M5.25 9a6.75 6.75 0 0 1 13.5 0v.75c0 2.123.8 4.057 2.118 5.52a.75.75 0 0 1-.297 1.206c-1.544.57-3.16.99-4.831 1.243a3.75 3.75 0 1 1-7.48 0 24.585 24.585 0 0 1-4.831-1.244.75.75 0 0 1-.298-1.205A8.217 8.217 0 0 0 5.25 9.75V9Zm4.502 8.9a2.25 2.25 0 1 0 4.496 0 25.057 25.057 0 0 1-4.496 0Z"
          clip-rule="evenodd"></path>
      </svg>
    </span>
    Notifications
  </button>
  <button
    class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
    <span class="inline-block size-5 w-5 h-5 mr-2">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="currentColor"
        aria-hidden="true"
        data-slot="icon">
        <path
          fill-rule="evenodd"
          d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm11.378-3.917c-.89-.777-2.366-.777-3.255 0a.75.75 0 0 1-.988-1.129c1.454-1.272 3.776-1.272 5.23 0 1.513 1.324 1.513 3.518 0 4.842a3.75 3.75 0 0 1-.837.552c-.676.328-1.028.774-1.028 1.152v.75a.75.75 0 0 1-1.5 0v-.75c0-1.279 1.06-2.107 1.875-2.502.182-.088.351-.199.503-.331.83-.727.83-1.857 0-2.584ZM12 18a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
          clip-rule="evenodd"></path>
      </svg>
      <span class="sr-only">Unknown icon</span>
    </span>
    Logout
  </button>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup
orientation="vertical"
size="lg"
withIcons
withDividers={true}
showBorder={true}
class="max-w-xs mx-auto shadow-xl"
>
<Button variant="solid" color="indigo" icon="UserIcon">Profile</Button>
<Button variant="solid" color="indigo" icon="CogIcon">Settings</Button>
<Button variant="solid" color="indigo" icon="BellIcon">Notifications</Button>
<Button variant="solid" color="indigo" icon="LogoutIcon">Logout</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group Shapes

Button groups with different shapes: default, pill, and square.

 
<div class="space-y-4 grid grid-cols-1 w-fit">
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-md [&#38;>*:last-child]:rounded-r-md [&#38;>*:not(:first-child)]:-ml-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Default
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Shape
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Buttons
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm rounded-full [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-l-full [&#38;>*:last-child]:rounded-r-full [&#38;>*]:justify-center"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
      Pill
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
      Shape
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
      Buttons
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-row [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm rounded-none [&#38;>*]:rounded-none [&#38;>*]:justify-center"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-purple-500 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 text-white dark:text-white hover:text-purple-100 dark:hover:text-purple-200 px-3 py-2 text-sm rounded-md">
      Square
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-purple-500 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 text-white dark:text-white hover:text-purple-100 dark:hover:text-purple-200 px-3 py-2 text-sm rounded-md">
      Shape
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-purple-500 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 text-white dark:text-white hover:text-purple-100 dark:hover:text-purple-200 px-3 py-2 text-sm rounded-md">
      Buttons
    </button>
  </div>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup shape="default">
<Button variant="solid" color="blue">Default</Button>
<Button variant="solid" color="blue">Shape</Button>
<Button variant="solid" color="blue">Buttons</Button>
</ButtonGroup>

<ButtonGroup shape="pill">
<Button variant="solid" color="indigo">Pill</Button>
<Button variant="solid" color="indigo">Shape</Button>
<Button variant="solid" color="indigo">Buttons</Button>
</ButtonGroup>

<ButtonGroup shape="square">
<Button variant="solid" color="purple">Square</Button>
<Button variant="solid" color="purple">Shape</Button>
<Button variant="solid" color="purple">Buttons</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Button Group Alignments

Button groups with different content alignments: left, center, and right.

 
<div class="grid grid-cols-3 w-fit gap-8">
  <div
    class="inline-flex overflow-hidden flex-col [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-start rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-t-md [&#38;>*:last-child]:rounded-b-md [&#38;>*:not(:first-child)]:-mt-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Left
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Aligned
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-500 text-white dark:text-white hover:text-blue-100 dark:hover:text-blue-200 px-3 py-2 text-sm rounded-md">
      Buttons
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-col [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-center rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-t-md [&#38;>*:last-child]:rounded-b-md [&#38;>*:not(:first-child)]:-mt-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-purple-500 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 text-white dark:text-white hover:text-purple-100 dark:hover:text-purple-200 px-3 py-2 text-sm rounded-md">
      Center
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-purple-500 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 text-white dark:text-white hover:text-purple-100 dark:hover:text-purple-200 px-3 py-2 text-sm rounded-md">
      Aligned
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-purple-500 hover:bg-purple-600 dark:bg-purple-600 dark:hover:bg-purple-500 text-white dark:text-white hover:text-purple-100 dark:hover:text-purple-200 px-3 py-2 text-sm rounded-md">
      Buttons
    </button>
  </div>
  <div
    class="inline-flex overflow-hidden flex-col [&#38;>*]:px-3 [&#38;>*]:py-2 [&#38;>*]:text-sm [&#38;>*]:justify-end rounded-md [&#38;>*]:rounded-none [&#38;>*:first-child]:rounded-t-md [&#38;>*:last-child]:rounded-b-md [&#38;>*:not(:first-child)]:-mt-px"
    role="group">
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
      Right
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
      Aligned
    </button>
    <button
      class="inline-flex items-center justify-center font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 bg-indigo-500 hover:bg-indigo-600 dark:bg-indigo-600 dark:hover:bg-indigo-500 text-white dark:text-white hover:text-indigo-100 dark:hover:text-indigo-200 px-3 py-2 text-sm rounded-md">
      Buttons
    </button>
  </div>
</div>
---
import { ButtonGroup } from '@/components/ui/buttongroup';
import { Button } from '@/components/ui/button';

---

<ButtonGroup alignment="left" orientation="vertical">
<Button variant="solid" color="blue">Left</Button>
<Button variant="solid" color="blue">Aligned</Button>
<Button variant="solid" color="blue">Buttons</Button>
</ButtonGroup>

<ButtonGroup alignment="center" orientation="vertical">
<Button variant="solid" color="purple">Center</Button>
<Button variant="solid" color="purple">Aligned</Button>
<Button variant="solid" color="purple">Buttons</Button>
</ButtonGroup>

<ButtonGroup alignment="right" orientation="vertical">
<Button variant="solid" color="indigo">Right</Button>
<Button variant="solid" color="indigo">Aligned</Button>
<Button variant="solid" color="indigo">Buttons</Button>
</ButtonGroup>
---
// Imports
import { type HTMLAttributes } from "astro/types";
import { tv, type VariantProps } from "@utils/custom-tv";
import { twMerge } from "tailwind-merge";

// Types and Interfaces
type ButtonGroupVariants = VariantProps<typeof buttonGroupStyles>;

interface Props extends HTMLAttributes<"div">, ButtonGroupVariants {
  orientation?: "horizontal" | "vertical";
  size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
  items?: 2 | 3 | 4 | 5 | 6;
  withIcons?: boolean;
  withDividers?: boolean;
  shape?: "default" | "pill" | "square";
  alignment?: "left" | "center" | "right";
  class?: string;
}

// Styles
const buttonGroupStyles = tv({
  base: "inline-flex overflow-hidden",
  variants: {
    orientation: {
      horizontal: "flex-row",
      vertical: "flex-col",
    },
    size: {
      xs: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-xs",
      sm: "[&>*]:px-2 [&>*]:py-1 [&>*]:text-sm",
      md: "[&>*]:px-3 [&>*]:py-2 [&>*]:text-sm",
      lg: "[&>*]:px-4 [&>*]:py-2 [&>*]:text-base",
      xl: "[&>*]:px-5 [&>*]:py-3 [&>*]:text-lg",
      "2xl": "[&>*]:px-6 [&>*]:py-4 [&>*]:text-xl",
    },
    items: {
      2: "",
      3: "",
      4: "",
      5: "",
      6: "",
    },
    withIcons: {
      true: "[&>*]:inline-flex [&>*]:items-center [&>*]:justify-center",
      false: "",
    },
    withDividers: {
      true: "",
      false: "",
    },
    shape: {
      default: "",
      pill: "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-l-full [&>*:last-child]:rounded-r-full",
      square: "rounded-none [&>*]:rounded-none",
    },
    alignment: {
      left: "[&>*]:justify-start",
      center: "[&>*]:justify-center",
      right: "[&>*]:justify-end",
    },
  },
  compoundVariants: [
    {
      orientation: "horizontal",
      withDividers: true,
      class: "divide-x divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "vertical",
      withDividers: true,
      class: "divide-y divide-gray-300 dark:divide-gray-600",
    },
    {
      orientation: "horizontal",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-l-md 
        [&>*:last-child]:rounded-r-md 
        [&>*:not(:first-child)]:-ml-px
      `,
    },
    {
      orientation: "vertical",
      shape: "default",
      class: `
        rounded-md 
        [&>*]:rounded-none 
        [&>*:first-child]:rounded-t-md 
        [&>*:last-child]:rounded-b-md 
        [&>*:not(:first-child)]:-mt-px
      `,
    },
    {
      orientation: "vertical",
      shape: "pill",
      class:
        "rounded-full [&>*]:rounded-none [&>*:first-child]:rounded-t-full [&>*:last-child]:rounded-b-full",
    },
  ],
  defaultVariants: {
    orientation: "horizontal",
    size: "md",
    items: 3,
    withIcons: false,
    withDividers: false,
    shape: "default",
    alignment: "center",
  },
});

// Component Logic
const {
  orientation = "horizontal",
  size = "md",
  items = 3,
  withIcons = false,
  withDividers = false,
  shape = "default",
  alignment = "center",
  class: className = "",
} = Astro.props as Props;

const containerClasses = twMerge(
  buttonGroupStyles({
    orientation,
    size,
    items,
    withIcons,
    withDividers,
    shape,
    alignment,
  }),
  className,
);

// PropTypes for documentation
export const propTypes = {
  orientation: {
    type: ["horizontal", "vertical"],
    description: "Orientation of the button group",
    default: "horizontal",
  },
  size: {
    type: ["xs", "sm", "md", "lg", "xl", "2xl"],
    description: "Size of the buttons in the group",
    default: "md",
  },
  items: {
    type: [2, 3, 4, 5, 6],
    description: "Number of items in the button group",
    default: 3,
  },
  withIcons: {
    type: "boolean",
    description: "Whether the buttons contain icons",
    default: false,
  },
  withDividers: {
    type: "boolean",
    description: "Whether to include dividers between buttons",
    default: false,
  },
  shape: {
    type: ["default", "pill", "square"],
    description: "Shape of the button group",
    default: "default",
  },
  alignment: {
    type: ["left", "center", "right"],
    description: "Alignment of content within the buttons",
    default: "center",
  },
  class: {
    type: "string",
    description: "Additional CSS classes to apply to the button group",
  },
};
---

<div class={containerClasses} role="group">
  <slot />
</div>

Component Properties

Property Type Default Description
orientation horizontal | vertical "horizontal" Orientation of the button group
size xs | sm | md | lg | xl | 2xl "md" Size of the buttons in the group
items 2 | 3 | 4 | 5 | 6 3 Number of items in the button group
withIcons boolean false Whether the buttons contain icons
withDividers boolean false Whether to include dividers between buttons
shape default | pill | square "default" Shape of the button group
alignment left | center | right "center" Alignment of content within the buttons
class string - Additional CSS classes to apply to the button group