Hover card
Une carte d’aperçu qui s’ouvre au survol ou au focus d’un lien, pour un contenu que les personnes voyantes peuvent parcourir du regard.
pnpm dlx shadcn@latest add https://hextaui.com/r/hover-card.jsonAjoute le composant, les tokens de thème HextaUI et les composants HextaUI dont il dépend.
Ajoutez les tokens de thème à votre CSS global, si ce n’est pas déjà fait.
Installez les dépendances.
pnpm add @base-ui/react cnCopiez et collez le code suivant dans votre projet.
components/ui/hover-card.tsx lib/motion.ts Mettez à jour les chemins d’import selon la configuration de votre projet.
Une hover card est un aperçu, pas un menu ni une boîte de dialogue. Le déclencheur reste un lien normal : tout ce que contient la carte doit donc aussi se trouver sur la page vers laquelle il pointe.
Côté
Définissez side et align sur <HoverCardContent />. Les côtés logiques comme inline-end suivent le sens de lecture, et la carte se retourne ou se décale lorsqu’elle sortirait de l’écran.
Délai
delay et closeDelay sur le déclencheur définissent combien de temps le pointeur doit rester avant l’ouverture de la carte et combien de temps elle persiste après sa sortie. La valeur par défaut de 600 ms évite que les cartes ne s’ouvrent en un éclair quand le pointeur traverse une page.
Lien en ligne
Utilisez render pour faire du déclencheur n’importe quel lien, y compris un lien au milieu d’une phrase. Lorsqu’un lien passe sur deux lignes, la carte s’ancre à la ligne que vous avez survolée.
Contenu interactif
Déplacez le pointeur du lien vers la carte et elle reste ouverte : les liens et boutons à l’intérieur peuvent donc être cliqués. Le trajet entre les deux est tolérant, un déplacement en diagonale ne la ferme donc pas.
Carte partagée
Une seule carte sert de nombreux liens. Créez un handle avec createHoverCardHandle, donnez un payload à chaque déclencheur et lisez-le dans la carte. Passer d’un nom à l’autre fait glisser la carte vers le nouveau lien au lieu de la fermer puis de la rouvrir. L’ancien contenu sort dans le sens de votre déplacement, le nouveau entre, et la hauteur s’adapte entre les deux.
Flèche
arrow ajoute une pointe qui se raccorde à la bordure de la carte sans couture. Le décalage latéral augmente pour lui faire de la place, et elle suit la carte lorsqu’elle se retourne.
Contenu en chargement
Lancez la récupération dans onOpenChange et affichez un skeleton jusqu’à l’arrivée des données. Lorsque le contenu change, la carte s’adapte en douceur à sa nouvelle hauteur au lieu de sauter.
Contrôlé
Passez open et onOpenChange. Le deuxième argument indique pourquoi il a changé, par exemple trigger-hover, trigger-focus ou escape-key.
Contenu long
Le texte sans coupure passe à la ligne dans la carte, et une carte plus haute que l’espace à côté du déclencheur défile au lieu de sortir de l’écran.
De droite à gauche
La carte lit la direction du déclencheur : les côtés logiques et l’alignement s’inversent donc et l’animation d’agrandissement part du bon coin.
| Touche | Action |
|---|---|
| Tab | Donner le focus au déclencheur ouvre la carte après le même délai que le survol. Déplacer le focus la ferme. |
| Enter | Suit le lien, comme n’importe quel autre lien. |
| Esc | Ferme la carte. |
- La carte est un complément visuel pour les utilisateurs voyants à la souris et au clavier. Les lecteurs d’écran n’entendent que le lien : ils ne sont donc pas forcés de passer par un aperçu à chaque lien rencontré.
- Rien ne s’ouvre sur écran tactile, où il n’y a pas de survol. Un appui suit le lien, c’est pourquoi la destination doit contenir les mêmes informations.
- Le focus n’entre jamais dans la carte. Si elle a besoin de contrôles accessibles au clavier, utilisez plutôt un popover.
- Avec la réduction des animations, la carte apparaît en fondu sans changer d’échelle, et une carte partagée saute d’un lien à l’autre au lieu de glisser.
Construit sur la preview card de Base UI. Chaque partie accepte les props de la primitive qu’elle enveloppe.
| Prop | Type | Par défaut |
|---|---|---|
open | boolean | – |
defaultOpen | boolean | false |
onOpenChangedetails.reason vaut trigger-hover, trigger-focus, trigger-press, outside-press, escape-key, imperative-action ou none. | (open: boolean, details) => void | – |
onOpenChangeCompleteAppelé à la fin de l’animation d’ouverture ou de fermeture. | (open: boolean) => void | – |
handleRelie les déclencheurs rendus en dehors de la racine. | HoverCardHandle<Payload> | – |
childrenUtilisez la forme fonction pour lire le payload du déclencheur qui a ouvert la carte. | ReactNode | ({ payload }) => ReactNode | – |
actionsRef | RefObject<{ close, unmount }> | – |
| Prop | Type | Par défaut |
|---|---|---|
href | string | – |
delayMillisecondes avant que le survol ou le focus n’ouvre la carte. | number | 600 |
closeDelayMillisecondes pendant lesquelles la carte reste ouverte après la sortie. | number | 300 |
handle | HoverCardHandle<Payload> | – |
payloadTransmis à la carte lorsque ce déclencheur l’ouvre. | Payload | – |
renderRendez votre propre lien, comme <Button variant="link" /> ou un lien de routeur. | ReactElement | (props, state) => ReactElement | <a> |
| Attribut | Description |
|---|---|
data-slot="hover-card-trigger" | Ciblez le déclencheur en CSS. |
data-popup-open | Présent tant que la carte de ce déclencheur est ouverte. |
| Prop | Type | Par défaut |
|---|---|---|
side | "top" | "bottom" | "left" | "right" | "inline-start" | "inline-end" | "bottom" |
align | "start" | "center" | "end" | "center" |
arrowAffiche une pointe dirigée vers le déclencheur. | boolean | false |
sideOffset | number | OffsetFunction | 6, or 10 with arrow |
alignOffset | number | OffsetFunction | 0 |
collisionPaddingEspace conservé entre la carte et le bord du viewport. | number | Rect | 8 |
collisionAvoidanceIndique si la carte se retourne, se décale ou ne fait rien en cas de collision. | CollisionAvoidance | – |
sticky | boolean | false |
anchorSe positionne par rapport à autre chose que le déclencheur. | Element | RefObject | VirtualElement | – |
positionMethod | "absolute" | "fixed" | "absolute" |
disableAnchorTracking | boolean | false |
portalPropsProps du portail, comme container. | HoverCardPortalProps | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribut | Description |
|---|---|
data-slot="hover-card-content" | Ciblez la carte en CSS. |
data-open | Présent tant que la carte est ouverte. |
data-starting-style | Présent pendant l’animation d’entrée de la carte. |
data-ending-style | Présent pendant l’animation de sortie de la carte. |
data-instant | focus lorsque le focus clavier a ouvert la carte, dismiss lorsque Escape ou un appui à l’extérieur l’a fermée. L’animation de sortie est ignorée tant qu’il est défini. |
data-side | Le côté retenu par la carte après les collisions. |
data-align | L’alignement retenu. |
--transform-origin | Le point d’où part l’animation d’agrandissement, à côté du déclencheur. |
--available-width | Espace restant à côté du déclencheur. La carte ne le dépasse jamais. |
--available-height | Espace restant au-dessus ou en dessous. Un contenu plus haut défile. |
| Attribut du positionneur | Description |
|---|---|
data-slot="hover-card-positioner" | L’élément qui bouge. Il glisse lorsqu’une carte partagée change de lien. |
data-anchor-hidden | Présent lorsque le déclencheur sort de la vue par le défilement. |
| Parties internes | Description |
|---|---|
data-slot="hover-card-viewport" | Enveloppe le contenu. Porte data-activation-direction pendant qu’une carte partagée change de lien. |
data-slot="hover-card-body" | Votre contenu. Sa hauteur s’adapte en douceur lorsqu’il change. |
data-slot="hover-card-arrow" | La pointe, avec data-side pour son bord. |
--popup-height | Défini sur la carte pendant qu’elle se redimensionne entre les liens. |
| Prop | Type | Par défaut |
|---|---|---|
container | HTMLElement | ShadowRoot | RefObject | null | document.body |
keepMounted | boolean | false |
Retourne un handle pour les déclencheurs détachés. Ses méthodes open(triggerId) et close() contrôlent la carte depuis des gestionnaires d’événements, et isOpen lit son état. Passez un argument de type pour typer le payload.
- MotionLes courbes d’easing, les durées et la vérification de réduction des animations utilisées par chaque composant, ainsi que des hooks pour les morphs de taille et les surlignages glissants.
- Alert dialogUne boîte de dialogue de confirmation pour les actions destructrices ou importantes, qui attend le travail asynchrone et devient une bottom sheet sur mobile.
- CommandUne liste d’actions recherchable, intégrée ou en palette ⌘K, avec pages, raccourcis et correspondances surlignées.
- Context menuUn menu d’actions au clic droit ou à l’appui long, avec sous-menus, éléments case à cocher et radio, et retour visuel de maintien au toucher.
- DialogUne fenêtre au-dessus de la page pour les formulaires et les tâches ciblées, avec en-tête et pied de page épinglés, imbrication, et une bottom sheet balayable sur mobile.
- DrawerUn panneau qui glisse depuis n’importe quel bord et suit votre doigt, avec des points d’accroche, une poignée fonctionnelle et des drawers imbriqués qui s’empilent.
Utilisé dans les blocks
Des blocks qui s’appuient sur Hover card.
- Chat SidebarLa barre latérale d’une application de chat. Logo, recherche et Nouveau chat en haut, vos propres liens en dessous, chats épinglés, projets qui se déploient pour montrer leurs chats, récents regroupés par jour, et des lignes avec menus au survol et au clic droit, renommage en ligne, suppression avec annulation et états de réponse en direct.
- ThinkingMontrez ce que fait un modèle pendant qu’il travaille. Une orbe en shader et un libellé en direct qui suit chaque étape, une trace repliable de recherches, de chips de sources et de raisonnements, puis une réponse avec des citations juste à côté des affirmations qu’elles étayent.