Edit Profile

Dark Mode

Copy config

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

DISCLAIMER: This component is in
Beta
status. That means that it is ready for production, but the API might change.

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.

Cross-browser Animations

Entry and exit animations have often been a frustrating experience in web development. Especially trying to animate between display: none, a discrete property.

Until recently, discrete properties were not animatable. Luckily, there's new properties to CSS that solve this problem.

The browser support for these is similar to support of the popover API. That said, the Qwik UI team has done an awesome job of managing animations on polyfill browsers for you using the data-open and data-closing attributes.

.my-transition {
  transition:
    opacity 0.5s,
    display 0.5s,
    overlay 0.5s;
 
  /* on new-line so the declaration is valid in all browsers */
  transition-behavior: allow-discrete;
 
  /* starting style for all browsers */
  opacity: 0;
}
 
.my-transition[data-open] {
  opacity: 1;
}
 
.my-transition[data-closing] {
  opacity: 0;
}

Above is an example of a transition that works across browsers. The allow-discrete property allows us to transition both display and overlay. Overlay is a property that allows us to transition top-layer behavior.

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.

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.

Hover

If we'd like to show the Popover.Panel on hover, we can use the hover prop.

I'm a mini tooltip!

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

To use an animation, add the following CSS classes to the component.

  • The data-open attribute determines the animation that happens when it is first opened.

  • The data-closing class determines what class is added when the listbox is closed.

Here's the CSS imported from the example:

.popover-animation {
  transform: scale(0);
}
 
.popover-animation[data-open] {
  animation: popover-grow 0.5s ease-in-out forwards;
}
 
.popover-animation[data-closing] {
  animation: popover-shrink 0.4s ease-in-out forwards;
}
 
@keyframes popover-shrink {
  from {
    transform: scale(1);
  }
 
  to {
    transform: scale(0);
  }
}
 
@keyframes popover-grow {
  from {
    transform: scale(0);
  }
 
  to {
    transform: scale(1);
  }
}

Transition declarations

Transitions use the same classes for entry and exit animations. Those being data-open and data-closing. They are explained more in the Caveats section.

CSS from the example:

.popover-transition {
  opacity: 0;
  transition:
    opacity 0.5s,
    display 0.5s,
    overlay 0.5s;
  transition-behavior: allow-discrete;
}
 
.popover-transition[data-open] {
  opacity: 1;
}
 
.popover-transition[data-closing] {
  opacity: 0;
}

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-closing
selector

Style the element when the popover is closing.

data-closed
selector

Style the element when the popover is closed.

data-closing
class

Class to animate exit behavior.

usePopover hook

PropTypeDescription
showPopover()
QRL

Opens the popover.

hidePopover()
QRL

Closes the popover.

togglePopover()
QRL

Toggles the popover between the open and closed state.