Hover card
Um card de prévia que abre quando um link recebe hover ou foco, para conteúdo que usuários que enxergam podem conferir rapidamente.
pnpm dlx shadcn@latest add https://hextaui.com/r/hover-card.jsonAdiciona o componente, os tokens de tema do HextaUI e quaisquer componentes do HextaUI dos quais ele depende.
Adicione os tokens de tema ao seu CSS global, se ainda não o fez.
Instale as dependências.
pnpm add @base-ui/react cnCopie e cole o código a seguir no seu projeto.
components/ui/hover-card.tsx lib/motion.ts Atualize os caminhos de importação para corresponder à configuração do seu projeto.
Um hover card é uma prévia, não um menu nem um diálogo. O gatilho continua sendo um link normal, então tudo o que está no card também deve estar na página para a qual ele aponta.
Lado
Defina side e align em <HoverCardContent />. Lados lógicos como inline-end seguem a direção de leitura, e o card se inverte ou se desloca quando sairia da tela.
Atraso
delay e closeDelay no gatilho definem por quanto tempo o ponteiro deve parar antes de o card abrir e quanto ele permanece depois de o ponteiro sair. O padrão de 600ms evita que os cards pisquem abertos quando o ponteiro atravessa uma página.
Link inline
Use render para fazer do gatilho qualquer link, inclusive um dentro de uma frase. Quando um link quebra em duas linhas, o card se ancora na linha sobre a qual você passou o mouse.
Conteúdo interativo
Mova o ponteiro do link para o card e ele permanece aberto, para que links e botões dentro dele possam ser clicados. O caminho entre eles é tolerante, então um movimento diagonal não o fecha.
Card compartilhado
Um card atende vários links. Crie um handle com createHoverCardHandle, dê a cada gatilho um payload e leia-o no card. Mover-se entre nomes faz o card deslizar até o novo link em vez de fechar e reabrir. O conteúdo antigo sai deslizando no sentido do seu movimento, o novo entra deslizando, e a altura se ajusta suavemente entre os dois.
Seta
arrow adiciona uma seta que se une à borda do card sem emenda. O deslocamento lateral aumenta para abrir espaço para ela, e ela acompanha o card quando ele se inverte.
Carregando conteúdo
Comece a buscar em onOpenChange e mostre um skeleton até os dados chegarem. Quando o conteúdo muda, o card se ajusta suavemente à nova altura em vez de saltar.
Controlado
Passe open e onOpenChange. O segundo argumento diz por que mudou, como trigger-hover, trigger-focus ou escape-key.
Conteúdo longo
Texto sem quebra é quebrado dentro do card, e um card mais alto que o espaço ao lado do gatilho rola em vez de sair da tela.
Da direita para a esquerda
O card lê a direção do gatilho, então os lados lógicos e o alinhamento se invertem e a animação de escala cresce a partir do canto correto.
| Tecla | Ação |
|---|---|
| Tab | Focar o gatilho abre o card após o mesmo atraso do hover. Mover o foco adiante o fecha. |
| Enter | Segue o link, como qualquer outro link. |
| Esc | Fecha o card. |
- O card é um extra visual para usuários videntes de mouse e teclado. Os leitores de tela ouvem apenas o link, para não serem forçados a passar por uma prévia em cada link.
- Nada abre em telas sensíveis ao toque, onde não há hover. Um toque segue o link, e por isso o destino precisa conter as mesmas informações.
- O foco nunca entra no card. Se ele precisar de controles alcançáveis pelo teclado, use um popover.
- Com movimento reduzido ativado, o card aparece com fade, sem escala, e um card compartilhado salta entre os links em vez de deslizar.
Construído sobre o preview card do Base UI. Cada parte aceita as props da primitiva que envolve.
| Prop | Tipo | Padrão |
|---|---|---|
open | boolean | – |
defaultOpen | boolean | false |
onOpenChangedetails.reason é trigger-hover, trigger-focus, trigger-press, outside-press, escape-key, imperative-action ou none. | (open: boolean, details) => void | – |
onOpenChangeCompleteChamado após o fim da animação de abertura ou fechamento. | (open: boolean) => void | – |
handleConecta gatilhos renderizados fora da raiz. | HoverCardHandle<Payload> | – |
childrenUse a forma de função para ler o payload do gatilho que abriu o card. | ReactNode | ({ payload }) => ReactNode | – |
actionsRef | RefObject<{ close, unmount }> | – |
| Prop | Tipo | Padrão |
|---|---|---|
href | string | – |
delayMilissegundos antes de o hover ou o foco abrir o card. | number | 600 |
closeDelayMilissegundos que o card permanece aberto depois de o ponteiro sair. | number | 300 |
handle | HoverCardHandle<Payload> | – |
payloadRepassado ao card quando este gatilho o abre. | Payload | – |
renderRenderize seu próprio link, como <Button variant="link" /> ou um link do router. | ReactElement | (props, state) => ReactElement | <a> |
| Atributo | Descrição |
|---|---|
data-slot="hover-card-trigger" | Selecione o gatilho no CSS. |
data-popup-open | Presente enquanto o card deste gatilho está aberto. |
| Prop | Tipo | Padrão |
|---|---|---|
side | "top" | "bottom" | "left" | "right" | "inline-start" | "inline-end" | "bottom" |
align | "start" | "center" | "end" | "center" |
arrowMostra uma seta apontando para o gatilho. | boolean | false |
sideOffset | number | OffsetFunction | 6, or 10 with arrow |
alignOffset | number | OffsetFunction | 0 |
collisionPaddingEspaço mantido entre o card e a borda do viewport. | number | Rect | 8 |
collisionAvoidanceSe o card se inverte, se desloca ou não faz nada em uma colisão. | CollisionAvoidance | – |
sticky | boolean | false |
anchorPosiciona em relação a algo diferente do gatilho. | Element | RefObject | VirtualElement | – |
positionMethod | "absolute" | "fixed" | "absolute" |
disableAnchorTracking | boolean | false |
portalPropsProps do portal, como container. | HoverCardPortalProps | – |
render | ReactElement | (props, state) => ReactElement | <div> |
| Atributo | Descrição |
|---|---|
data-slot="hover-card-content" | Selecione o card no CSS. |
data-open | Presente enquanto o card está aberto. |
data-starting-style | Presente enquanto o card anima a entrada. |
data-ending-style | Presente enquanto o card anima a saída. |
data-instant | focus quando o foco do teclado abriu o card, dismiss quando Escape ou um clique fora o fechou. A animação de saída é ignorada enquanto estiver definido. |
data-side | O lado em que o card se fixou após as colisões. |
data-align | O alinhamento em que ele se fixou. |
--transform-origin | De onde a animação de escala cresce, ao lado do gatilho. |
--available-width | Espaço restante ao lado do gatilho. O card nunca cresce além dele. |
--available-height | Espaço restante acima ou abaixo. Conteúdo mais alto rola. |
| Atributo do positioner | Descrição |
|---|---|
data-slot="hover-card-positioner" | O elemento que se move. Ele desliza quando um card compartilhado troca de link. |
data-anchor-hidden | Presente quando o gatilho sai da vista por rolagem. |
| Partes internas | Descrição |
|---|---|
data-slot="hover-card-viewport" | Envolve o conteúdo. Carrega data-activation-direction enquanto um card compartilhado troca de link. |
data-slot="hover-card-body" | Seu conteúdo. A altura se ajusta suavemente quando ele muda. |
data-slot="hover-card-arrow" | A seta, com data-side para sua borda. |
--popup-height | Definido no card enquanto ele se redimensiona entre links. |
| Prop | Tipo | Padrão |
|---|---|---|
container | HTMLElement | ShadowRoot | RefObject | null | document.body |
keepMounted | boolean | false |
Retorna um handle para gatilhos desanexados. Seus métodos open(triggerId) e close() controlam o card a partir de event handlers, e isOpen lê seu estado. Passe um argumento de tipo para tipar o payload.
- MotionAs curvas de easing, as durações e a verificação de movimento reduzido com que todo componente anima, além de hooks para transformações de tamanho e destaques deslizantes.
- Alert dialogUm diálogo de confirmação para ações destrutivas ou importantes que aguarda trabalho assíncrono e vira um bottom sheet no celular.
- CommandUma lista pesquisável de ações, inline ou como paleta ⌘K, com páginas, atalhos e correspondências destacadas.
- Context menuUm menu de ações ao clicar com o botão direito ou pressionar e segurar, com submenus, itens de checkbox e de rádio e feedback de pressão no toque.
- DialogUma janela sobre a página para formulários e tarefas focadas, com cabeçalho e rodapé fixos, aninhamento e um bottom sheet com deslize no celular.
- DrawerUm painel que desliza a partir de qualquer borda e acompanha o seu dedo, com pontos de ancoragem, uma alça funcional e drawers aninhados que se empilham.
Usado em blocos
Blocos que se baseiam em Hover card.
- Chat SidebarA barra lateral de um app de chat. Logo, busca e Novo chat no topo, seus próprios links abaixo, chats fixados, projetos que se expandem para mostrar seus chats, recentes agrupados por dia e linhas com menus de hover e de clique direito, renomeação inline, exclusão com desfazer e estados de resposta ao vivo.
- ThinkingMostre o que um modelo está fazendo enquanto trabalha. Um orbe de shader e um rótulo ao vivo que acompanha cada etapa, uma trilha recolhível de buscas, chips de fonte e raciocínio, e depois uma resposta com citações bem ao lado das afirmações que sustentam.