Popover

Import
import { Popover } from "reshaped";
import type { PopoverProps } from "reshaped";
Related components
Works with any type of content
Can be controlled and uncontrolled

Automatically traps focus when opened and supports multiple focus management modes

Automatically fits the popover into the viewport or locks it to the position value you provide

Full keyboard navigation
Supports custom width
Supports custom trigger element rendering
Supports hover and click trigger events


You can use Popovers with any interactive element on the page by passing its attributes and adding the content you want to render.

<Popover>
  <Popover.Trigger>
    {(attributes) => <Button attributes={attributes}>Trigger popover</Button>}
  </Popover.Trigger>
  <Popover.Content>Popover content</Popover.Content>
</Popover>

Popovers open after clicking the trigger element, but you can customize that using triggerType property.

<Popover triggerType="hover">
  <Popover.Trigger>
    {(attributes) => (
      <Button attributes={attributes}>Trigger popover on hover</Button>
    )}
  </Popover.Trigger>
  <Popover.Content>Popover content</Popover.Content>
</Popover>

You can define the position where you want to display the Popover. However, if it doesn't fit into the screen, it will automatically pick a better position that stays within the viewport.

<Popover position="bottom-end">
  <Popover.Trigger>
    {(attributes) => <Button attributes={attributes}>Trigger popover</Button>}
  </Popover.Trigger>
  <Popover.Content>Popover content</Popover.Content>
</Popover>

If you want to ignore the viewport boundaries and always show Popover using a specific position value, you can lock it with a forcePosition property. This can be useful when using Popover to build dropdown menus.

<Popover position="bottom-end" forcePosition>
  <Popover.Trigger>
    {(attributes) => <Button attributes={attributes}>Trigger popover</Button>}
  </Popover.Trigger>
  <Popover.Content>Popover content</Popover.Content>
</Popover>

You can control the width of the Popover with the width property. You can either pass a specific px or percent value. That includes using CSS variables for defining the size.

<Popover width="calc(var(--rs-unit-x1) * 100)">
  <Popover.Trigger>
    {(attributes) => <Button attributes={attributes}>Trigger popover</Button>}
  </Popover.Trigger>
  <Popover.Content>Popover content</Popover.Content>
</Popover>

Popover comes with a default padding in its content area, and you can customize it with the padding property. For example, you can altogether remove it with padding set to 0.

<Popover padding={0}>
  <Popover.Trigger>
    {(attributes) => <Button attributes={attributes}>Trigger popover</Button>}
  </Popover.Trigger>
  <Popover.Content>
    <View backgroundColor="neutral-faded" height={50} />
  </Popover.Content>
</Popover>

If you need to add a close button to the Popover content, you can use it with the Dismissible utility.

function Demo() {
  const { activate, deactivate, active } = useToggle();

  return (
    <Popover active={active} onOpen={activate} onClose={deactivate}>
      <Popover.Trigger>
        {(attributes) => (
          <Button attributes={attributes}>Trigger popover</Button>
        )}
      </Popover.Trigger>
      <Popover.Content>
        <Dismissible onClose={deactivate} closeAriaLabel="Close popover">
          <View backgroundColor="neutral-faded" height={50} />
        </Dismissible>
      </Popover.Content>
    </Popover>
  );
}

You can either pass a literal width value like 200px or a trigger value to align Popover content width with its trigger. This is helpful when you're using fullWidth Button component or Select / TextField together with DropdownMenu.

<Popover width="trigger">
  <Popover.Trigger>
    {(attributes) => (
      <Select
        name="animal"
        placeholder="Select an animal"
        inputAttributes={attributes}
      />
    )}
  </Popover.Trigger>
  <Popover.Content></Popover.Content>
</Popover>

You can remove most of the Popover content styles by using the headless variant. It can be useful, when you want to customize how the content looks like. For example, to add a border color to it or to show an image component without rendering a card wrapper around it.

You can apply custom styles by using both approaches: rendering another component inside the Popover.Content or adding a className to it. When using the headless variant, you still have access to all Popover properties.

<Popover variant="headless">
  <Popover.Trigger>
    {(attributes) => <Button attributes={attributes}>Show a photo</Button>}
  </Popover.Trigger>
  <Popover.Content>
    <Image
      src="/img/examples/image-retina.webp"
      alt="Canyon rock"
      borderRadius="medium"
      width="200px"
    />
  </Popover.Content>
</Popover>
  • It's essential to pass the attributes provided by the Popover component to your interactive trigger component. That way, you will ensure that all the user events and aria attributes are assigned correctly.

  • Popover traps the focus in its content area, but you can control how it's applied with the trapFocusMode property. It applies a regular focus trap with the Tab key navigation enabled by default. However, you can switch it to action-menu or content-menu modes to make it work like a listbox or regular content area with links.