Edit Profile

Dark Mode

Copy config

Copy and paste the following code into your global.css file to apply the styles.

Popover

A popup that goes above other content on the page. You can still interact with the rest of the page while the popover is open.

  • In the Top Layer (above the rest of the page)
  • Built on top of the native popover API specification
  • Polyfill for unsupported browsers
  • Executes code on interaction
  • Float and position the popover

The Qwik UI Popover component is built on top of the Native Popover API. Support is in every browser, and will increase over time.

While we wait for support though, Qwik UI uses a polyfill under the hood for you, so that you can use the component in all browsers.

Building blocks

import { component$ } from '@builder.io/qwik';
import { Popover } from '@qwik-ui/headless';
 
export default component$(() => {
  return (
    <Popover.Root>
      <Popover.Trigger>Trigger</Popover.Trigger>
      <Popover.Panel>Panel</Popover.Panel>
    </Popover.Root>
  );
});

🎨 Anatomy

ComponentDescription
Popover.Root

The parent container for the popover trigger and panel.

Popover.Trigger

A button that opens the popover when interacted with.

Popover.Panel

An HTML Element that is above other content on the page.

What is a Popover?

A popover is a non-modal UI element that creates overlays around a DOM element. Non-modal meaning the rest of the page can be interacted with while the popover is shown.

It's great for displaying additional information or options without navigating away from the current context.

When would I use a popover?

It can help prevent overflow issues within your UI, and make sure your content is above everything. The popover component guarantees that your items in the panel remains above the rest of the page.

Use case examples

ComponentDescription
Combobox

A text input that allows users to fill in values from a predefined list.

Select

A dropdown menu that allows users to choose one value from a list.

Context Menu

A menu that appears upon user interaction, such as right-clicking.

Tooltip

A text label that appears when a user hovers, focuses, or touches an element.

Toast

A small message that shows up temporarily to give the user some feedback.

Dropdown Menu

A list of options that appears below a button, that users can select from.

Hover Card

A card that appears when a user hovers over an element.

Caveats

Styling open popovers

.popover-panel[data-open] {
  background: green;
}

Use the data-open attribute on the <Popover.Panel> component to specifically style the popup when it's open on all browsers.

Popover modes

Auto

By default, a popover is auto.

An auto popover will automatically hide when you click outside of it and typically only one can be shown at a time.

Auto popovers dismiss when clicking outside of them and pressing the escape key. There can also only be one auto popover open at a time.

Manual

A manual popover gives you more control over the popup.

Manual popovers do not dismiss unless you click on the <Popover.Trigger> or programmatically close them.

Programmatic Behavior

To programmatically open the Popover.Panel, Qwik UI provides a couple functions from the usePopover hook.

PropTypeDescription
showPopover()
QRL

Opens the popover.

hidePopover()
QRL

Closes the popover.

togglePopover()
QRL

Toggles the popover between the open and closed.

We can control where the popover is floating by using the bind:anchor prop. We pass it a signal, and use that signal as the anchor's ref.

Then, make sure to add an ID to the <Popover.Root> component. This ID must match the ID provided to usePopover.

// a more advanced use case
const { showPopover, hidePopover } = usePopover(popoverId);
 
useTask$(async ({ track }) => {
  track(() => context.isListboxOpenSig.value);
 
  if (isServer) return;
 
  if (context.isListboxOpenSig.value) {
    showPopover();
  } else {
    hidePopover();
  }
});

Above is an example of how we programmatically open and close the popover in the Qwik UI Select component.

Handling state changes

Panel is closed!

Use the onToggle$ prop on the <Popover.Panel> to listen for changes to the popover visibility.

The example above uses a Signal to track whether the popover is triggered or not.

Floating Behavior

By default, the Qwik UI Popover will float below the trigger component.

To make a popover float, we use JavaScript to choose where the popover should be positioned.

Floating mode makes the bundle a bit bigger. We try to keep the API small but still powerful.

Opt out of the floating library

We can opt out of the floating library by setting floating={false} on the <Popover.Root>.

Instead, the popover will be fixed position, and you can use CSS to position it.

Configuration

The Popover.Root component is designed for positioning elements that float and facilitating interactions with them.

Custom Floating Position

By default, popovers will float below the trigger component.

When setting floating on the root, you can customize the position of the popover.

popover on the right ⤵️

Above we have set the floating prop to right, and so the <Popover.Panel> will be positioned to the right of the trigger.

Start & End

This also includes moving things to specific corners of the anchor.

You can suffix the direction with -start or -end to move the popover to the start or end of the anchor.

Flip

Enabled by default, we can use the flip prop to flip its position based on the available space in the viewport.

auto placed on scroll 📜

To disable flipping, set flip={false} on the <Popover.Root>.

Gutter

In the previous docs examples, we use the gutter property on the listbox. Gutter is the space between the anchor element and the floating element.

gutter of 40px!

Styling

Styles can be added normally like any other component in Qwik UI, such as adding a class. The Popover API however, exposes the [popover] attribute.

If Tailwind is the framework of choice, then styles can be added using the arbitrary variant syntax or @apply command. Below is an example of styling with [popover] as an arbitrary variant.

Floating preset

By default, the popover API comes with built-in browser styles, including fixed behavior, margin, the list goes on.

There are times when we want to override this behavior. An example being when we want floating behavior.

Qwik UI strips the following styles when in floating mode:

/* Strips the user agent styles from the popover when in floating mode */
@layer qwik-ui {
  [data-floating] {
    margin: unset;
    padding: unset;
    border: unset;
    overflow: unset;
    position: absolute;
  }
}

/** override the polyfill's layer, which gets dynamically imported later on. */
@layer popover-polyfill {
  [data-floating] {
    margin: unset;
    padding: unset;
    border: unset;
    overflow: unset;
    position: absolute;
  }
}

We put it under an @layer so that it can be easily overridden when adding your own styles.

Animations

Popovers present unique challenges for animations due to their reliance on the display property, which traditionally hasn't been animatable. Modern browsers solve this problem with discrete animations, which allow smooth transitions between display: none and display: block. This ensures that popovers remain visible for the entire duration of the animation.

There are two main types of animations that can be applied to popovers in Qwik UI:

  • Keyframe Animations: For more complex entry and exit animations, such as growing or shrinking effects.
  • CSS Transitions: For smoother, incremental property changes like opacity and scaling.

To handle animations across all browsers, Qwik UI uses both keyframes and transitions, leveraging the native :popover-open pseudo-class and ensuring smooth state transitions with transition-behavior: allow-discrete.

Keyframe Animation Example

Keyframes are ideal for handling the entry and exit of the popover. Below is an example using popover-grow for opening and popover-shrink for closing the popover:

Transition declarations

CSS transitions are useful for animating properties like opacity and scale over time. Discrete properties like display and overlay can be handled using transition-behavior: allow-discrete.

By using keyframe animations and CSS transitions together, we can achieve smooth entry and exit effects for popovers. Keyframes like popover-grow and popover-shrink handle scaling and visibility, while transitions focus on gradual changes to properties like opacity. Remember to include display and overlay in your transition properties and use transition-behavior: allow-discrete to ensure smooth animations across all browsers.

Additional References

Qwik UI aims to be in line with the standard whenever possible. Our goal is to empower Qwik developers to create amazing experiences for their users.

To read more about the popover API you can check it out on:

Popover Root

PropTypeDescription
id
string

Popover's id. Should match the popover target.

manual
boolean

A manual popover needs to be manually hidden, such as toggling the button or programmatically.

floating
boolean | TPlacement

Enables extra JavaScript behavior for floating elements.

anchorRef
Signal

Signal reference that can be passed for floating behavior.

flip
boolean

Flips the placement of the popover when it starts to collide with the boundaries.

gutter
number

The space between the floating element and the anchored element.

[popover]
selector

Selects the popover on all browsers.

data-open
selector

Style the element when the popover is open.

data-closed
selector

Style the element when the popover is closed.

Popover Panel

PropTypeDescription
onToggle
QRL

Function called when the popover opens or closes

usePopover hook

PropTypeDescription
showPopover()
QRL

Opens the popover.

hidePopover()
QRL

Closes the popover.

togglePopover()
QRL

Toggles the popover between the open and closed state.