Skip to main content

Common Examples

import { Popover } from "@servicetitan/anvil2";

const ExampleComponent = () => {
  return (
    <Popover>
      <Popover.Button>Click me!</Popover.Button>
      <Popover.Content>This is the popover content.</Popover.Content>
    </Popover>
  );
};

Popover basics

To build a popover, three components are required:
  • Popover: the configurable parent component
  • A way to control the open state of the popover. One of:
    • Popover.Button: an Anvil2 Button
    • Popover.Trigger: used to render a custom trigger component
  • Popover.Content: the content rendered within the popover
<Popover>
  <Popover.Button>Trigger Button</Popover.Button>
  <Popover.Content>Popover content. Accepts a ReactNode.</Popover.Content>
</Popover>

Popover placement

Use the placement prop on the Popover to change the default positioning. The popover will reposition itself if there is not enough space in the default placement.
<Popover placement="top">...</Popover>

Controlling popovers

Popovers can be controlled or uncontrolled (default). Control the popover using the open prop.

Uncontrolled (default)

Controlled

Using a custom trigger

To use something other than an Anvil2 Button to trigger the popover, use the Popover.Trigger component. The Popover.Trigger passes a set of props to the children that should be passed to an interactive HTML element, such as a button or input.
<Popover>
  <Popover.Trigger>
    {(props) => <button {...props}>Open Popover</button>}
  </Popover.Trigger>
  <Popover.Content>Content</Popover.Content>
</Popover>

Popover close button

The Popover.Close button can be used to close the popover from within the popover content.On controlled popovers, the onClick prop should be used to update the open state:
<Popover.Close onClick={() => setIsOpenState(false)} icon={Close} />

Disabling default closing behavior

By default, an uncontrolled popover closes if either the user clicks outside of the popover, or the user presses the “Escape” key. Both of these behaviors can be disabled with props:

Disable close on outside click

Disable close on “Escape” press

Enabling trapped focus

By default, the popover content does not trap focus so that users can navigate the content with a keyboard without naturally. To enable this behavior, set the modal prop of the Popover to true.

Default without trapping

Trapped focus

Using with Anvil1

Popover from version 1.23.0 uses HTML popover API which utilizes top-layer. This feature puts what’s inside the top-layer to be on the top of entire the HTML. Because of this, there are cases where it does not work well with Anvil1’s portaled components.
  • While having the Popover open, if a portaled Anvil1 component is triggered to open from within, the Popover will be on top always. This is something we can potentially adjust in Anvil1 and we have a spike ticket internally for it. If you encounter this issue, please reach out to us.
  • While having the Popover open, if a Drawer or Dialog from Anvil1 is triggered to open, not within the Popover, the Popover will be on top of the Drawer or Dialog.

React Accessibility

Most of the accessibility considerations for managing aria props and keyboard focus are handled internally. There are some things to keep in mind while working with popovers:
  • Always test keyboard navigation for interactive elements within popovers. The user should be able to easily access the elements in a logical order.
  • If the popover includes a form, be sure to follow accessible best practices for form building.
  • When building a custom trigger using Popover.Trigger, be sure to pass the props to an interactive element, as certain aria props are included to properly connect the trigger to the content.
For more guidance on creating accessible components, see building accessible custom components best practices.
Last modified on January 23, 2026