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ó.
Xem trước
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
<ButtonGroup aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>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.
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
<ButtonGroup aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup orientation="vertical" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>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ó.
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
<ButtonGroup size="sm" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup size="md" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup size="xl" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>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.
import { Button } from "@/components/ui/button"
import { ButtonGroup, ButtonGroupSeparator } from "@/components/ui/button-group"
<ButtonGroup aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup variant="solid" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<ButtonGroupSeparator />
<Button>Sửa</Button>
<ButtonGroupSeparator />
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup variant="soft" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup variant="ghost" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup variant="destructive" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<ButtonGroupSeparator />
<Button>Sửa</Button>
<ButtonGroupSeparator />
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup variant="destructive-soft" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<Button>Sửa</Button>
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup variant="glossy" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<ButtonGroupSeparator />
<Button>Sửa</Button>
<ButtonGroupSeparator />
<Button>Xóa</Button>
</ButtonGroup>
<ButtonGroup variant="destructive-glossy" aria-label="Thao tác với tệp">
<Button>Nhân bản</Button>
<ButtonGroupSeparator />
<Button>Sửa</Button>
<ButtonGroupSeparator />
<Button>Xóa</Button>
</ButtonGroup>Ví dụ
Thao tác nối liền
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
<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.
import { IconBold, IconItalic, IconUnderline } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
<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.
import { IconChevronDown, IconSparkles } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup, ButtonGroupSeparator } from "@/components/ui/button-group"
<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
import { IconArrowLeft, IconArrowRight } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
<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
import { IconMinus, IconPlus } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
<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
import { IconDownload, IconLink, IconMail } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
<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
npx werewolf-ui add button-groupChạ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 để biết yêu cầu và cách cài qua registry.