开发预览 更新于 2026-05-10

IconButton 图标按钮

仅图标的方形按钮,必须配 aria-label;常用于 toolbar、表头列操作、输入后缀。

基础用法

3 个 variant(default / primary / danger),3 档尺寸(sm / md / lg),形状 square / round

pressed 用于 toggle 行为(pin / bookmark),自动设 aria-pressed

背景 视口
src/App.vue
<script setup lang="ts">
import { CfIconButton } from '@chufix-design/vue';
</script>
<template>
  <div class="demo-row">
    <CfIconButton aria-label="刷新">
      <svg viewBox="0 0 16 16" fill="none"><path d="M3 8a5 5 0 1 1 1.5 3.5M3 8V5m0 3h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
    </CfIconButton>
    <CfIconButton variant="primary" aria-label="保存">
      <svg viewBox="0 0 16 16" fill="none"><path d="M3 8.5l3.2 3.2L13 5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
    </CfIconButton>
    <CfIconButton variant="danger" aria-label="删除">
      <svg viewBox="0 0 16 16" fill="none"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
    </CfIconButton>
    <CfIconButton :pressed="true" aria-label="固定">
      <svg viewBox="0 0 16 16" fill="none"><path d="M8 2v8m0 4v.01M5 5h6" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
    </CfIconButton>
  </div>
</template>
<script setup>
import { CfIconButton } from '@chufix-design/vue';
</script>
<template>
  <div class="demo-row">
    <CfIconButton aria-label="刷新">
      <svg viewBox="0 0 16 16" fill="none"><path d="M3 8a5 5 0 1 1 1.5 3.5M3 8V5m0 3h3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
    </CfIconButton>
    <CfIconButton variant="primary" aria-label="保存">
      <svg viewBox="0 0 16 16" fill="none"><path d="M3 8.5l3.2 3.2L13 5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
    </CfIconButton>
    <CfIconButton variant="danger" aria-label="删除">
      <svg viewBox="0 0 16 16" fill="none"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
    </CfIconButton>
    <CfIconButton :pressed="true" aria-label="固定">
      <svg viewBox="0 0 16 16" fill="none"><path d="M8 2v8m0 4v.01M5 5h6" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
    </CfIconButton>
  </div>
</template>
import { CfIconButton } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfIconButton aria-label="保存" variant="primary"><Icon /></CfIconButton>
      <CfIconButton aria-label="删除" variant="danger"><Icon /></CfIconButton>
      <CfIconButton aria-label="固定" pressed><Icon /></CfIconButton>
    </>
  );
}
import { CfIconButton } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfIconButton aria-label="保存" variant="primary"><Icon /></CfIconButton>
      <CfIconButton aria-label="删除" variant="danger"><Icon /></CfIconButton>
      <CfIconButton aria-label="固定" pressed><Icon /></CfIconButton>
    </>
  );
}

尺寸与形状

3 档尺寸(sm 26 / md 32 / lg 38 px)。shape="round" 切到圆形(pill)。

背景 视口
src/App.vue
<script setup lang="ts">
import { CfIconButton } from '@chufix-design/vue';
const star = `<svg viewBox="0 0 16 16" fill="none"><path d="M8 2l1.9 4 4.4.4-3.3 3 .9 4.3L8 11.5 4.1 13.7l.9-4.3-3.3-3 4.4-.4z" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/></svg>`;
</script>
<template>
  <div class="demo-row" style="align-items: center; gap: 16px;">
    <CfIconButton size="sm" aria-label="星标 (sm)"><span v-html="star" style="display: contents;"/></CfIconButton>
    <CfIconButton size="md" aria-label="星标 (md)"><span v-html="star" style="display: contents;"/></CfIconButton>
    <CfIconButton size="lg" aria-label="星标 (lg)"><span v-html="star" style="display: contents;"/></CfIconButton>
    <span style="width: 1px; height: 24px; background: var(--line-1); margin: 0 8px;" />
    <CfIconButton size="md" shape="round" aria-label="圆形"><span v-html="star" style="display: contents;"/></CfIconButton>
    <CfIconButton size="lg" shape="round" aria-label="圆形 lg"><span v-html="star" style="display: contents;"/></CfIconButton>
  </div>
</template>
<script setup>
import { CfIconButton } from '@chufix-design/vue';
const star = `<svg viewBox="0 0 16 16" fill="none"><path d="M8 2l1.9 4 4.4.4-3.3 3 .9 4.3L8 11.5 4.1 13.7l.9-4.3-3.3-3 4.4-.4z" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/></svg>`;
</script>
<template>
  <div class="demo-row" style="align-items: center; gap: 16px;">
    <CfIconButton size="sm" aria-label="星标 (sm)"><span v-html="star" style="display: contents;"/></CfIconButton>
    <CfIconButton size="md" aria-label="星标 (md)"><span v-html="star" style="display: contents;"/></CfIconButton>
    <CfIconButton size="lg" aria-label="星标 (lg)"><span v-html="star" style="display: contents;"/></CfIconButton>
    <span style="width: 1px; height: 24px; background: var(--line-1); margin: 0 8px;" />
    <CfIconButton size="md" shape="round" aria-label="圆形"><span v-html="star" style="display: contents;"/></CfIconButton>
    <CfIconButton size="lg" shape="round" aria-label="圆形 lg"><span v-html="star" style="display: contents;"/></CfIconButton>
  </div>
</template>
import { CfIconButton } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfIconButton size="sm" aria-label="星标" />
      <CfIconButton size="md" aria-label="星标" />
      <CfIconButton size="lg" aria-label="星标" />
      <CfIconButton shape="round" aria-label="圆形" />
    </>
  );
}
import { CfIconButton } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfIconButton size="sm" aria-label="星标" />
      <CfIconButton size="md" aria-label="星标" />
      <CfIconButton size="lg" aria-label="星标" />
      <CfIconButton shape="round" aria-label="圆形" />
    </>
  );
}

状态

pressed 切换 toggle 状态(自动设 aria-pressed),loadingdisabled 分别给出 spinner 与禁用样式。

背景 视口
已固定
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfIconButton } from '@chufix-design/vue';
const pinned = ref(true);
const liked = ref(false);
const star = `<svg viewBox="0 0 16 16" fill="none"><path d="M8 2l1.9 4 4.4.4-3.3 3 .9 4.3L8 11.5 4.1 13.7l.9-4.3-3.3-3 4.4-.4z" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/></svg>`;
</script>
<template>
  <div class="demo-row" style="align-items: center; gap: 16px;">
    <CfIconButton :pressed="pinned" aria-label="固定" @click="pinned = !pinned">
      <span v-html="star" style="display: contents;"/>
    </CfIconButton>
    <CfIconButton :pressed="liked" variant="danger" aria-label="收藏" @click="liked = !liked">
      <span v-html="star" style="display: contents;"/>
    </CfIconButton>
    <CfIconButton loading aria-label="加载中">
      <span v-html="star" style="display: contents;"/>
    </CfIconButton>
    <CfIconButton disabled aria-label="禁用">
      <span v-html="star" style="display: contents;"/>
    </CfIconButton>
    <span v-if="pinned" style="font-size: 12px; color: var(--accent-1); font-family: var(--font-mono);">已固定</span>
    <span v-if="liked" style="font-size: 12px; color: var(--status-error); font-family: var(--font-mono);">已收藏</span>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfIconButton } from '@chufix-design/vue';
const pinned = ref(true);
const liked = ref(false);
const star = `<svg viewBox="0 0 16 16" fill="none"><path d="M8 2l1.9 4 4.4.4-3.3 3 .9 4.3L8 11.5 4.1 13.7l.9-4.3-3.3-3 4.4-.4z" stroke="currentColor" stroke-width="1.4" stroke-linejoin="round"/></svg>`;
</script>
<template>
  <div class="demo-row" style="align-items: center; gap: 16px;">
    <CfIconButton :pressed="pinned" aria-label="固定" @click="pinned = !pinned">
      <span v-html="star" style="display: contents;"/>
    </CfIconButton>
    <CfIconButton :pressed="liked" variant="danger" aria-label="收藏" @click="liked = !liked">
      <span v-html="star" style="display: contents;"/>
    </CfIconButton>
    <CfIconButton loading aria-label="加载中">
      <span v-html="star" style="display: contents;"/>
    </CfIconButton>
    <CfIconButton disabled aria-label="禁用">
      <span v-html="star" style="display: contents;"/>
    </CfIconButton>
    <span v-if="pinned" style="font-size: 12px; color: var(--accent-1); font-family: var(--font-mono);">已固定</span>
    <span v-if="liked" style="font-size: 12px; color: var(--status-error); font-family: var(--font-mono);">已收藏</span>
  </div>
</template>
import { CfIconButton } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfIconButton pressed aria-label="固定" />
      <CfIconButton variant="danger" pressed aria-label="收藏" />
      <CfIconButton loading aria-label="加载中" />
      <CfIconButton disabled aria-label="禁用" />
    </>
  );
}
import { CfIconButton } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfIconButton pressed aria-label="固定" />
      <CfIconButton variant="danger" pressed aria-label="收藏" />
      <CfIconButton loading aria-label="加载中" />
      <CfIconButton disabled aria-label="禁用" />
    </>
  );
}

Toolbar 组合

pressed@click 配合可以组装出格式化工具栏:粗体 / 斜体 / 下划线分别独立 toggle, 对齐方式互斥但展示用同一组按钮。同一行内用 1–2px 间距,必要时插入 <span> 分隔线分组。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfIconButton, CfIcon } from '@chufix-design/vue';

const bold = ref<boolean>(false);
const italic = ref<boolean>(false);
const underline = ref<boolean>(false);
</script>
<template>
  <div class="adm-toolbar">
    <CfIconButton :pressed="bold"      aria-label="粗体"  @click="bold = !bold">
      <CfIcon name="bold" />
    </CfIconButton>
    <CfIconButton :pressed="italic"    aria-label="斜体"  @click="italic = !italic">
      <CfIcon name="italic" />
    </CfIconButton>
    <CfIconButton :pressed="underline" aria-label="下划线" @click="underline = !underline">
      <CfIcon name="underline" />
    </CfIconButton>
    <span class="adm-toolbar__sep" aria-hidden="true" />
    <CfIconButton aria-label="对齐:左">
      <CfIcon name="align-left" />
    </CfIconButton>
    <CfIconButton aria-label="对齐:居中">
      <CfIcon name="align-center" />
    </CfIconButton>
    <CfIconButton aria-label="对齐:右">
      <CfIcon name="align-right" />
    </CfIconButton>
  </div>
</template>
<style scoped>
.adm-toolbar {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-6);
}
.adm-toolbar__sep {
  width: 1px;
  height: 18px;
  background: var(--line-1);
  margin: 0 4px;
}
</style>
<script setup>
import { ref } from 'vue';
import { CfIconButton, CfIcon } from '@chufix-design/vue';

const bold = ref<boolean>(false);
const italic = ref<boolean>(false);
const underline = ref<boolean>(false);
</script>
<template>
  <div class="adm-toolbar">
    <CfIconButton :pressed="bold"      aria-label="粗体"  @click="bold = !bold">
      <CfIcon name="bold" />
    </CfIconButton>
    <CfIconButton :pressed="italic"    aria-label="斜体"  @click="italic = !italic">
      <CfIcon name="italic" />
    </CfIconButton>
    <CfIconButton :pressed="underline" aria-label="下划线" @click="underline = !underline">
      <CfIcon name="underline" />
    </CfIconButton>
    <span class="adm-toolbar__sep" aria-hidden="true" />
    <CfIconButton aria-label="对齐:左">
      <CfIcon name="align-left" />
    </CfIconButton>
    <CfIconButton aria-label="对齐:居中">
      <CfIcon name="align-center" />
    </CfIconButton>
    <CfIconButton aria-label="对齐:右">
      <CfIcon name="align-right" />
    </CfIconButton>
  </div>
</template>
<style scoped>
.adm-toolbar {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 4px;
  background: var(--bg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-6);
}
.adm-toolbar__sep {
  width: 1px;
  height: 18px;
  background: var(--line-1);
  margin: 0 4px;
}
</style>
import { useState } from 'react';
import { CfIconButton, CfIcon } from '@chufix-design/react';

export default function Demo() {
const [bold, setBold] = useState(false);
const [italic, setItalic] = useState(false);
return (
  <div style={{ display: 'inline-flex', gap: 2 }}>
    <CfIconButton pressed={bold} aria-label="粗体" onClick={() => setBold(!bold)}>
      <CfIcon name="bold" />
    </CfIconButton>
    <CfIconButton pressed={italic} aria-label="斜体" onClick={() => setItalic(!italic)}>
      <CfIcon name="italic" />
    </CfIconButton>
  </div>
);
}
import { useState } from 'react';
import { CfIconButton, CfIcon } from '@chufix-design/react';

export default function Demo() {
const [bold, setBold] = useState(false);
const [italic, setItalic] = useState(false);
return (
  <div style={{ display: 'inline-flex', gap: 2 }}>
    <CfIconButton pressed={bold} aria-label="粗体" onClick={() => setBold(!bold)}>
      <CfIcon name="bold" />
    </CfIconButton>
    <CfIconButton pressed={italic} aria-label="斜体" onClick={() => setItalic(!italic)}>
      <CfIcon name="italic" />
    </CfIconButton>
  </div>
);
}

徽章

badge 具名插槽渲染右上角徽章,用于通知数量、未读标记等场景。短文案(“3”、“99+“)效果最好, 单点(”•“)适合纯”有新内容”提示。徽章自动定位、无需手写样式。

背景 视口
src/App.vue
<script setup lang="ts">
import { CfIconButton, CfIcon } from '@chufix-design/vue';
</script>
<template>
  <div class="demo-row">
    <CfIconButton aria-label="通知(3 条未读)">
      <CfIcon name="bell" />
      <template #badge>3</template>
    </CfIconButton>
    <CfIconButton aria-label="邮件(99+ 封未读)">
      <CfIcon name="mail" />
      <template #badge>99+</template>
    </CfIconButton>
    <CfIconButton aria-label="收件箱(有新内容)">
      <CfIcon name="inbox" />
      <template #badge>•</template>
    </CfIconButton>
  </div>
</template>
<script setup>
import { CfIconButton, CfIcon } from '@chufix-design/vue';
</script>
<template>
  <div class="demo-row">
    <CfIconButton aria-label="通知(3 条未读)">
      <CfIcon name="bell" />
      <template #badge>3</template>
    </CfIconButton>
    <CfIconButton aria-label="邮件(99+ 封未读)">
      <CfIcon name="mail" />
      <template #badge>99+</template>
    </CfIconButton>
    <CfIconButton aria-label="收件箱(有新内容)">
      <CfIcon name="inbox" />
      <template #badge>•</template>
    </CfIconButton>
  </div>
</template>
import { CfIcon, CfIconButton } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfIconButton aria-label="通知(3 条未读)" badge="3">
      <CfIcon name="bell" />
      </CfIconButton>
      <CfIconButton aria-label="邮件(99+ 封未读)" badge="99+">
      <CfIcon name="mail" />
      </CfIconButton>
      <CfIconButton aria-label="收件箱(有新内容)" badge="•">
      <CfIcon name="inbox" />
      </CfIconButton>
    </>
  );
}
import { CfIcon, CfIconButton } from '@chufix-design/react';

export default function Demo() {
  return (
    <>
      <CfIconButton aria-label="通知(3 条未读)" badge="3">
      <CfIcon name="bell" />
      </CfIconButton>
      <CfIconButton aria-label="邮件(99+ 封未读)" badge="99+">
      <CfIcon name="mail" />
      </CfIconButton>
      <CfIconButton aria-label="收件箱(有新内容)" badge="•">
      <CfIcon name="inbox" />
      </CfIconButton>
    </>
  );
}

API

Props

Prop类型默认值说明
variant'default' | 'primary' | 'danger''default'视觉变体
size'sm' | 'md' | 'lg''md'尺寸
shape'square' | 'round''square'形状
pressedbooleanfalsetoggle 状态,输出 aria-pressed
loadingbooleanfalse显示 spinner,自动屏蔽点击
disabledbooleanfalse禁用
type'button' | 'submit' | 'reset''button'原生 button type,用于 Form 提交场景

Events

Event载荷类型说明
clickMouseEvent点击触发;disabledloading 时不触发

Slots / Children

SlotProps说明
default图标内容;React 端等价为 children
badge右上角徽章;React 端等价为 badge prop

a11y:必须传 aria-label,否则屏幕阅读器无法识别按钮含义。

反馈与讨论

IconButton 图标按钮 的讨论

0
0 / 600
正在加载评论...