Icon Button
Icon button component with tooltip support, multiple variants, colors, and sizes
Icon Button
带 Tooltip 功能的图标按钮组件,支持多种变体、颜色、尺寸和加载状态。
基础用法
不带 tooltip 的图标按钮:
带 Tooltip 的图标按钮
悬停查看 tooltip 提示:
变体展示
Solid (实心)
Light (浅色 - 有边框)
Light (浅色 - 无边框)
Outline (边框)
Ghost (幽灵)
尺寸展示
Tooltip 位置
加载状态
禁用状态
实际应用场景
工具栏按钮组(Ghost 变体)
工具栏按钮组(Light 变体)
卡片操作按钮
"use client";
import * as React from "react";
import { IconButton } from "@/components/composed/icon-button/icon-button";
import {
Plus,
Minus,
Trash2,
Edit2,
Settings,
Copy,
Check,
MoreHorizontal,
MoreVertical,
X,
ChevronLeft,
ChevronRight,
ChevronUp,
ChevronDown,
Search,
RefreshCw,
Download,
Upload,
FolderPlus,
FilePlus,
} from "lucide-react";
// ==================== 演示组件 ====================
export function IconButtonDemo() {
// 状态管理
const [loadingStates, setLoadingStates] = React.useState<
Record<string, boolean>
>({});
const [copied, setCopied] = React.useState<string | null>(null);
// 模拟加载状态切换
const toggleLoading = (id: string) => {
setLoadingStates((prev) => ({ ...prev, [id]: !prev[id] }));
};
// 模拟复制功能
const handleCopy = (text: string, id: string) => {
navigator.clipboard.writeText(text);
setCopied(id);
setTimeout(() => setCopied(null), 2000);
};
return (
<div className="w-full max-w-[900px] mx-auto p-6 space-y-8">
{/* 标题区域 */}
<div className="space-y-2">
<h1 className="text-2xl font-semibold text-[var(--Text-text-primary)]">
Icon Button
</h1>
<p className="text-sm text-[var(--Text-text-secondary)]">
带 Tooltip 功能的图标按钮组件,支持多种变体、颜色、尺寸和加载状态。
</p>
</div>
{/* 基础用法 */}
<section className="space-y-4">
<h2 className="text-lg font-medium text-[var(--Text-text-primary)]">
基础用法
</h2>
<div className="p-6 bg-[var(--Container-bg-container)] rounded-[var(--radius-lg)] border border-[var(--Border-border-neutral)] space-y-4">
<p className="text-sm text-[var(--Text-text-secondary)] mb-4">
不带 tooltip 的图标按钮:
</p>
<div className="flex flex-wrap gap-3">
<IconButton variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton variant="solid" color="primary">
<Minus className="size-4" />
</IconButton>
<IconButton variant="light" color="primary">
<Settings className="size-4" />
</IconButton>
<IconButton variant="outline" color="secondary">
<Download className="size-4" />
</IconButton>
<IconButton variant="ghost" color="primary">
<MoreHorizontal className="size-4" />
</IconButton>
</div>
</div>
</section>
{/* 带 Tooltip 的图标按钮 */}
<section className="space-y-4">
<h2 className="text-lg font-medium text-[var(--Text-text-primary)]">
带 Tooltip 的图标按钮
</h2>
<div className="p-6 bg-[var(--Container-bg-container)] rounded-[var(--radius-lg)] border border-[var(--Border-border-neutral)] space-y-4">
<p className="text-sm text-[var(--Text-text-secondary)] mb-4">
悬停查看 tooltip 提示:
</p>
<div className="flex flex-wrap gap-3">
<IconButton tooltip="添加新内容" variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton tooltip="删除" variant="outline" color="danger">
<Trash2 className="size-4" />
</IconButton>
<IconButton tooltip="编辑" variant="ghost" color="primary">
<Edit2 className="size-4" />
</IconButton>
<IconButton tooltip="复制" variant="outline" color="secondary">
{copied === "copy" ? (
<Check className="size-4 text-[var(--Text-text-success)]" />
) : (
<Copy
className="size-4"
onClick={() => handleCopy("copy", "copy")}
/>
)}
</IconButton>
<IconButton tooltip="刷新" variant="solid" color="secondary">
<RefreshCw className="size-4" />
</IconButton>
<IconButton tooltip="设置" variant="light" color="primary">
<Settings className="size-4" />
</IconButton>
</div>
</div>
</section>
{/* 变体展示 */}
<section className="space-y-4">
<h2 className="text-lg font-medium text-[var(--Text-text-primary)]">
变体展示
</h2>
<div className="p-6 bg-[var(--Container-bg-container)] rounded-[var(--radius-lg)] border border-[var(--Border-border-neutral)] space-y-6">
{/* Solid 变体 */}
<div className="space-y-3">
<h3 className="text-sm font-medium text-[var(--Text-text-secondary)]">
Solid (实心)
</h3>
<div className="flex flex-wrap gap-3">
<IconButton tooltip="主色" variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton tooltip="次要色" variant="solid" color="secondary">
<Settings className="size-4" />
</IconButton>
<IconButton tooltip="危险色" variant="solid" color="danger">
<Trash2 className="size-4" />
</IconButton>
</div>
</div>
{/* Light 变体 */}
<div className="space-y-3">
<h3 className="text-sm font-medium text-[var(--Text-text-secondary)]">
Light (浅色 - 有边框)
</h3>
<div className="flex flex-wrap gap-3">
<IconButton tooltip="主色" variant="light" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton tooltip="次要色" variant="light" color="secondary">
<Settings className="size-4" />
</IconButton>
<IconButton tooltip="危险色" variant="light" color="danger">
<Trash2 className="size-4" />
</IconButton>
</div>
</div>
{/* Light 无边框变体 */}
<div className="space-y-3">
<h3 className="text-sm font-medium text-[var(--Text-text-secondary)]">
Light (浅色 - 无边框)
</h3>
<div className="flex flex-wrap gap-3">
<IconButton
tooltip="主色"
variant="light"
color="primary"
borderless
>
<Plus className="size-4" />
</IconButton>
<IconButton
tooltip="次要色"
variant="light"
color="secondary"
borderless
>
<Settings className="size-4" />
</IconButton>
<IconButton
tooltip="危险色"
variant="light"
color="danger"
borderless
>
<Trash2 className="size-4" />
</IconButton>
</div>
</div>
{/* Outline 变体 */}
<div className="space-y-3">
<h3 className="text-sm font-medium text-[var(--Text-text-secondary)]">
Outline (边框)
</h3>
<div className="flex flex-wrap gap-3">
<IconButton tooltip="主色" variant="outline" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton tooltip="次要色" variant="outline" color="secondary">
<Settings className="size-4" />
</IconButton>
<IconButton tooltip="危险色" variant="outline" color="danger">
<Trash2 className="size-4" />
</IconButton>
</div>
</div>
{/* Ghost 变体 */}
<div className="space-y-3">
<h3 className="text-sm font-medium text-[var(--Text-text-secondary)]">
Ghost (幽灵)
</h3>
<div className="flex flex-wrap gap-3">
<IconButton tooltip="主色" variant="ghost" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton tooltip="次要色" variant="ghost" color="secondary">
<Settings className="size-4" />
</IconButton>
<IconButton tooltip="危险色" variant="ghost" color="danger">
<Trash2 className="size-4" />
</IconButton>
</div>
</div>
</div>
</section>
{/* 尺寸展示 */}
<section className="space-y-4">
<h2 className="text-lg font-medium text-[var(--Text-text-primary)]">
尺寸展示
</h2>
<div className="p-6 bg-[var(--Container-bg-container)] rounded-[var(--radius-lg)] border border-[var(--Border-border-neutral)] space-y-4">
<div className="flex flex-wrap items-center gap-4">
<IconButton
tooltip="超小 (24px)"
size="sm"
variant="solid"
color="primary"
>
<Plus className="size-3.5" />
</IconButton>
<IconButton
tooltip="小 (32px)"
size="md"
variant="solid"
color="primary"
>
<Plus className="size-4" />
</IconButton>
<IconButton
tooltip="中 (36px)"
size="lg"
variant="solid"
color="primary"
>
<Plus className="size-4.5" />
</IconButton>
<IconButton
tooltip="大 (40px)"
size="xl"
variant="solid"
color="primary"
>
<Plus className="size-5" />
</IconButton>
</div>
</div>
</section>
{/* Tooltip 位置 */}
<section className="space-y-4">
<h2 className="text-lg font-medium text-[var(--Text-text-primary)]">
Tooltip 位置
</h2>
<div className="p-6 bg-[var(--Container-bg-container)] rounded-[var(--radius-lg)] border border-[var(--Border-border-neutral)] space-y-4">
<div className="flex flex-wrap gap-4">
<IconButton
tooltip="上边"
tooltipSide="top"
variant="outline"
color="secondary"
>
<ChevronUp className="size-4" />
</IconButton>
<IconButton
tooltip="下边"
tooltipSide="bottom"
variant="outline"
color="secondary"
>
<ChevronDown className="size-4" />
</IconButton>
<IconButton
tooltip="左边"
tooltipSide="left"
variant="outline"
color="secondary"
>
<ChevronLeft className="size-4" />
</IconButton>
<IconButton
tooltip="右边"
tooltipSide="right"
variant="outline"
color="secondary"
>
<ChevronRight className="size-4" />
</IconButton>
</div>
</div>
</section>
{/* 加载状态 */}
<section className="space-y-4">
<h2 className="text-lg font-medium text-[var(--Text-text-primary)]">
加载状态
</h2>
<div className="p-6 bg-[var(--Container-bg-container)] rounded-[var(--radius-lg)] border border-[var(--Border-border-neutral)] space-y-4">
<div className="flex flex-wrap gap-4">
<IconButton
tooltip="下载中..."
loading={loadingStates["load1"]}
variant="solid"
color="primary"
onClick={() => toggleLoading("load1")}
>
<Download className="size-4" />
</IconButton>
<IconButton
tooltip="上传中..."
loading={loadingStates["load2"]}
variant="light"
color="primary"
onClick={() => toggleLoading("load2")}
>
<Upload className="size-4" />
</IconButton>
<IconButton
tooltip="刷新中..."
loading={loadingStates["load3"]}
variant="ghost"
color="primary"
onClick={() => toggleLoading("load3")}
>
<RefreshCw className="size-4" />
</IconButton>
</div>
</div>
</section>
{/* 禁用状态 */}
<section className="space-y-4">
<h2 className="text-lg font-medium text-[var(--Text-text-primary)]">
禁用状态
</h2>
<div className="p-6 bg-[var(--Container-bg-container)] rounded-[var(--radius-lg)] border border-[var(--Border-border-neutral)] space-y-4">
<div className="flex flex-wrap gap-4">
<IconButton tooltip="禁用" disabled variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton tooltip="禁用" disabled variant="light" color="primary">
<Settings className="size-4" />
</IconButton>
<IconButton
tooltip="禁用"
disabled
variant="outline"
color="secondary"
>
<Download className="size-4" />
</IconButton>
<IconButton tooltip="禁用" disabled variant="ghost" color="danger">
<Trash2 className="size-4" />
</IconButton>
</div>
</div>
</section>
{/* 实际应用场景 */}
<section className="space-y-4">
<h2 className="text-lg font-medium text-[var(--Text-text-primary)]">
实际应用场景
</h2>
<div className="p-6 bg-[var(--Container-bg-container)] rounded-[var(--radius-lg)] border border-[var(--Border-border-neutral)] space-y-4">
{/* 工具栏场景 */}
<div className="space-y-2">
<h3 className="text-sm font-medium text-[var(--Text-text-secondary)]">
工具栏按钮组(Ghost 变体)
</h3>
<div className="flex items-center gap-1 p-2 bg-[var(--Page-bg-page-secondary)] rounded-[var(--radius-md)] border border-[var(--Border-border-neutral)]">
<IconButton
tooltip="添加文件夹"
variant="ghost"
color="secondary"
size="sm"
>
<FolderPlus className="size-4" />
</IconButton>
<IconButton
tooltip="添加文件"
variant="ghost"
color="secondary"
size="sm"
>
<FilePlus className="size-4" />
</IconButton>
<IconButton
tooltip="编辑"
variant="ghost"
color="secondary"
size="sm"
>
<Edit2 className="size-4" />
</IconButton>
<IconButton
tooltip="删除"
variant="ghost"
color="danger"
size="sm"
>
<Trash2 className="size-4" />
</IconButton>
<div className="w-px h-6 bg-[var(--Border-border-neutral)] mx-2" />
<IconButton
tooltip="搜索"
variant="ghost"
color="secondary"
size="sm"
>
<Search className="size-4" />
</IconButton>
<IconButton
tooltip="刷新"
variant="ghost"
color="secondary"
size="sm"
>
<RefreshCw className="size-4" />
</IconButton>
</div>
</div>
{/* Light 工具栏场景 */}
<div className="space-y-2">
<h3 className="text-sm font-medium text-[var(--Text-text-secondary)]">
工具栏按钮组(Light 变体)
</h3>
<div className="flex items-center gap-2 p-3 bg-[var(--Page-bg-page-secondary)] rounded-[var(--radius-md)] border border-[var(--Border-border-neutral)]">
<IconButton
tooltip="刷新"
variant="light"
color="primary"
size="sm"
>
<RefreshCw className="size-4" />
</IconButton>
<IconButton
tooltip="设置"
variant="light"
color="primary"
size="sm"
>
<Settings className="size-4" />
</IconButton>
<IconButton
tooltip="下载"
variant="light"
color="primary"
borderless
size="sm"
>
<Download className="size-4" />
</IconButton>
<IconButton
tooltip="上传"
variant="light"
color="primary"
borderless
size="sm"
>
<Upload className="size-4" />
</IconButton>
</div>
</div>
{/* 更多操作场景 */}
<div className="space-y-2">
<h3 className="text-sm font-medium text-[var(--Text-text-secondary)]">
卡片操作按钮
</h3>
<div className="flex items-center gap-2 p-4 bg-[var(--Page-bg-page-secondary)] rounded-[var(--radius-md)] border border-[var(--Border-border-neutral)]">
<span className="text-sm text-[var(--Text-text-secondary)] flex-1">
项目名称
</span>
<IconButton
tooltip="编辑"
variant="ghost"
color="secondary"
size="sm"
>
<Edit2 className="size-4" />
</IconButton>
<IconButton
tooltip="更多"
variant="ghost"
color="secondary"
size="sm"
>
<MoreVertical className="size-4" />
</IconButton>
<IconButton
tooltip="关闭"
variant="ghost"
color="secondary"
size="sm"
>
<X className="size-4" />
</IconButton>
</div>
</div>
</div>
</section>
</div>
);
}
Icon Button 组件是带有可选 Tooltip 功能的图标按钮,适用于工具栏、卡片操作等场景。
概述
- 四种变体:solid(实心)、light(浅色)、outline(边框)、ghost(幽灵)
- 三种颜色:primary(主色)、secondary(次要色)、danger(危险色)
- 四种尺寸:sm(小,24px)、md(中,32px)、lg(大,36px)、xl(超大,40px)
- 内置 Tooltip:通过
tooltip属性快速添加提示信息 - 灵活定位:Tooltip 支持四个方向的定位
- 完整状态:支持 default、hover、pressed、disabled、loading 状态
- CSS Token:使用 CSS 变量实现主题化
快速开始
import { IconButton } from "@/registry/wuhan/composed/icon-button/icon-button";
import { Plus, Settings } from "lucide-react";
export function Example() {
return (
<div className="flex gap-2">
{/* 带 Tooltip 的图标按钮 */}
<IconButton tooltip="添加内容">
<Plus className="size-4" />
</IconButton>
{/* 不带 Tooltip */}
<IconButton variant="outline" color="secondary">
<Settings className="size-4" />
</IconButton>
</div>
);
}特性
- 图标优先:专为图标设计的紧凑按钮
- Tooltip 集成:内置 Tooltip 支持,无需额外封装
- 多种变体:满足不同视觉权重需求
- 完整状态:覆盖所有交互状态
- 主题化:基于 CSS 变量,易于定制
- 可访问性:支持键盘导航和屏幕阅读器
安装
代码演示
基础用法
不带 Tooltip 的图标按钮,适用于不需要提示信息的场景。
<IconButton variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton variant="light" color="primary">
<Settings className="size-4" />
</IconButton>
<IconButton variant="outline" color="secondary">
<Download className="size-4" />
</IconButton>
<IconButton variant="ghost" color="primary">
<MoreHorizontal className="size-4" />
</IconButton>带 Tooltip 的图标按钮
通过 tooltip 属性添加提示信息,悬停时显示。
<IconButton tooltip="添加新内容" variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton tooltip="删除" variant="outline" color="danger">
<Trash2 className="size-4" />
</IconButton>
<IconButton tooltip="编辑" variant="ghost" color="primary">
<Edit2 className="size-4" />
</IconButton>按钮变体
四种变体样式:solid(实心)、light(浅色)、outline(边框)、ghost(幽灵)。
{
/* Solid 实心 */
}
<IconButton variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>;
{
/* Light 浅色 */
}
<IconButton variant="light" color="primary">
<Settings className="size-4" />
</IconButton>;
{
/* Light 浅色(无边框) */
}
<IconButton variant="light" color="primary" borderless>
<Download className="size-4" />
</IconButton>;
{
/* Outline 边框 */
}
<IconButton variant="outline" color="primary">
<MoreHorizontal className="size-4" />
</IconButton>;
{
/* Ghost 幽灵 */
}
<IconButton variant="ghost" color="primary">
<Trash2 className="size-4" />
</IconButton>;按钮颜色
三种颜色:primary(主色)、secondary(次要色)、danger(危险色)。
{
/* Primary 主色 */
}
<IconButton variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>;
{
/* Secondary 次要色 */
}
<IconButton variant="solid" color="secondary">
<Settings className="size-4" />
</IconButton>;
{
/* Danger 危险色 */
}
<IconButton variant="solid" color="danger">
<Trash2 className="size-4" />
</IconButton>;按钮尺寸
四种尺寸:sm(24px)、md(32px)、lg(36px)、xl(40px)。
<IconButton size="sm" variant="solid" color="primary">
<Plus className="size-3.5" />
</IconButton>
<IconButton size="md" variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton size="lg" variant="solid" color="primary">
<Plus className="size-4.5" />
</IconButton>
<IconButton size="xl" variant="solid" color="primary">
<Plus className="size-5" />
</IconButton>Light 变体
Light 变体具有浅色背景和边框,支持有边框和无边框两种模式。
{
/* Light 有边框 */
}
<IconButton variant="light" color="primary">
<Settings className="size-4" />
</IconButton>;
{
/* Light 无边框 */
}
<IconButton variant="light" color="primary" borderless>
<Download className="size-4" />
</IconButton>;Tooltip 位置
通过 tooltipSide 属性控制 Tooltip 的显示位置。
<IconButton tooltip="上边" tooltipSide="top" variant="outline" color="secondary">
<ChevronUp className="size-4" />
</IconButton>
<IconButton tooltip="下边" tooltipSide="bottom" variant="outline" color="secondary">
<ChevronDown className="size-4" />
</IconButton>
<IconButton tooltip="左边" tooltipSide="left" variant="outline" color="secondary">
<ChevronLeft className="size-4" />
</IconButton>
<IconButton tooltip="右边" tooltipSide="right" variant="outline" color="secondary">
<ChevronRight className="size-4" />
</IconButton>加载状态
通过 loading 属性显示加载状态。
const [loading, setLoading] = useState(false);
<IconButton tooltip="下载中" loading={loading} onClick={() => setLoading(true)}>
<Download className="size-4" />
</IconButton>;禁用状态
通过 disabled 属性禁用按钮。
<IconButton tooltip="禁用" disabled variant="solid" color="primary">
<Plus className="size-4" />
</IconButton>
<IconButton tooltip="禁用" disabled variant="light" color="primary">
<Settings className="size-4" />
</IconButton>
<IconButton tooltip="禁用" disabled variant="outline" color="secondary">
<Download className="size-4" />
</IconButton>工具栏场景
图标按钮常用于工具栏场景。
<div className="flex items-center gap-1 p-2 bg-surface rounded-md border">
<IconButton tooltip="添加文件夹" variant="ghost" color="secondary" size="sm">
<FolderPlus className="size-4" />
</IconButton>
<IconButton tooltip="添加文件" variant="ghost" color="secondary" size="sm">
<FilePlus className="size-4" />
</IconButton>
<IconButton tooltip="编辑" variant="ghost" color="secondary" size="sm">
<Edit2 className="size-4" />
</IconButton>
<IconButton tooltip="删除" variant="ghost" color="danger" size="sm">
<Trash2 className="size-4" />
</IconButton>
</div>卡片操作按钮
用于卡片或列表项的操作按钮。
<div className="flex items-center gap-2 p-4 bg-surface rounded-md border">
<span className="text-sm text-secondary flex-1">项目名称</span>
<IconButton tooltip="编辑" variant="ghost" color="secondary" size="sm">
<Edit2 className="size-4" />
</IconButton>
<IconButton tooltip="更多" variant="ghost" color="secondary" size="sm">
<MoreVertical className="size-4" />
</IconButton>
<IconButton tooltip="关闭" variant="ghost" color="secondary" size="sm">
<X className="size-4" />
</IconButton>
</div>API
IconButton Props
|| 参数 | 说明 | 类型 | 默认值 |
||------|------|------|--------|
|| variant | 按钮变体 | 'solid' \| 'light' \| 'outline' \| 'ghost' | 'solid' |
|| color | 按钮颜色 | 'primary' \| 'secondary' \| 'danger' | 'primary' |
|| size | 按钮尺寸 | 'sm' \| 'md' \| 'lg' \| 'xl' | 'md' |
|| loading | 是否加载中 | boolean | false |
|| disabled | 是否禁用 | boolean | false |
|| borderless | 是否无边框(仅 light 变体有效) | boolean | false |
|| tooltip | 提示内容 | React.ReactNode | - |
|| tooltipSide | Tooltip 位置 | 'top' \| 'right' \| 'bottom' \| 'left' | 'top' |
|| tooltipSideOffset | Tooltip 距离 | number | 4 |
|| tooltipAlign | Tooltip 对齐 | 'start' \| 'center' \| 'end' | 'center' |
|| tooltipDelayDuration | Tooltip 延迟 | number | 0 |
|| tooltipContentClassName | Tooltip 自定义类名 | string | - |
|| children | 按钮内容(图标) | React.ReactNode | - |
|| onClick | 点击事件 | () => void | - |
设计规范
尺寸规范
|| 尺寸 | 按钮尺寸 | 图标尺寸 | ||------|----------|----------| || sm | 24px (size-6) | 14px (size-3.5) | || md | 32px (size-8) | 16px (size-4) | || lg | 36px (size-9) | 18px (size-4.5) | || xl | 40px (size-10) | 20px (size-5) |
基础样式
|| 属性 | 值 | ||------|-----| || 圆角 | 8px (radius-md) | || 边框 | transparent(实心/幽灵),品牌色(边框/浅色) | || 聚焦环 | ring-brand,offset 2px |
颜色规范
Primary 主色
|| 状态 | Solid | Light | Light (borderless) | Outline | Ghost | ||------|-------|-------|-------------------|---------|-------| || default | bg-brand, text-inverse | bg-brand-light, border-brand-light, text-brand | bg-brand-light, text-brand | bg-container, border-brand, text-brand | bg-transparent, text-brand | || hover | bg-brand-hover, text-inverse | bg-brand-light-hover, border-brand-light-hover | bg-brand-light-hover | border-brand-hover, text-brand-hover | bg-brand-light | || pressed | bg-brand-active, text-inverse | bg-brand-light-active, border-brand-light-active | bg-brand-light-active | border-brand-active, text-brand-active | bg-brand-light-active | || disabled | opacity-50 | opacity-50 | opacity-50 | bg-container-disable, text-disable | bg-transparent, text-disable | || loading | opacity-50 | opacity-50 | opacity-50 | bg-container-disable, text-disable | bg-transparent, text-disable |
Secondary 次要色
|| 状态 | Solid | Outline | Ghost | ||------|-------|---------|-------| || default | bg-secondary, text-inverse | bg-container, border-neutral, text-secondary | bg-transparent, text-secondary | || hover | bg-secondary-hover, text-inverse | bg-neutral-light, text-secondary-hover | bg-neutral-light | || pressed | bg-secondary-active, text-inverse | bg-neutral-light-hover, text-secondary-active | bg-neutral-light-hover | || disabled | opacity-50 | bg-container-disable, text-disable | bg-transparent, text-disable | || loading | opacity-50 | bg-container-disable, text-disable | bg-transparent, text-disable |
Danger 危险色
|| 状态 | Solid | Outline | Ghost | ||------|-------|---------|-------| || default | bg-error, text-inverse | bg-container, border-error, text-error | bg-transparent, text-error | || hover | bg-error-hover, text-inverse | border-error-hover, text-error-hover | bg-error-light | || pressed | bg-error-active, text-inverse | border-error-active, text-error-active | bg-error-light-active | || disabled | opacity-50 | bg-container-disable, text-disable | bg-transparent, text-disable | || loading | opacity-50 | bg-container-disable, text-disable | bg-transparent, text-disable |
使用场景
- 工具栏按钮:工具栏中的操作按钮,如添加、编辑、删除
- 卡片操作:卡片或列表项的快速操作按钮
- 表单辅助:表单中的辅助功能按钮
- 状态切换:开关模式的图标按钮
- 导航辅助:面包屑、标签页等导航元素
最佳实践
- 图标选择:使用清晰的图标,确保含义直观
- Tooltip 内容:保持简洁,不超过一句话
- 颜色使用:危险操作使用 danger 颜色
- 尺寸一致:同一工具栏保持相同尺寸
- 状态反馈:加载状态时禁止重复点击
- 可访问性:确保图标按钮可通过键盘访问
注意事项
- CSS 变量:组件使用 CSS 变量实现主题化,需要在全局样式中定义对应的变量
- 加载状态:加载状态时会禁用按钮并显示加载图标
- Tooltip 依赖:使用 Tooltip 功能需要安装
@radix-ui/react-tooltip - 图标尺寸:图标尺寸会根据按钮大小自动调整,无需手动设置
- 禁用状态:禁用状态会覆盖加载状态
- Light 变体:borderless 属性仅对 light 变体有效
原语组件
IconButton 基于 IconButtonPrimitive 原语组件构建,该组件提供了更底层的控制。
原语组件提供了:
IconButtonPrimitive- 基础图标按钮样式
可以在 registry/wuhan/blocks/icon-button/icon-button-01.tsx 中找到原语组件。
与 Tooltip 组件的关系
IconButton 组件内置了 Tooltip 功能,这是通过组合 IconButtonPrimitive 和 Tooltip 组件实现的。
如果你需要更复杂的 Tooltip 行为,可以直接使用 Tooltip 组件:
import { Tooltip } from "@/registry/wuhan/composed/tooltip";
import { IconButtonPrimitive } from "@/registry/wuhan/blocks/icon-button/icon-button-01";
<Tooltip content="自定义提示">
<IconButtonPrimitive variant="light" color="primary">
<Plus className="size-4" />
</IconButtonPrimitive>
</Tooltip>;扩展示例
复制按钮
import { useState } from "react";
import { IconButton } from "@/registry/wuhan/composed/icon-button/icon-button";
import { Copy, Check } from "lucide-react";
function CopyButton({ text }: { text: string }) {
const [copied, setCopied] = useState(false);
const handleCopy = () => {
navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
return (
<IconButton
tooltip={copied ? "已复制" : "复制"}
onClick={handleCopy}
variant="ghost"
color="secondary"
>
{copied ? (
<Check className="size-4 text-success" />
) : (
<Copy className="size-4" />
)}
</IconButton>
);
}图标切换
import { useState } from "react";
import { IconButton } from "@/registry/wuhan/composed/icon-button/icon-button";
import { Star, StarOff } from "lucide-react";
function FavoriteButton() {
const [favorite, setFavorite] = useState(false);
return (
<IconButton
tooltip={favorite ? "取消收藏" : "收藏"}
onClick={() => setFavorite(!favorite)}
variant={favorite ? "solid" : "light"}
color="primary"
>
{favorite ? (
<Star className="size-4 fill-current" />
) : (
<Star className="size-4" />
)}
</IconButton>
);
}Light 变体工具栏
<div className="flex items-center gap-2 p-3 bg-surface rounded-lg border">
<IconButton tooltip="刷新" variant="light" color="primary" size="sm">
<RefreshCw className="size-4" />
</IconButton>
<IconButton tooltip="设置" variant="light" color="primary" size="sm">
<Settings className="size-4" />
</IconButton>
<IconButton tooltip="下载" variant="light" color="primary" borderless size="sm">
<Download className="size-4" />
</IconButton>
<IconButton tooltip="上传" variant="light" color="primary" borderless size="sm">
<Upload className="size-4" />
</IconButton>
</div>