ButtonGroup 按钮组

把一组按钮拼接为一个整体,共用边框与圆角。

<script setup lang="ts">
  import { AlignCenter, AlignLeft, AlignRight } from '@lucide/vue'
  import { ButtonGroup, IconButton } from '@hina-ui/vue'
</script>

<template>
  <ButtonGroup label="对齐方式">
    <IconButton label="左对齐" variant="outline">
      <AlignLeft />
    </IconButton>
    <IconButton label="居中" variant="outline">
      <AlignCenter />
    </IconButton>
    <IconButton label="右对齐" variant="outline">
      <AlignRight />
    </IconButton>
  </ButtonGroup>
</template>
vue

用法

import { ButtonGroup } from '@hina-ui/vue'
ts

将按钮直接放入组容器即可,拼接由容器负责:首尾保留外侧的圆角,相接的一侧不保留圆角,相邻的边框重叠为一条,而不是并排的两条。

<script setup lang="ts">
  import { Button, ButtonGroup } from '@hina-ui/vue'
</script>

<template>
  <ButtonGroup label="视图">
    <Button variant="outline" tone="neutral">列表</Button>
    <Button variant="outline" tone="neutral">网格</Button>
    <Button variant="outline" tone="neutral">时间线</Button>
  </ButtonGroup>
</template>
vue

组内的按钮应当使用同一种变体与色调。只有地位相同的操作才适合拼在一起,主次不同的操作应当分开放置。

示例

变体

变体与色调由组内的每个按钮各自设置,组容器不会代为指定。

<script setup lang="ts">
  import { Button, ButtonGroup, Stack } from '@hina-ui/vue'
</script>

<template>
  <Stack align="center">
    <ButtonGroup label="填充">
      <Button variant="solid" tone="accent">上一步</Button>
      <Button variant="solid" tone="accent">保存</Button>
      <Button variant="solid" tone="accent">下一步</Button>
    </ButtonGroup>

    <ButtonGroup label="浅色">
      <Button variant="soft" tone="accent">上一步</Button>
      <Button variant="soft" tone="accent">保存</Button>
      <Button variant="soft" tone="accent">下一步</Button>
    </ButtonGroup>

    <ButtonGroup label="描边">
      <Button variant="outline" tone="neutral">上一步</Button>
      <Button variant="outline" tone="neutral">保存</Button>
      <Button variant="outline" tone="neutral">下一步</Button>
    </ButtonGroup>
  </Stack>
</template>
vue

尺寸

尺寸同样设置在按钮上。同一组内必须使用相同的尺寸,否则相邻按钮的高度无法对齐。

<script setup lang="ts">
  import { Button, ButtonGroup, Stack } from '@hina-ui/vue'
</script>

<template>
  <Stack align="center">
    <ButtonGroup label="小号">
      <Button size="sm" variant="outline" tone="neutral">日</Button>
      <Button size="sm" variant="outline" tone="neutral">周</Button>
      <Button size="sm" variant="outline" tone="neutral">月</Button>
    </ButtonGroup>

    <ButtonGroup label="中号">
      <Button variant="outline" tone="neutral">日</Button>
      <Button variant="outline" tone="neutral">周</Button>
      <Button variant="outline" tone="neutral">月</Button>
    </ButtonGroup>

    <ButtonGroup label="大号">
      <Button size="lg" variant="outline" tone="neutral">日</Button>
      <Button size="lg" variant="outline" tone="neutral">周</Button>
      <Button size="lg" variant="outline" tone="neutral">月</Button>
    </ButtonGroup>
  </Stack>
</template>
vue

纵向排列

设置 orientation="vertical" 之后,整组改为纵向拼接,相接的一侧随之转到上下两端,整组的宽度由最宽的一项决定。

<script setup lang="ts">
  import { Copy, Scissors, Trash2 } from '@lucide/vue'
  import { Button, ButtonGroup } from '@hina-ui/vue'
</script>

<template>
  <ButtonGroup label="文件操作" orientation="vertical" divider>
    <Button variant="soft" tone="neutral">
      <template #icon>
        <Copy />
      </template>
      复制
    </Button>
    <Button variant="soft" tone="neutral">
      <template #icon>
        <Scissors />
      </template>
      剪切
    </Button>
    <Button variant="soft" tone="neutral">
      <template #icon>
        <Trash2 />
      </template>
      删除
    </Button>
  </ButtonGroup>
</template>
vue

占满宽度

设置 block 之后整组占满容器的宽度,组内的按钮平分剩余空间。这一形态适用于对话框的底部与移动端界面。

<script setup lang="ts">
  import { Button, ButtonGroup } from '@hina-ui/vue'
</script>

<template>
  <ButtonGroup label="投票" block>
    <Button variant="outline" tone="neutral">赞成</Button>
    <Button variant="outline" tone="neutral">弃权</Button>
    <Button variant="outline" tone="neutral">反对</Button>
  </ButtonGroup>
</template>
vue

分隔线

底色相同的按钮拼在一起时,相邻的边界并不明显。设置 divider 会在按钮之间加一条细线,长度不占满整条边,颜色取自当前的文字颜色。

<script setup lang="ts">
  import { Button, ButtonGroup, Stack } from '@hina-ui/vue'
</script>

<template>
  <Stack align="center">
    <ButtonGroup label="不带分隔线">
      <Button variant="soft" tone="neutral">复制</Button>
      <Button variant="soft" tone="neutral">剪切</Button>
      <Button variant="soft" tone="neutral">粘贴</Button>
    </ButtonGroup>

    <ButtonGroup label="带分隔线" divider>
      <Button variant="soft" tone="neutral">复制</Button>
      <Button variant="soft" tone="neutral">剪切</Button>
      <Button variant="soft" tone="neutral">粘贴</Button>
    </ButtonGroup>
  </Stack>
</template>
vue

混排图标按钮

Button 与 IconButton 可以拼接在同一组中,常见的做法是在主操作之后加入一个下拉触发器。

<script setup lang="ts">
  import { ChevronDown } from '@lucide/vue'
  import { Button, ButtonGroup, IconButton } from '@hina-ui/vue'
</script>

<template>
  <ButtonGroup label="发布">
    <Button>立即发布</Button>
    <IconButton label="更多发布选项" variant="solid" tone="accent">
      <ChevronDown />
    </IconButton>
  </ButtonGroup>
</template>
vue

不可用

组容器没有 disabled 属性。需要禁用整组时,逐个设置按钮的 disabled;也可以只禁用其中的一个。

<script setup lang="ts">
  import { Button, ButtonGroup, Stack } from '@hina-ui/vue'
</script>

<template>
  <Stack align="center">
    <ButtonGroup label="整组不可用">
      <Button variant="outline" tone="neutral" disabled>加粗</Button>
      <Button variant="outline" tone="neutral" disabled>斜体</Button>
      <Button variant="outline" tone="neutral" disabled>下划线</Button>
    </ButtonGroup>

    <ButtonGroup label="单个不可用">
      <Button variant="outline" tone="neutral" disabled>上一页</Button>
      <Button variant="outline" tone="neutral">刷新</Button>
      <Button variant="outline" tone="neutral">下一页</Button>
    </ButtonGroup>
  </Stack>
</template>
vue

自定义样式

class 会追加到组容器上。需要改写首尾的圆角时,在容器上使用子元素选择器统一设置,不要逐个写在按钮上。

<script setup lang="ts">
  import { Button, ButtonGroup } from '@hina-ui/vue'
</script>

<template>
  <ButtonGroup
    label="排序"
    class="[&>*:first-child]:rounded-s-full [&>*:last-child]:rounded-e-full"
  >
    <Button variant="soft" tone="neutral" class="px-6">最新</Button>
    <Button variant="soft" tone="neutral" class="px-6">最热</Button>
    <Button variant="soft" tone="neutral" class="px-6">评分</Button>
  </ButtonGroup>
</template>
vue

行为

  • 组内的按钮不再有按下时的缩放。
  • 获得键盘焦点的按钮会提到上层,焦点框不被相邻按钮遮挡。
  • 组容器为 role="group",label 会作为整组的 aria-label。纵向排列时还会带上 aria-orientation="vertical"。

API

Props

属性
类型
默认值
说明
label
string
—
整组的无障碍名称
orientation
'horizontal' | 'vertical'
'horizontal'
拼接方向
block
boolean
false
是否占满容器宽度并平分空间
divider
boolean
false
是否在相邻按钮之间显示分隔线
class
string
—
追加至根元素的类名

Slots

插槽
说明
default
组内的按钮