# ButtonGroup

> Buttons joined into one control with shared borders and only the outer corners rounded, horizontal or vertical, with a separator slot for split buttons.

Source: https://docs.nasaqui.com/components/button-group

## Install

```bash
npx shadcn@latest add https://docs.nasaqui.com/r/button-group.json
```

Fuses several `Button`s into one control. Borders overlap so they read as one edge, and only the outer corners are
rounded, using logical radii (inline start of the first, inline end of the last), so RTL is right without overrides.

## When to use

- Related actions side by side (Day / Week / Month) or a split button (action plus menu).

## When not to use

- Options with a pressed state: use `ToggleGroup`.
- Unrelated actions: keep them apart with normal spacing.

## Import

```tsx
import { Button, ButtonGroup } from "@fadymondy/nasaq/web";
```

## Quick start

```tsx
import { Button, ButtonGroup } from "@fadymondy/nasaq/web";

export function Period() {
  return (
    <ButtonGroup aria-label="Period">
      <Button>Day</Button>
      <Button>Week</Button>
      <Button>Month</Button>
    </ButtonGroup>
  );
}
```

## Anatomy

```
<ButtonGroup>              data-slot="button-group"  data-orientation, role="group"
├─ <Button>                data-slot="button"
├─ <ButtonGroupSeparator>  data-slot="button-group-separator"
└─ <Button> / DropdownMenuTrigger render={<Button />}
```

## API

### ButtonGroup (`ButtonGroupProps`)

All `div` props, plus:

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Row or column. |

### ButtonGroupSeparator

A `div` with `role="separator"`. Use it between borderless buttons such as two `primary` ones.

## Examples

Split button with a menu:

```tsx
import {
  Button,
  ButtonGroup,
  ButtonGroupSeparator,
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
  Icon,
} from "@fadymondy/nasaq/web";
import { ChevronDown } from "lucide-react";

export function SplitPublish() {
  return (
    <ButtonGroup aria-label="Publish">
      <Button variant="primary">Publish</Button>
      <ButtonGroupSeparator />
      <DropdownMenu>
        <DropdownMenuTrigger render={<Button variant="primary" size="icon" aria-label="More publish options" />}>
          <Icon icon={ChevronDown} />
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end">
          <DropdownMenuItem>Schedule publish</DropdownMenuItem>
          <DropdownMenuItem>Save as draft</DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>
    </ButtonGroup>
  );
}
```

Vertical, in Arabic:

```tsx
import { Button, ButtonGroup } from "@fadymondy/nasaq/web";

export function ActionsAr() {
  return (
    <ButtonGroup orientation="vertical" aria-label="الإجراءات">
      <Button>تعديل</Button>
      <Button>نسخ</Button>
    </ButtonGroup>
  );
}
```

## Accessibility

| Key | Action |
| --- | --- |
| Tab | Moves through each button in order. |
| Enter / Space | Activates the focused button. |

- The wrapper is `role="group"`. Give it an `aria-label` and localise it. Icon-only buttons need their own `aria-label`.

## RTL & i18n

Buttons follow reading order. Rounding uses `rounded-s-control` / `rounded-e-control` (vertical uses top and bottom), so the
first button sits at the right in Arabic with its right corners round.

## Styling & tokens

Radius token `--radius-control`; borders from each button's variant. Children are styled by `data-slot="button"`, so
children must be `Button`s (or triggers rendered as one). `className` merges onto the group.

## Do / Don't

- Do keep to two to five buttons.
- Don't mix sizes inside one group.

## Related

[button](https://docs.nasaqui.com/components/button), [toggle-group](https://docs.nasaqui.com/components/toggle-group), [dropdown-menu](https://docs.nasaqui.com/components/dropdown-menu).

## Lab

https://docs.nasaqui.com/?path=/docs/components-actions-button-group--docs

## Code

### React

```tsx
import { Button, ButtonGroup } from "@fadymondy/nasaq/web";

export function Period() {
  return (
    <ButtonGroup aria-label="Period">
      <Button>Day</Button>
      <Button>Week</Button>
      <Button>Month</Button>
    </ButtonGroup>
  );
}
```

### shadcn

```tsx
import { Button } from "@/components/ui/button";
import { ButtonGroup } from "@/components/ui/button-group";

export function Period() {
  return (
    <ButtonGroup aria-label="Period">
      <Button>Day</Button>
      <Button>Week</Button>
      <Button>Month</Button>
    </ButtonGroup>
  );
}
```

### Vue

```vue
<script setup lang="ts">
import { NqButton, NqButtonGroup } from "@fadymondy/nasaq/vue";
</script>

<template>
  <NqButtonGroup aria-label="Period">
    <NqButton>Day</NqButton>
    <NqButton>Week</NqButton>
    <NqButton>Month</NqButton>
  </NqButtonGroup>
</template>
```

### Blade

```blade
<x-nq::button-group aria-label="Period">
    <x-nq::button>Day</x-nq::button>
    <x-nq::button>Week</x-nq::button>
    <x-nq::button>Month</x-nq::button>
</x-nq::button-group>
```

### HTML + Alpine

```html
<div role="group" data-slot="button-group" data-orientation="horizontal" aria-label="Period" class="flex w-fit max-w-full [&>[data-slot=button]]:relative [&>[data-slot=button]]:rounded-none [&>[data-slot=button]]:focus-visible:z-10 [&>[data-slot=button]]:hover:z-1 [&>[data-slot=button]]:first-child:rounded-s-control [&>[data-slot=button]]:last-child:rounded-e-control [&>[data-slot=button]]+[&>[data-slot=button]]:-ms-px">
    <button data-slot="button"
     type="button"                         class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Day</button>
    <button data-slot="button"
     type="button"                         class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Week</button>
    <button data-slot="button"
     type="button"                         class="inline-flex shrink-0 select-none items-center justify-center gap-2 whitespace-nowrap rounded-control border font-sans text-label transition-colors duration-150 ease-nq min-h-[var(--nq-touch-min,0px)] outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-nq-focus disabled:pointer-events-none disabled:opacity-50 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border-border bg-card text-foreground hover:bg-nq-hover h-control px-[var(--nq-control-pad)]">
        Month</button>
</div>
```
