Hover Card 悬浮卡片

基于 BrConfigProvider 实现全局主题配置,支持自适应定位、懒渲染和键盘导航的企业级悬浮卡片组件,可无缝集成 BrTableBrList 等组件。

组件特性

  • 🎯 自适应定位:智能计算空间,支持自动避障和多方向(上/下/左/右)弹出。
  • 无缝集成:可与 BrTableBrListBrAvatar 等组件完美组合,处理复杂交互。
  • 🎨 主题定制:基于 BrConfigProvider 实现全局定制,支持 TailwindCSS 局部覆写。
  • ⌨️ 可访问性:内置键盘导航(Tab 切换、ESC 关闭)、延迟控制,避免误触。
  • 📦 多实例管理:自带 HoverCardManager 提供全局 z-index 层级自动递增。

基础使用

最基础的悬浮卡片,鼠标悬浮在触发元素上时显示。

<script setup lang="ts">
import { BrHoverCard, BrHoverCardTrigger, BrHoverCardContent, BrButton } from '@breezeui/vue'
</script>

<template>
  <BrHoverCard>
    <BrHoverCardTrigger as-child>
      <BrButton variant="link">Hover me</BrButton>
    </BrHoverCardTrigger>
    <BrHoverCardContent class="w-80">
      <div class="flex justify-between space-x-4">
        <div class="space-y-1">
          <h4 class="text-sm font-semibold">BreezeUI</h4>
          <p class="text-sm">
            An enterprise-class UI components based on Vue3, TailwindCSS and Radix Vue.
          </p>
        </div>
      </div>
    </BrHoverCardContent>
  </BrHoverCard>
</template>

与头像 (Avatar) 集成

常用于用户信息展示的场景,在头像上悬浮以显示用户的详细信息。

<script setup lang="ts">
import { BrHoverCard, BrHoverCardTrigger, BrHoverCardContent, BrAvatar, BrAvatarImage, BrAvatarFallback } from '@breezeui/vue'
import { CalendarDays } from 'lucide-vue-next'
</script>

<template>
  <BrHoverCard>
    <BrHoverCardTrigger as-child>
      <BrAvatar class="cursor-pointer">
        <BrAvatarImage src="https://github.com/vuejs.png" alt="@vuejs" />
        <BrAvatarFallback>VU</BrAvatarFallback>
      </BrAvatar>
    </BrHoverCardTrigger>
    <BrHoverCardContent class="w-80">
      <div class="flex justify-between space-x-4">
        <BrAvatar>
          <BrAvatarImage src="https://github.com/vuejs.png" />
          <BrAvatarFallback>VU</BrAvatarFallback>
        </BrAvatar>
        <div class="space-y-1">
          <h4 class="text-sm font-semibold">@vuejs</h4>
          <p class="text-sm">
            The Progressive JavaScript Framework.
          </p>
          <div class="flex items-center pt-2">
            <CalendarDays class="mr-2 h-4 w-4 opacity-70" />
            <span class="text-xs text-muted-foreground">
              Joined December 2013
            </span>
          </div>
        </div>
      </div>
    </BrHoverCardContent>
  </BrHoverCard>
</template>

与表格 (Table) 集成

在表格行悬浮时展示更多扩展信息或操作表单。

<script setup lang="ts">
import { 
  BrHoverCard, BrHoverCardTrigger, BrHoverCardContent,
  BrTable, BrTableHeader, BrTableRow, BrTableHead, BrTableBody, BrTableCell,
  BrBadge 
} from '@breezeui/vue'

const invoices = [
  { invoice: "INV001", paymentStatus: "Paid", totalAmount: "$250.00", paymentMethod: "Credit Card" },
  { invoice: "INV002", paymentStatus: "Pending", totalAmount: "$150.00", paymentMethod: "PayPal" },
]

const columns = [
  { title: 'Invoice', key: 'invoice', width: 100 },
  { title: 'Status', key: 'paymentStatus' },
  { title: 'Method', key: 'paymentMethod' },
  { title: 'Amount', key: 'totalAmount', align: 'right' }
]
</script>

<template>
  <BrTable :columns="columns" :data="invoices">
    <template #cell-invoice="{ row }">
      <span class="font-medium">
        <BrHoverCard>
          <BrHoverCardTrigger>
            <span class="cursor-help underline underline-offset-4">
              {{ row.invoice }}
            </span>
          </BrHoverCardTrigger>
          <BrHoverCardContent class="w-64">
            <div class="space-y-2">
              <h4 class="font-medium leading-none">Invoice Details</h4>
              <p class="text-sm text-muted-foreground">
                Transaction details for {{ row.invoice }} via {{ row.paymentMethod }}.
              </p>
            </div>
          </BrHoverCardContent>
        </BrHoverCard>
      </span>
    </template>
    <template #cell-paymentStatus="{ row }">
      <BrBadge :variant="row.paymentStatus === 'Paid' ? 'default' : 'secondary'">
        {{ row.paymentStatus }}
      </BrBadge>
    </template>
  </BrTable>
</template>

表单交互 (键盘导航支持)

悬浮卡片内置了焦点管理功能,通过 Tab 键可直接切换到卡片内的输入框进行交互,并支持通过 ESC 键快捷关闭卡片。

<script setup lang="ts">
import { 
  BrHoverCard, BrHoverCardTrigger, BrHoverCardContent,
  BrButton, BrInput, BrLabel, BrFormItem
} from '@breezeui/vue'
</script>

<template>
  <div class="flex justify-center p-12">
    <BrHoverCard>
      <BrHoverCardTrigger as-child>
        <BrButton variant="secondary">Hover to open quick form</BrButton>
      </BrHoverCardTrigger>
      <BrHoverCardContent class="w-80">
        <div class="space-y-4">
          <div class="space-y-2">
            <h4 class="font-medium leading-none">Quick Note</h4>
            <p class="text-sm text-muted-foreground">Via Tab key to switch directly to input</p>
          </div>
          <BrFormItem>
            <BrLabel>Tag</BrLabel>
            <BrInput placeholder="Enter customer tag..." />
          </BrFormItem>
        </div>
      </BrHoverCardContent>
    </BrHoverCard>
  </div>
</template>

主题定制

支持使用 BrConfigProvider 对 HoverCard 进行全局配置,或者使用 TailwindCSS 实现局部样式隔离定制。

<script setup lang="ts">
import { BrConfigProvider, BrHoverCard, BrHoverCardTrigger, BrHoverCardContent, BrButton } from '@breezeui/vue'
</script>

<template>
  <BrConfigProvider 
    :theme="{ 
      variables: { 
        '--radius': '1rem',
        '--popover': '220 10% 95%'
      } 
    }"
  >
    <div class="p-6">
      <BrHoverCard>
        <BrHoverCardTrigger as-child>
          <BrButton>Custom HoverCard</BrButton>
        </BrHoverCardTrigger>
        <BrHoverCardContent 
          :isolated="true" 
          class="w-80 border-2 border-primary bg-primary/10 shadow-xl"
        >
          <div class="text-primary-foreground font-medium">
            Flexible customization in light and dark modes.
          </div>
        </BrHoverCardContent>
      </BrHoverCard>
    </div>
  </BrConfigProvider>
</template>

API 说明

BrHoverCard

参数类型默认值说明
defaultOpenbooleanfalse初始状态下是否打开
openbooleanfalse受控的打开状态
openDelaynumber700触发打开的延迟时间(毫秒),避免误触
closeDelaynumber300触发关闭的延迟时间(毫秒)
@update:open(value: boolean) => void-打开状态改变时的回调

BrHoverCardTrigger

包含子元素的包装器,默认使用 asChild

BrHoverCardContent

参数类型默认值说明
placement'top' | 'bottom' | 'left' | 'right' | 'top-start' 等 12 种'bottom'悬浮卡片相对触发器的位置
sideOffsetnumber4悬浮卡片距离触发器的偏移量
loadingbooleanfalse是否显示加载态占位
emptybooleanfalse是否显示空数据占位
zIndexnumber自动递增卡片的 z-index 层级,默认通过 HoverCardManager 自动管理
isolatedbooleanfalse是否开启样式隔离类,避免全局样式污染

HoverCardManager

静态管理类,用于管理悬浮卡片的全局状态和层级。

方法返回类型说明
nextZIndex()number获取下一个自增的 z-index,用于处理多实例嵌套层级