import { useState, useRef } from 'react' import { createPortal } from 'react-dom' import { Button, Card, Tag } from 'antd' import { BulbOutlined, WarningOutlined, ThunderboltOutlined, } from '@ant-design/icons' import './ButtonWithHoverCard.css' /** * 悬浮展开卡片按钮组件 * 鼠标悬停时,在按钮旁边展开一个精美的信息卡片 * @param {Object} props * @param {string} props.label - 按钮文本 * @param {ReactNode} props.icon - 按钮图标 * @param {string} props.type - 按钮类型 * @param {boolean} props.danger - 危险按钮 * @param {boolean} props.disabled - 禁用状态 * @param {Function} props.onClick - 点击回调 * @param {Object} props.cardInfo - 卡片信息配置 * @param {string} props.size - 按钮大小 */ function ButtonWithHoverCard({ label, icon, type = 'default', danger = false, disabled = false, onClick, cardInfo, size = 'middle', ...restProps }) { const [showCard, setShowCard] = useState(false) const [cardPosition, setCardPosition] = useState({ top: 0, left: 0 }) const wrapperRef = useRef(null) const handleMouseEnter = () => { if (!cardInfo || disabled) return if (wrapperRef.current) { const rect = wrapperRef.current.getBoundingClientRect() setCardPosition({ top: rect.top + rect.height / 2, left: rect.right + 12, }) } setShowCard(true) } const handleMouseLeave = () => { setShowCard(false) } // 渲染悬浮卡片 const renderCard = () => { if (!showCard || !cardInfo) return null return (
{/* 标题区 */}
{cardInfo.icon && ( {cardInfo.icon} )}

{cardInfo.title}

{cardInfo.badge && ( {cardInfo.badge.text} )}
{/* 描述 */} {cardInfo.description && (

{cardInfo.description}

)} {/* 使用场景 */} {cardInfo.scenarios && cardInfo.scenarios.length > 0 && (
使用场景
    {cardInfo.scenarios.slice(0, 2).map((scenario, index) => (
  • {scenario}
  • ))}
)} {/* 快速提示 */} {cardInfo.quickTips && cardInfo.quickTips.length > 0 && (
快速提示
    {cardInfo.quickTips.map((tip, index) => (
  • {tip}
  • ))}
)} {/* 注意事项 */} {cardInfo.warnings && cardInfo.warnings.length > 0 && (
注意
    {cardInfo.warnings.slice(0, 2).map((warning, index) => (
  • {warning}
  • ))}
)} {/* 快捷键 */} {cardInfo.shortcut && (
快捷键 {cardInfo.shortcut}
)}
) } return ( <>
{/* 使用 Portal 渲染悬浮卡片到 body */} {typeof document !== 'undefined' && createPortal(renderCard(), document.body)} ) } export default ButtonWithHoverCard