HoverCard
<script setup lang="ts">
import { ref } from 'vue'
import { HoverCardArrow, HoverCardContent, HoverCardPortal, HoverCardRoot, HoverCardTrigger } from 'radix-vue'
const hoverState = ref(false)
</script>
<template>
<HoverCardRoot v-model:open="hoverState">
<HoverCardTrigger
class="inline-block cursor-pointer rounded-full shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] outline-none focus:shadow-[0_0_0_2px_white]"
href="https://twitter.com/radix_ui"
target="_blank"
rel="noreferrer noopener"
>
<img
class="block h-[45px] w-[45px] rounded-full"
src="https://pbs.twimg.com/profile_images/1337055608613253126/r_eiMp2H_400x400.png"
alt="Radix UI"
>
</HoverCardTrigger>
<HoverCardPortal>
<HoverCardContent
class="data-[side=bottom]:animate-slideUpAndFade data-[side=right]:animate-slideLeftAndFade data-[side=left]:animate-slideRightAndFade data-[side=top]:animate-slideDownAndFade w-[300px] rounded-md bg-white p-5 shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] data-[state=open]:transition-all"
:side-offset="5"
>
<div class="flex flex-col gap-[7px]">
<img
class="block h-[60px] w-[60px] rounded-full"
src="https://pbs.twimg.com/profile_images/1337055608613253126/r_eiMp2H_400x400.png"
alt="Radix UI"
>
<div class="flex flex-col gap-[15px]">
<div>
<div class="text-mauve12 m-0 text-[15px] font-medium leading-[1.5]">
Radix
</div>
<div class="text-mauve10 m-0 text-[15px] leading-[1.5]">
@radix_ui
</div>
</div>
<div class="text-mauve12 m-0 text-[15px] leading-[1.5]">
Components, icons, colors, and templates for building high-quality, accessible UI. Free and open-source.
</div>
<div class="flex gap-[15px]">
<div class="flex gap-[5px]">
<div class="text-mauve12 m-0 text-[15px] font-medium leading-[1.5]">
0
</div>
<div class="text-mauve10 m-0 text-[15px] leading-[1.5]">
Following
</div>
</div>
<div class="flex gap-[5px]">
<div class="text-mauve12 m-0 text-[15px] font-medium leading-[1.5]">
2,900
</div>
<div class="text-mauve10 m-0 text-[15px] leading-[1.5]">
Followers
</div>
</div>
</div>
</div>
</div>
<HoverCardArrow
class="fill-white"
:width="8"
/>
</HoverCardContent>
</HoverCardPortal>
</HoverCardRoot>
</template>
功能
- 可以是受控的或不受控的。
- 自定义侧面、对齐方式、偏移量、碰撞处理。
- 可以选择渲染一个指向箭头。
- 支持自定义打开和关闭延迟。
- 被屏幕阅读器忽略。
安装
从命令行安装组件。
$ npm add radix-vue
解剖
导入所有部分并将其组合在一起。
<script setup>
import { HoverCardArrow, HoverCardContent, HoverCardPortal, HoverCardRoot, HoverCardTrigger } from 'radix-vue'
</script>
<template>
<HoverCardRoot>
<HoverCardTrigger />
<HoverCardPortal>
<HoverCardContent>
<HoverCardArrow />
</HoverCardContent>
</HoverCardPortal>
</HoverCardRoot>
</template>
API 参考
根
包含悬停卡的所有部分。
道具 | 默认 | 类型 |
---|---|---|
closeDelay | 300 | 数字 鼠标离开触发器或内容到悬停卡关闭的持续时间。 |
defaultOpen | 假 | 假 悬停卡首次渲染时的打开状态。当您不需要控制其打开状态时使用。 |
打开 | 布尔值 悬停卡的受控打开状态。可以绑定为 | |
openDelay | 700 | 数字 鼠标进入触发器到悬停卡打开的持续时间。 |
发射 | 有效负载 |
---|---|
update:open | [value: 布尔值] 悬停卡打开状态改变时调用的事件处理程序。 |
插槽 (默认) | 有效负载 |
---|---|
打开 | 布尔值 当前打开状态 |
触发器
悬停时打开悬停卡的链接。
道具 | 默认 | 类型 |
---|---|---|
作为 | 'a' | AsTag | 组件 此组件应呈现的元素或组件。可以被 |
asChild | 布尔值 更改默认渲染的元素,用于作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 |
数据属性 | 价值 |
---|---|
[data-state] | "open" | "closed" |
门户
使用时,将内容部分传送到 body
中。
道具 | 默认 | 类型 |
---|---|---|
禁用 | 布尔值 禁用传送并内联渲染组件 | |
forceMount | 布尔值 用于在需要更多控制时强制挂载。在使用 Vue 动画库控制动画时很有用。 | |
到 | 字符串 | HTMLElement Vue 原生传送组件属性 |
内容
悬停卡打开时弹出的组件。
道具 | 默认 | 类型 |
---|---|---|
对齐 | 'start' | 'center' | 'end' 相对于触发器的首选对齐方式。当发生碰撞时可能会改变。 | |
alignOffset | 数字 从 | |
arrowPadding | 数字 箭头与内容边缘之间的填充。如果您的内容有圆角,这将防止它溢出角。 | |
作为 | 'div' | AsTag | 组件 此组件应呈现的元素或组件。可以被 |
asChild | 布尔值 更改默认渲染的元素,用于作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 | |
avoidCollisions | 布尔值 当 | |
collisionBoundary | 元素 | (元素 | 空)[] | 空 用作碰撞边界的元素。默认情况下,这是视窗,但您可以提供要包含在此检查中的其他元素。 | |
collisionPadding | 数字 | 部分<记录<'top' | 'right' | 'bottom' | 'left', 数字>> 从边界边缘开始发生碰撞检测的像素距离。接受一个数字(所有边的数字相同),或一个部分填充对象,例如:{ top: 20, left: 20 }。 | |
forceMount | 布尔值 用于在需要更多控制时强制挂载。在使用 Vue 动画库控制动画时很有用。 | |
hideWhenDetached | 布尔值 当触发器被完全遮挡时是否隐藏内容。 | |
prioritizePosition | 布尔值 强制内容在视窗内定位。 可能会与参考元素重叠,这可能不是您想要的。 | |
侧 | 'top' | 'right' | 'bottom' | 'left' 打开时渲染的触发器的首选侧面。当发生碰撞并且 avoidCollisions 启用时,将被反转。 | |
sideOffset | 数字 与触发器的像素距离。 | |
粘性 | 'partial' | 'always' 对齐轴上的粘性行为。 | |
updatePositionStrategy | 'always' | 'optimized' 在每个动画帧上更新浮动元素位置的策略。 |
发射 | 有效负载 |
---|---|
escapeKeyDown | [event: KeyboardEvent] 按下 Escape 键时调用的事件处理程序。可以防止。 |
focusOutside | [event: FocusOutsideEvent] 焦点移出 |
interactOutside | [event: PointerDownOutsideEvent | FocusOutsideEvent] 在 |
pointerDownOutside | [event: PointerDownOutsideEvent] 在 |
数据属性 | 价值 |
---|---|
[data-state] | "open" | "closed" |
[data-side] | "left" | "right" | "bottom" | "top" |
[data-align] | "start" | "end" | "center" |
CSS 变量 | 描述 |
---|---|
--radix-hover-card-content-transform-origin | 从内容和箭头位置/偏移量计算出的 transform-origin |
--radix-hover-card-content-available-width | 触发器与边界边缘之间的剩余宽度 |
--radix-hover-card-content-available-height | 触发器与边界边缘之间的剩余高度 |
--radix-hover-card-trigger-width | 触发器的宽度 |
--radix-hover-card-trigger-height | 触发器的高度 |
箭头
一个可选的箭头元素,与悬停卡一起渲染。这可用于在视觉上帮助将触发器与 HoverCardContent
链接起来。必须渲染在 HoverCardContent
内。
道具 | 默认 | 类型 |
---|---|---|
作为 | 'svg' | AsTag | 组件 此组件应呈现的元素或组件。可以被 |
asChild | 布尔值 更改默认渲染的元素,用于作为子元素传递的元素,合并其属性和行为。 阅读我们的 组合 指南了解更多详细信息。 | |
高度 | 5 | 数字 箭头的像素高度。 |
宽度 | 10 | 数字 箭头的像素宽度。 |
示例
立即显示
使用 openDelay
属性控制悬停卡打开所需的时间。
<script setup>
import {
HoverCardArrow,
HoverCardContent,
HoverCardPortal,
HoverCardRoot,
HoverCardTrigger,
} from 'radix-vue'
</script>
<template>
<HoverCardRoot :open-delay="0">
<HoverCardTrigger>…</HoverCardTrigger>
<HoverCardContent>…</HoverCardContent>
</HoverCardRoot>
</template>
约束内容大小
您可能希望约束内容的宽度,使其与触发器的宽度匹配。您可能还想约束其高度,使其不超过视窗高度。
我们公开了几个 CSS 自定义属性,例如 --radix-hover-card-trigger-width
和 --radix-hover-card-content-available-height
来支持这一点。使用它们来约束内容尺寸。
// index.vue
<script setup>
import { HoverCardArrow, HoverCardContent, HoverCardPortal, HoverCardRoot, HoverCardTrigger } from 'radix-vue'
</script>
<template>
<HoverCardRoot>
<HoverCardTrigger>…</HoverCardTrigger>
<HoverCardPortal>
<HoverCardContent
class="HoverCardContent"
:side-offset="5"
>
…
</HoverCardContent>
</HoverCardPortal>
</HoverCardRoot>
</template>
/* styles.css */
.HoverCardContent {
width: var(--radix-hover-card-trigger-width);
max-height: var(--radix-hover-card-content-available-height);
}
原点感知动画
我们公开了一个 CSS 自定义属性 --radix-hover-card-content-transform-origin
。使用它根据 side
、sideOffset
、align
、alignOffset
和任何碰撞从其计算的原点对内容进行动画处理。
// index.vue
<script setup>
import { HoverCardArrow, HoverCardContent, HoverCardPortal, HoverCardRoot, HoverCardTrigger } from 'radix-vue'
</script>
<template>
<HoverCardRoot>
<HoverCardTrigger>…</HoverCardTrigger>
<HoverCardContent class="HoverCardContent">
…
</HoverCardContent>
</HoverCardRoot>
</template>
/* styles.css */
.HoverCardContent {
transform-origin: var(--radix-hover-card-content-transform-origin);
animation: scaleIn 0.5s ease-out;
}
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0);
}
to {
opacity: 1;
transform: scale(1);
}
}
碰撞感知动画
我们公开了 data-side
和 data-align
属性。它们的值将在运行时更改以反映碰撞。使用它们创建碰撞和方向感知动画。
// index.vue
<script setup>
import { HoverCardArrow, HoverCardContent, HoverCardPortal, HoverCardRoot, HoverCardTrigger } from 'radix-vue'
</script>
<template>
<HoverCardRoot>
<HoverCardTrigger>…</HoverCardTrigger>
<HoverCardContent class="HoverCardContent">
…
</HoverCardContent>
</HoverCardRoot>
</template>
/* styles.css */
.HoverCardContent {
animation-duration: 0.6s;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.HoverCardContent[data-side="top"] {
animation-name: slideUp;
}
.HoverCardContent[data-side="bottom"] {
animation-name: slideDown;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
无障碍性
悬停卡仅供视力正常的用户使用,键盘用户将无法访问内容。
键盘交互
键 | 描述 |
---|---|
Tab | 打开/关闭悬停卡。 |
Enter | 打开悬停卡链接 |