HoverCard
A card that opens when the pointer rests on something and holds a preview of what is on the other side of it: a person behind a mention, a repository behind a link, a deploy behind an id.
import { HoverCard, TextLink } from 'neba';
<HoverCard trigger={<TextLink href="/people/nadiarowan">@nadiarowan</TextLink>} title="Nadia Rowan">
Maintainer · 214 commits
</HoverCard>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
| trigger * | ReactElement | — | What the card hangs off. One element that accepts a ref and spreads props; the card merges onto it rather than wrapping it |
| title | ReactNode | — | The heading |
| description | ReactNode | — | A line under the title |
| children | ReactNode | — | The body |
| sizeshared | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | The type scale, the padding, and how wide the card may get |
| colorshared | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'primary' | Semantic colour role. The sheet is never dyed, so it reaches the edge |
| densityshared | 'default' | 'compact' | 'default' | Changes the card's inset and nothing else |
| sideshared | 'top' | 'right' | 'bottom' | 'left' | 'bottom' | Which edge of the trigger it appears on. Flips when there is no room |
| alignshared | 'start' | 'center' | 'end' | 'center' | Where it sits along that edge |
| sideOffset | number | 6 | Distance from the trigger, in pixels |
| alignOffset | number | 0 | Shift along that edge, in pixels |
| arrow | boolean | false | Draws the wedge pointing at the trigger. Off by default: a translucent sheet's wedge cannot carry the blurred backdrop with it |
| open | boolean | — | Whether the card is open. With onOpenChange it makes it controlled |
| defaultOpen | boolean | — | Whether it starts open, uncontrolled |
| onOpenChange | (open: boolean) => void | — | Fired whenever it opens or closes |
| delay | number | — | How long the pointer has to rest on the trigger before the card opens, in milliseconds |
| closeDelay | number | — | How long the card stays after the pointer has left, in milliseconds. This is what makes the gap crossable |
| width | number | string | — | A hard cap on the width, overriding the one size implies. Numbers are pixels |
Every native <div> attribute passes through to the popup, apart from color, title and children, which the component owns. There is no variant and no elevation, for the reason Popover has neither: a surface that had to be hovered has already asserted itself, and a card that floats over the page cannot be sat flat.
It sits between the library's other two popups. A Tooltip is a label: one line, and the pointer never reaches it. A Popover was asked for by a press, so it can hold a form. This one is uninvited like a tooltip and reachable like a popover: the pointer can cross into it and a link inside it can be followed.
Examples
trigger
The trigger is an element rather than children, and the card merges onto it: no wrapper, so the layout is unchanged and a link stays a link. Usually a TextLink or an Avatar.
delay · closeDelay
delay is how long the pointer has to rest before the card opens, and closeDelay how long it stays after the pointer leaves: which is what makes the gap between the trigger and the card crossable.
side · align · arrow
side is the edge of the trigger the card appears on, flipping when there is no room; align is where it sits along that edge. arrow draws the wedge, and is off by default because a translucent sheet's wedge cannot carry the blurred backdrop with it.
size
size sets the type scale, the inset and how wide the card is allowed to get. width overrides the last of those on its own.
Accessibility
- Whatever is in the card must also exist on the page the trigger leads to. A keyboard with no hover, a touchscreen with no pointer, and a screen reader all arrive by that route instead, so this can never be the only way to something.
- The card is reachable with the pointer, so a link inside it can be followed; it stays open while the pointer is in it.
- Escape closes it.