# ButtonGroup

Một hàng hoặc cột Button liên quan có tên, nối thành một khối có cạnh chung hoặc cách nhau. Nhóm đặt một size và variant cho các Button của nó.

**Phụ thuộc:** npm: 1 trực tiếp, 4 tổng; registry: 3 trực tiếp, 3 tổng.

## Cách dùng

### Khi nào dùng

- Giữ hai đến năm thao tác liên quan cùng nhau, như Copy, Edit và Delete trong toolbar.
- Một thao tác chính với menu thêm bên cạnh (split button).

### Khi nào không dùng

- Một lựa chọn luôn được chọn, như view hoặc căn chỉnh. Dùng ToggleGroup hoặc Tabs.
- Các thao tác không liên quan, hoặc thao tác chính cạnh Cancel. Đặt các Button cạnh nhau.
- Chuyển giữa các trang kết quả. Dùng Pagination.

## Biến thể

### orientation

Một hàng hoặc một cột Button.

Giá trị: `horizontal`, `vertical`. Mặc định: `horizontal`.

### size

Size của mọi Button trong nhóm, cùng các bước với Button: sm 28px, md 32px, lg 36px (mặc định của nhóm), xl 44px với chuột; trên cảm ứng md là 36px, lg 44px và xl 48px. Button tự đặt size thì giữ size của nó.

Giá trị: `sm`, `md`, `lg`, `xl`. Mặc định: `lg`.

### variant

Variant của mọi Button trong nhóm. Button tự đặt variant thì giữ variant của nó. Nhóm nối liền vẽ một shadow cho variant (shadow-low cho secondary và solid, shadow-med cho các bản glossy) thay vì mỗi Button một shadow. Đặt ButtonGroupSeparator giữa các Button solid nối liền.

Giá trị: `secondary`, `solid`, `soft`, `ghost`, `destructive`, `destructive-soft`, `glossy`, `destructive-glossy`. Mặc định: `secondary`.

## Ví dụ

### Thao tác nối liền

```tsx
<ButtonGroup aria-label="Thao tác tệp">
  <Button>Đổi tên</Button>
  <Button>Nhân bản</Button>
  <Button>Archive</Button>
</ButtonGroup>
```

### Icon và label

Button chỉ có icon mang tên riêng.

```tsx
<ButtonGroup aria-label="Định dạng văn bản">
  <Button iconOnly aria-label="Đậm">
    <IconBold size={16} />
  </Button>
  <Button iconOnly aria-label="In nghiêng">
    <IconItalic size={16} />
  </Button>
  <Button iconOnly aria-label="Gạch chân">
    <IconUnderline size={16} />
  </Button>
</ButtonGroup>
```

### Split button

Một thao tác chính và một menu thêm. Button solid không có viền, nên separator đánh dấu chỗ một Button kết thúc.

```tsx
<ButtonGroup aria-label="Publish" variant="solid">
  <Button leadingIcon={<IconSparkles size={16} />}>Publish</Button>
  <ButtonGroupSeparator />
  <Button iconOnly aria-label="More publish options">
    <IconChevronDown size={16} />
  </Button>
</ButtonGroup>
```

### Cách nhau

```tsx
<ButtonGroup aria-label="Pages" attached={false}>
  <Button leadingIcon={<IconArrowLeft size={16} />}>Previous</Button>
  <Button trailingIcon={<IconArrowRight size={16} />}>Next</Button>
</ButtonGroup>
```

### Chiều dọc

```tsx
<ButtonGroup aria-label="Zoom" orientation="vertical">
  <Button iconOnly aria-label="Zoom in">
    <IconPlus size={16} />
  </Button>
  <Button iconOnly aria-label="Zoom out">
    <IconMinus size={16} />
  </Button>
</ButtonGroup>
```

### Toàn chiều rộng

```tsx
<ButtonGroup aria-label="Chia sẻ" fullWidth>
  <Button leadingIcon={<IconLink size={16} />}>Share link</Button>
  <Button leadingIcon={<IconMail size={16} />}>Email</Button>
  <Button leadingIcon={<IconDownload size={16} />}>Download</Button>
</ButtonGroup>
```

## Nên và không nên

### Nên

- Gom hai đến năm thao tác liên quan chặt, như Rename, Duplicate và Archive, hoặc một thao tác chính và một menu thêm.
- Đặt tên nhóm bằng aria-label hoặc một tiêu đề hiển thị qua aria-labelledby.
- Dùng một variant cho cả nhóm. Dùng ButtonGroupSeparator giữa các Button solid nối liền.

### Không nên

- Đừng gom các thao tác không liên quan hoặc một thao tác chính với Cancel. Đặt các Button đó cạnh nhau.
- Đừng dùng nhóm cho một lựa chọn luôn được chọn; dùng ToggleGroup hoặc Tabs.
- Đừng đặt Button link trong nhóm.

## Props

| Tên | Kiểu | Giá trị | Mặc định | Mô tả |
| --- | --- | --- | --- | --- |
| `orientation` | `enum` | `horizontal`, `vertical` | `horizontal` | Một hàng hoặc một cột Button. |
| `attached` | `boolean` |  | `true` | Nối các Button thành một khối có cạnh chung. false thì cách chúng ra bằng khoảng spacing-sm. |
| `size` | `enum` | `sm`, `md`, `lg`, `xl` | `lg` | Size của mọi Button trong nhóm, cùng các bước với Button: sm 28px, md 32px, lg 36px (mặc định của nhóm), xl 44px với chuột; trên cảm ứng md là 36px, lg 44px và xl 48px. Button tự đặt size thì giữ size của nó. |
| `variant` | `enum` | `secondary`, `solid`, `soft`, `ghost`, `destructive`, `destructive-soft`, `glossy`, `destructive-glossy` | `secondary` | Variant của mọi Button trong nhóm. Button tự đặt variant thì giữ variant của nó. Nhóm nối liền vẽ một shadow cho variant (shadow-low cho secondary và solid, shadow-med cho các bản glossy) thay vì mỗi Button một shadow. Đặt ButtonGroupSeparator giữa các Button solid nối liền. |
| `fullWidth` | `boolean` |  | `false` | Lấp đầy chiều rộng của container. Trong một hàng, các Button chia đều chiều rộng. |

### Slot

| Tên | Bắt buộc | Mô tả |
| --- | --- | --- |
| `children` | có | Các Button, và ButtonGroupSeparator giữa các Button solid nối liền. Chỉ Button con trực tiếp mới nhận size và variant của nhóm. |

## Cấu tạo

| Phần | Mô tả |
| --- | --- |
| `root` | Nhóm có tên. Nhóm không vẽ fill: các Button giữ fill, viền và motion của chúng. Khi nối liền, các Button bỏ shadow riêng và nhóm vẽ một shadow (theo bước của variant) quanh cả khối. |
| `item` | Một Button trong nhóm. Khi nối liền, chỉ các góc ngoài còn bo tròn và viền giữa hai Button gộp thành một đường. |
| `separator` | Đường 1px tùy chọn giữa hai Button solid, vốn không có viền để thấy chỗ một Button kết thúc. |

## Khả năng truy cập

Role: `group`

| Phím | Hành động |
| --- | --- |
| `Tab, Shift+Tab` | Đi qua từng Button. Mỗi Button giữ điểm dừng tab riêng. |
| `Space, Enter` | Nhấn Button đang focus. |

- Nhóm cần aria-label hoặc aria-labelledby, để trình đọc màn hình đọc các Button thuộc về gì.
- Mỗi Button giữ tên riêng. Button chỉ có icon cần aria-label.
- Button đang focus nổi lên trên các Button bên cạnh, nên focus ring không bao giờ bị Button kế tiếp che.
- ButtonGroupSeparator chỉ để trang trí và bị ẩn với trình đọc màn hình.
- Với một lựa chọn luôn được chọn, dùng ToggleGroup hoặc Tabs: Button trong nhóm không có trạng thái pressed.

## Cài đặt

```bash
npx werewolf-ui add button-group
```

Chạy `npx werewolf-ui init` một lần trong app trước khi thêm component. Init cài token, thêm CSS import và luật cho agent. Add cài component này cùng các dependency và giữ nguyên theme của bạn. Xem [Cài đặt](https://www.werewolf-ui.dev/vi/docs/installation.md) để biết yêu cầu và cách cài qua registry.
