17 KiB
17 KiB
按钮扩展组件设计文档
版本: v1.2.0 更新时间: 2025-11-17 作者: Nex Design Team 状态: ✅ 已完成
📖 目录
概述
设计目标
为终端列表页面的按钮提供清晰的操作介绍和帮助信息,解决以下问题:
- 用户不了解按钮功能
- 复杂操作缺少引导
- 需要快速的上下文帮助
设计原则
- 简洁至上 - 去除不必要的动画,使用扁平化设计
- 功能独立 - 帮助功能不影响主操作流程
- 易于理解 - 直观的图标和交互模式
- 现代美学 - 符合Material Design和Fluent Design趋势
设计方案
我们提供了5种不同的设计方案,可根据实际场景选择使用:
方案1:增强型工具提示 (Enhanced Tooltip)
特点:
- 渐变色彩背景,视觉效果出众
- 支持标题、描述、快捷键、注意事项
- 带有脉冲动画的提示图标
- 响应式设计,移动端友好
适用场景:
- ✅ 简单操作,需要快速了解功能
- ✅ 不希望占用额外页面空间
- ✅ 信息量较少的提示
效果预览:
[按钮] (i) ← 脉冲动画图标
↓ 悬停
┌────────────────────────┐
│ 新增主机 │
│ 向系统中添加新的主机... │
│ 快捷键: Ctrl+N │
│ 注意: 请确保IP不冲突 │
└────────────────────────┘
方案2:智能帮助面板 (Smart Help Panel) ⭐ 推荐
特点:
- 侧边抽屉式设计,信息完整
- 实时显示当前悬停按钮的详细信息
- 包含使用场景、操作步骤、注意事项等
- 支持查看所有可用操作的快速索引
- 点击"?"图标直接打开帮助面板
适用场景:
- ✅ 复杂业务操作,需要详细说明
- ✅ 新用户培训和引导
- ✅ 功能较多,需要分步骤引导
交互流程:
1. 悬停按钮 → 出现"?"图标
2. 点击"?" → 打开右侧帮助面板
3. 显示详细内容:
- 功能说明
- 使用场景
- 操作步骤
- 注意事项
- 快捷键
- 权限要求
特殊优化:
- 面板打开时,鼠标离开按钮不会清空内容
- 点击"所有可用操作"卡片可切换内容
- 自动展开"当前操作"区域
方案3:悬浮展开卡片 (Hover Expand Card)
特点:
- 精美的悬浮卡片设计
- 滑入动画,视觉流畅
- 分层信息展示
- 使用React Portal渲染,永不被遮挡
适用场景:
- ✅ 需要展示较多信息
- ✅ 不想打断操作流程
- ✅ 希望信息就近显示
技术实现:
// 使用Portal避免z-index遮挡问题
import { createPortal } from 'react-dom'
{createPortal(renderCard(), document.body)}
方案4:智能引导 (Smart Guide)
特点:
- 简洁扁平设计,独立帮助图标
- 点击查看弹窗式详细引导
- 包含步骤式操作说明
适用场景:
- ✅ 需要详细引导,但不希望干扰主流程
- ✅ 功能上线初期的用户引导
- ✅ 复杂操作的分步说明
设计对比:
旧版(已废弃):脉冲动画徽章,过于复杂
新版:简洁帮助图标,点击查看详情
┌────────────┐ ┌─┐
│ 新增主机 │ │?│ ← 简洁优雅
└────────────┘ └─┘
方案5:底部固定提示栏 (Bottom Hint Bar)
特点:
- 固定底部位置,不遮挡操作区域
- 实时更新,流畅切换
- 三种主题可选(渐变、浅色、深色)
适用场景:
- ✅ 需要始终可见的提示信息
- ✅ 不希望被tooltip遮挡操作区域
- ✅ 简单的实时信息展示
组件API
ButtonWithTip
增强型工具提示按钮组件。
Props:
interface ButtonWithTipProps {
label: string // 按钮文本
icon?: ReactNode // 按钮图标
type?: 'primary' | 'default' // 按钮类型
danger?: boolean // 是否为危险按钮
disabled?: boolean // 是否禁用
onClick?: () => void // 点击回调
size?: 'small' | 'middle' | 'large'
showTipIcon?: boolean // 是否显示提示图标
tip?: {
title?: string // 提示标题
description?: string // 详细描述
shortcut?: string // 快捷键
notes?: string[] // 注意事项
placement?: 'top' | 'bottom' | 'left' | 'right'
}
}
使用示例:
import ButtonWithTip from '@/components/ButtonWithTip/ButtonWithTip'
<ButtonWithTip
label="新增主机"
icon={<PlusOutlined />}
type="primary"
tip={{
title: '新增主机',
description: '向系统中添加新的主机终端设备',
shortcut: 'Ctrl+N',
notes: ['请确保IP地址不与现有主机冲突', 'MAC地址必须唯一']
}}
onClick={handleAdd}
/>
ActionHelpPanel
智能帮助面板组件(方案2)。
Props:
interface ActionHelpPanelProps {
visible: boolean // 是否显示面板
onClose: () => void // 关闭回调
currentAction?: { // 当前操作信息
title: string
icon: ReactNode
description: string
scenarios?: string[] // 使用场景
steps?: string[] // 操作步骤
warnings?: string[] // 注意事项
shortcut?: string // 快捷键
permission?: string // 权限要求
badge?: {
text: string
color: string
}
}
allActions?: Array<Action> // 所有可用操作
placement?: 'left' | 'right' // 面板位置
onActionSelect?: (action: Action) => void // 选择操作回调
}
使用示例:
import ActionHelpPanel from '@/components/ActionHelpPanel/ActionHelpPanel'
const [showPanel, setShowPanel] = useState(false)
const [currentAction, setCurrentAction] = useState(null)
// 在按钮外层添加hover和点击事件
<div
onMouseEnter={() => setCurrentAction(actionsConfig.add)}
onMouseLeave={() => !showPanel && setCurrentAction(null)}
>
<Button>新增主机</Button>
<button onClick={() => setShowPanel(true)}>?</button>
</div>
<ActionHelpPanel
visible={showPanel}
onClose={() => setShowPanel(false)}
currentAction={currentAction}
allActions={Object.values(actionsConfig)}
onActionSelect={(action) => setCurrentAction(action)}
/>
ButtonWithHoverCard
悬浮展开卡片按钮组件(方案3)。
Props:
interface ButtonWithHoverCardProps {
label: string
icon?: ReactNode
type?: 'primary' | 'default'
danger?: boolean
disabled?: boolean
onClick?: () => void
size?: 'small' | 'middle' | 'large'
cardInfo?: {
title: string
icon: ReactNode
description: string
scenarios?: string[]
quickTips?: string[]
warnings?: string[]
shortcut?: string
badge?: { text: string; color: string }
}
}
技术要点:
- 使用
createPortal渲染卡片到document.body - 使用
useRef获取按钮位置 - 避免z-index遮挡问题
ButtonWithGuide
智能引导按钮组件(方案4)。
Props:
interface ButtonWithGuideProps {
label: string
icon?: ReactNode
type?: 'primary' | 'default'
danger?: boolean
disabled?: boolean
onClick?: () => void
size?: 'small' | 'middle' | 'large'
guide?: {
title: string
icon: ReactNode
description: string
steps?: string[]
scenarios?: string[]
warnings?: string[]
shortcut?: string
permission?: string
badge?: { text: string; color: string }
}
}
特点:
- 简洁的帮助图标(不影响按钮文字)
- 点击打开弹窗式详细引导
- 包含步骤式说明(使用Ant Design Steps组件)
BottomHintBar
底部固定提示栏组件(方案5)。
Props:
interface BottomHintBarProps {
visible: boolean
hintInfo?: {
title: string
icon: ReactNode
description: string
quickTip?: string
warning?: string
shortcut?: string
badge?: { text: string; color: string }
}
onClose?: () => void
theme?: 'light' | 'dark' | 'gradient'
}
使用示例:
import BottomHintBar from '@/components/BottomHintBar/BottomHintBar'
const [showHint, setShowHint] = useState(false)
const [hintInfo, setHintInfo] = useState(null)
<div
onMouseEnter={() => {
setHintInfo(actionConfig)
setShowHint(true)
}}
onMouseLeave={() => setShowHint(false)}
>
<Button>操作按钮</Button>
</div>
<BottomHintBar
visible={showHint}
hintInfo={hintInfo}
theme="gradient"
/>
使用指南
快速开始
- 选择合适的方案
根据使用场景选择组件:
| 场景 | 推荐方案 |
|---|---|
| 简单列表页面,快速提示 | 方案1 增强型工具提示 |
| 复杂后台系统,详细引导 | 方案2 智能帮助面板 ⭐ |
| 数据密集页面,信息丰富 | 方案3 悬浮展开卡片 |
| 新功能上线,用户引导 | 方案4 智能引导 |
| 操作频繁,始终可见 | 方案5 底部固定提示栏 |
- 导入组件
// 方案1
import ButtonWithTip from '@/components/ButtonWithTip/ButtonWithTip'
// 方案2
import ActionHelpPanel from '@/components/ActionHelpPanel/ActionHelpPanel'
// 方案3
import ButtonWithHoverCard from '@/components/ButtonWithHoverCard/ButtonWithHoverCard'
// 方案4
import ButtonWithGuide from '@/components/ButtonWithGuide/ButtonWithGuide'
// 方案5
import BottomHintBar from '@/components/BottomHintBar/BottomHintBar'
- 配置操作信息
建议将操作配置统一管理:
const actionsConfig = {
add: {
title: '新增主机',
icon: <PlusOutlined />,
description: '向系统中添加新的主机终端设备',
scenarios: [
'当有新设备需要接入系统管理时',
'需要扩展终端设备数量时'
],
steps: [
'点击"新增主机"按钮',
'填写主机基本信息',
'选择主机所属分组',
'保存并等待主机上线'
],
warnings: [
'请确保IP地址不与现有主机冲突',
'MAC地址必须唯一且格式正确'
],
shortcut: 'Ctrl+N',
permission: '管理员权限',
badge: { text: '常用', color: 'blue' }
},
// ... 其他操作
}
方案2完整实现示例
import { useState } from 'react'
import { Button } from 'antd'
import { PlusOutlined } from '@ant-design/icons'
import ActionHelpPanel from '@/components/ActionHelpPanel/ActionHelpPanel'
function MyPage() {
const [showHelpPanel, setShowHelpPanel] = useState(false)
const [currentAction, setCurrentAction] = useState(null)
// 处理悬停
const handleHover = (actionKey) => {
if (!showHelpPanel) {
setCurrentAction(actionsConfig[actionKey])
}
}
// 处理离开
const handleLeave = () => {
if (!showHelpPanel) {
setCurrentAction(null)
}
}
// 处理点击
const handleHelpClick = (e, actionKey) => {
e.stopPropagation()
setCurrentAction(actionsConfig[actionKey])
setShowHelpPanel(true)
}
return (
<div>
{/* 按钮区域 */}
<div
className="button-wrapper"
onMouseEnter={() => handleHover('add')}
onMouseLeave={handleLeave}
>
<Button type="primary" icon={<PlusOutlined />}>
新增主机
</Button>
<button
className="help-icon"
onClick={(e) => handleHelpClick(e, 'add')}
>
?
</button>
</div>
{/* 帮助面板 */}
<ActionHelpPanel
visible={showHelpPanel}
onClose={() => setShowHelpPanel(false)}
currentAction={currentAction}
allActions={Object.values(actionsConfig)}
onActionSelect={(action) => setCurrentAction(action)}
/>
</div>
)
}
最佳实践
1. 内容编写规范
功能描述:
- 用简洁的语言描述功能(1-2句话)
- 突出重点和目的
- 避免技术术语
使用场景:
- 列举2-4个实际使用场景
- 使用"当...时"的句式
- 帮助用户理解何时使用
操作步骤:
- 按实际操作顺序编写
- 每步一句话,清晰明确
- 使用动词开头
注意事项:
- 危险操作必须有明确警告
- 使用醒目的颜色标记
- 提供实际的使用建议
2. 性能优化
// ✅ 使用useMemo缓存配置
const actionsConfig = useMemo(() => ({
add: { ... },
delete: { ... }
}), [])
// ✅ 防止不必要的重渲染
const handleHover = useCallback((key) => {
if (!showPanel) {
setCurrentAction(actionsConfig[key])
}
}, [showPanel, actionsConfig])
// ✅ 面板打开时避免hover更新
if (!showPanel) {
setCurrentAction(null)
}
3. 可访问性
// 添加title属性
<button className="help-icon" title="查看帮助">
?
</button>
// 添加aria标签
<Button aria-label="新增主机">
新增主机
</Button>
// 快捷键支持
useEffect(() => {
const handleKeyPress = (e) => {
if (e.ctrlKey && e.key === 'n') {
handleAdd()
}
}
window.addEventListener('keydown', handleKeyPress)
return () => window.removeEventListener('keydown', handleKeyPress)
}, [])
4. 响应式适配
/* 移动端隐藏某些提示 */
@media (max-width: 768px) {
.help-icon {
display: none;
}
.hover-info-card {
width: 100%;
left: 0 !important;
transform: translateY(-50%);
}
}
更新日志
v1.2.0 (2025-11-17)
新增:
- ✨ 新增
ButtonWithGuide组件,替代复杂的徽章设计 - ✨ 方案2添加
onActionSelect回调,支持点击卡片切换内容
修复:
- 🐛 修复方案2点击"?"后内容消失的问题
- 🐛 修复方案2"所有可用操作"卡片无法点击的问题
- 🐛 修复方案3悬浮卡片被Card遮挡(使用Portal)
- 🐛 修复菜单图标,从
GlobalOutlined改为BlockOutlined
优化:
- 💄 简化方案4设计,去掉复杂的脉冲动画
- 💄 方案2面板打开时不响应鼠标hover事件
- 💄 提升整体视觉一致性
v1.1.0 (2025-11-17)
新增:
- ✨ 新增
ActionHelpPanel智能帮助面板组件 - ✨ 新增
BottomHintBar底部提示栏组件 - ✨ 方案2添加点击"?"图标直接打开面板功能
修复:
- 🐛 修复
ButtonWithTip的 Tooltip overlayClassName 警告 - 🐛 修复
AppSider的 findDOMNode 警告(使用 items 配置) - 🐛 修复方案5底部提示栏鼠标移动时闪烁的问题
优化:
- 💄 为方案2按钮添加悬停时的"?"图标提示
- 💄 提升方案3悬浮卡片的 z-index 和阴影效果
v1.0.0 (2025-11-17)
初始版本:
- 🎉 发布5种按钮扩展设计方案
- 📦 提供完整的组件API和使用文档
- 📝 提供详细的设计指南和最佳实践
技术架构
依赖项
{
"react": "^18.2.0",
"react-dom": "^18.2.0",
"antd": "^5.x",
"@ant-design/icons": "^5.x"
}
目录结构
src/components/
├── ButtonWithTip/
│ ├── ButtonWithTip.jsx
│ └── ButtonWithTip.css
├── ActionHelpPanel/
│ ├── ActionHelpPanel.jsx
│ └── ActionHelpPanel.css
├── ButtonWithHoverCard/
│ ├── ButtonWithHoverCard.jsx
│ └── ButtonWithHoverCard.css
├── ButtonWithGuide/
│ ├── ButtonWithGuide.jsx
│ └── ButtonWithGuide.css
└── BottomHintBar/
├── BottomHintBar.jsx
└── BottomHintBar.css
src/pages/
└── AllButtonDesigns.jsx # 演示页面
docs/
└── components/
└── ButtonExtensions.md # 本文档
常见问题
Q1: 如何选择合适的方案?
A: 根据以下因素选择:
- 信息量:少 → 方案1,多 → 方案2/3
- 复杂度:简单 → 方案1/5,复杂 → 方案2/4
- 使用频率:频繁 → 方案5,偶尔 → 方案1/3
- 用户类型:新手 → 方案2/4,熟练 → 方案1/5
Q2: 可以混合使用多种方案吗?
A: 可以。建议:
- 同一页面使用统一的方案
- 不同页面可以使用不同方案
- 核心操作使用方案2,次要操作使用方案1
Q3: 如何自定义样式?
A: 所有组件都支持自定义样式:
// 通过className
<ButtonWithTip className="my-custom-button" />
// 通过style
<ButtonWithTip style={{ marginRight: 16 }} />
// 修改CSS变量
:root {
--tip-primary-gradient: linear-gradient(...);
}
Q4: 移动端如何适配?
A: 所有组件都内置了响应式支持:
- 方案1:移动端隐藏提示图标
- 方案2:面板宽度自适应
- 方案3:卡片居中显示
- 方案5:提示栏自适应布局
最后更新: 2025-11-17 文档版本: v1.2.0