v2Placement, collision handling, and portals

Popovers for highlighted text

A headless React component that shows a popover when people select text. You write the popover. The component decides when to show it, where to place it, and when to hide it.

Get started
npm i @omsimos/react-highlight-popover

Select any text on this page to try it

Playground

Try the options

Select text in the box, then change the options. The code below updates to match.

Typography is what language looks like. Select a few words here, then change the options to see where the popover goes.

Placement
Alignment
8px
import { HighlightPopover } from "@omsimos/react-highlight-popover";const renderPopover = ({ selection }) => (  <div className="rounded-lg border bg-white p-3 shadow-lg">    {selection}  </div>);export function Article() {  return (    <HighlightPopover      renderPopover={renderPopover}      offset={{ y: 8 }}    >      <p>Select some text in this paragraph.</p>    </HighlightPopover>  );}

Features

What it handles for you

  • Headless

    Render any React element. The component adds no styles of its own.

  • Small

    About 2.4 kB gzipped, with no dependencies besides React.

  • Collision handling

    The popover flips and shifts to stay on screen, and follows the text on scroll and resize.

  • Waits for release

    The popover appears after the user releases the mouse, not halfway through a drag.

  • Keyboard and ARIA

    Escape hides the popover, keyboard selections show it, and popoverProps sets its ARIA attributes.

  • Server Components

    The build includes a "use client" directive, so you can render it from a Server Component.

Quick start

Wrap the text people can select

Pass a renderPopover function that returns your popover. Inside the popover, the useHighlightPopover hook reads the selection and can close the popover.

Read the docs
import { HighlightPopover } from "@omsimos/react-highlight-popover";

export function Article({ children }) {
  return (
    <HighlightPopover
      offset={{ y: 8 }}
      renderPopover={({ selection }) => (
        <div className="rounded-lg border bg-white p-2 shadow-lg">
          You selected: {selection}
        </div>
      )}
    >
      {children}
    </HighlightPopover>
  );
}

Add a selection popover to your app