react ~5 KB 0 deps v0.1.0 โ†— GitHub โ†—

@mshafiqyajid/react-hover-card

Headless hover card hook and styled component. Mouse and keyboard triggered, smart auto-placement, open/close delay timers, portal positioning, arrow, flip + shift, dark mode, reduced-motion safe.

Playground #

Props
TSX
import { HoverCardStyled } from "@mshafiqyajid/react-hover-card/styled";
import "@mshafiqyajid/react-hover-card/styles.css";

<HoverCardStyled
  content="Hover card content"
/>

Install #

npm install @mshafiqyajid/react-hover-card

Quick start #

import { HoverCardStyled } from "@mshafiqyajid/react-hover-card/styled";
import "@mshafiqyajid/react-hover-card/styles.css";

<HoverCardStyled
  content={
    <div>
      <strong>@username</strong>
      <p>Joined January 2024 ยท 120 followers</p>
    </div>
  }
  openDelay={300}
  placement="auto"
>
  <a href="/profile">@username</a>
</HoverCardStyled>

Headless #

import { useHoverCard } from "@mshafiqyajid/react-hover-card";

const { triggerProps, cardProps, isOpen, open, close } = useHoverCard({
  openDelay: 300,
  closeDelay: 100,
  onOpenChange: (open) => console.log("open:", open),
});

return (
  <>
    <a href="/profile" {...triggerProps}>@username</a>
    {isOpen && (
      <div {...cardProps} className="my-card">
        <p>Rich content here</p>
      </div>
    )}
  </>
);

The hook handles open/close timers, keyboard (Escape), and ARIA. Position the card with your own layout or portal solution.

API โ€” HoverCardStyled #

PropTypeDefaultDescription
contentReactNodeโ€”Card body content
childrenReactElementโ€”The trigger element
openDelaynumber300ms before opening on hover/focus
closeDelaynumber100ms before closing after mouse-leave/blur
placement"auto" | "top" | "bottom" | "left" | "right" (each with optional -start / -end)"auto"Preferred placement; auto picks the side with most room
offsetnumber8Gap in px between trigger and card
collisionPaddingnumber8Viewport edge margin for flip/shift
flipbooleantrueAuto-flip to opposite side near edges
shiftbooleantruePush back into view along cross-axis
arrowbooleantrueShow arrow pointing to trigger
strategy"absolute" | "fixed""absolute"Positioning strategy
openbooleanโ€”Controlled open state
defaultOpenbooleanfalseInitial open state (uncontrolled)
onOpenChange(open: boolean) => voidโ€”Callback when open state changes
classNamestringโ€”Extra class on the card element
styleReact.CSSPropertiesโ€”Inline styles on the card element

API โ€” useHoverCard #

OptionTypeDefaultDescription
openDelaynumber300ms before opening
closeDelaynumber100ms before closing
openbooleanโ€”Controlled open state
defaultOpenbooleanfalseInitial open state (uncontrolled)
onOpenChange(open: boolean) => voidโ€”Callback on open state change

Returns: triggerProps, cardProps, isOpen, open(), close()

CSS variables #

VariableDefaultDescription
--rhc-bg#ffffffCard background
--rhc-fg#18181bCard text color
--rhc-border#e4e4e7Card border color
--rhc-radius10pxCard border radius
--rhc-shadowโ€”Card box shadow
--rhc-duration-in180msOpen transition duration
--rhc-duration-out120msClose transition duration
--rhc-min-width220pxMinimum card width
--rhc-max-width360pxMaximum card width
--rhc-padding1remContent padding

data-placement #

The card's data-placement attribute reflects the resolved (post-flip) placement. Style side-specific arrow direction or radius by it.

Edit this page on GitHub