Docs

Documentation versions (currently viewingVaadin 24)

Popover

Popover is a generic overlay whose position is anchored to an element in the UI.

A generic overlay whose position is anchored to an element in the UI.

Open in a
new tab
Popover popover = new Popover();
popover.setTarget(button);
popover.setWidth("300px");
popover.addThemeVariants(PopoverVariant.ARROW,
        PopoverVariant.LUMO_NO_PADDING);
popover.setPosition(PopoverPosition.BOTTOM);
popover.setAriaLabelledBy("notifications-heading");

Popovers support focusable, interactive content, and can be used to build virtually any type of anchored overlays from custom drop-down fields and drop-down buttons to and interactive tooltips.

The popover’s position is anchored to an element in the UI, called the target element.

Popovers differ from Dialogs in that they are visually anchored to a target element, and they differ from Tooltips in that they can be focused and support rich, interactive content.

Opening and Closing

Popovers can be configured to open and close based on different pointer and keyboard based triggers. See Typical Use Cases for examples.

Opening Triggers

Three target element triggers can be configured to open the popover:

  • Click: clicking the target element, or pressing Space when the target element has focus (default)

  • Hover: hovering over the target element

  • Focus: focusing the target element

Popover popover = new Popover();
popover.setOpenOnClick(false);
popover.setOpenOnHover(true);
popover.setOpenOnFocus(true);

All three triggers can be enabled simultaneously. If no opening trigger is enabled, the popover can only be opened programmatically.

The hover and focus opening triggers have a configurable opening delay.

Popover popover = new Popover();
popover.setHoverDelay(500);
popover.setFocusDelay(500);

Closing Triggers

The following triggers close the popover by default:

  • Target click: Clicking the target element (non-modal popovers only)

  • Outside click: clicking anywhere outside the overlay (can be disabled)

  • Esc: pressing Esc (can be disabled)

Popover popover = new Popover();
popover.setCloseOnEsc(false);
popover.setCloseOnOutsideClick(false);

Additionally:

  • When opened on hover, the popover closes on mouseout, i.e. when the pointer leaves the target element and the overlay.

  • When opened on focus, the popover closes on blur, i.e. when focus is no longer on the target element or in the overlay.

The mouseout closing trigger has a configurable delay.

Popover popover = new Popover();
popover.setHideDelay(500);

Auto Focus

Keyboard focus can be automatically moved to the Popover when it opens. This is recommended for popovers with interactive content that the user is expected to interact with. Modal popovers have auto-focus behavior by default. Popovers opened with hover or focus should not use auto-focus.

Popover popover = new Popover();
popover.setAutofocus(true);

Positioning

By default, popovers open below their target element, horizontally centered to its midpoint, but the positioning options allow this to be changed to any edge or corner, depending on what is most appropriate for the use case.

The popover’s position is automatically maintained if the target element scrolls within the viewport. If there is insufficient space in the viewport for the desired positioning, the popover automatically shifts to fit within the viewport.

Open in a
new tab
select.addValueChangeListener(event -> {
    PopoverPosition position = event.getValue();
    popover.setPosition(position);
});

Target Gap

The distance between the popover and the target element can be customized by setting the following CSS properties on the Popover component:

  • --vaadin-popover-offset-top

  • --vaadin-popover-offset-bottom

  • --vaadin-popover-offset-start

  • --vaadin-popover-offset-end

Target Arrow

Popovers can render a wedge-shaped arrow tip pointing at the target element.

Open in a
new tab
Popover popover = new Popover();
popover.addThemeVariants(PopoverVariant.ARROW);

Configuring Delays

The delay before popover opens can be configured separately for hover and focus. There is no delay before the popover appears on click or when opening programmatically.

The delay before popover closes — when the pointer leaves the target element — can also be configured separately. On blur, though, the popover is closed immediately to avoid confusion when focusing another element.

// Global delay configuration:
Popover.setDefaultFocusDelay(2000);
Popover.setDefaultHoverDelay(1000);
Popover.setDefaultHideDelay(1000);

// Overriding delays for a particular popover:
Popover popover = new Popover();
popover.setHoverDelay(0);

Dimensions

By default, the Popover’s size is determined by its contents, but an explicit width and height can be set on the Popover itself.

Contents that exceed the width of the popover will scroll.

The maximum width of popovers is limited to the width of the viewport, minus a small margin that can be customized with CSS by overriding the inset property of the vaadin-popover-overlay element.

Modality

A modal Popover blocks the user from interacting with the rest of the user interface while open, automatically moves focus from the target element to the Popover, and traps keyboard focus within it.

When combined with an outside click closing trigger, modality prevents accidentally triggering other UI elements when clicking outside the Popover to close it.

By default, modal popovers do not render a modality curtain (or backdrop), but one can be enabled separately. A modality curtain can be useful for de-emphasizing the UI in the background and to give a visual indication that the rest of the UI is blocked from user interaction.

Open in a
new tab
Popover popover = new Popover();
popover.setModal(true);
popover.setBackdropVisible(true);

Accessibility

By default, the Popover overlay has the ARIA role dialog. This can be changed to another role to provide appropriate semantics for the type of content and interaction in the popover (see Typical Use Cases for examples).

  • menu: when the content is a list of actions or links

  • listbox: when the content is a list form which you can select one or more items

  • grid: when the content is a tabular structure from which you select an item

  • tree: when the content is a hierarchical list

Remember that, unlike Tooltip, the contents of a Popover are not automatically announced by screen readers when it opens. Consider using a live region to announce non-interactive popovers, and ensure keyboard access to interactive popovers.

The target element is automatically applied aria-controls (with a reference to the Popover overlay), aria-haspopup (with the overlay’s role as the value), and aria-expanded (set to true when open, and to false otherwise).

An accessible name can be provided for the overlay using the ARIA label API:

Popover popover = new Popover();
popover.setAriaLabel("Label");
// OR
popover.setAriaLabelledby("label-element-id");

Typical Use Cases

Here are a few examples of common use cases for the Popover component with recommended configurations.

Open in a
new tab
TextField field = new TextField("Search date range");
field.setWidth("340px");
Icon icon = LumoIcon.DROPDOWN.create();
field.setSuffixComponent(icon);

popover = new Popover();
popover.setModal(true);
popover.setWidth("325px");
popover.setAriaLabel("Select a date range");
popover.setOpenOnFocus(true);
popover.setFocusDelay(0);
popover.setTarget(field);
  • Opens on click, focus

  • Closes on Esc, blur, outside click, target click, and programmatically upon selection

  • Modal, no modality curtain (drop-down fields typically don’t have curtains)

  • Auto-focused

  • ARIA role dialog

  • ARIA label “Select a date range”

User Menu

Open in a
new tab
String name = person.getFirstName() + " " + person.getLastName();
String pictureUrl = person.getPictureUrl();

Avatar avatar = new Avatar(name);
avatar.setImage(pictureUrl);
avatar.getStyle().set("display", "block");
avatar.getStyle().set("cursor", "pointer");
avatar.getElement().setAttribute("tabindex", "-1");

Button button = new Button(avatar);
button.addThemeVariants(ButtonVariant.LUMO_ICON,
        ButtonVariant.LUMO_TERTIARY_INLINE);
button.getStyle().set("margin", "var(--lumo-space-s)");
button.getStyle().set("margin-inline-start", "auto");
button.getStyle().set("border-radius", "50%");

Popover popover = new Popover();
popover.setModal(true);
popover.setOverlayRole("menu");
popover.setAriaLabel("User menu");
popover.setTarget(button);
popover.setPosition(PopoverPosition.BOTTOM_END);
popover.addThemeVariants(PopoverVariant.LUMO_NO_PADDING);
  • Opens on click

  • Closes on Esc, outside click, target click

  • Modal, no modality curtain (small popovers like this usually don’t need them)

  • ARIA role menu (the overlay’s content is a menu; although there are non-list elements, they are not interactive, nor do they need to be announced by screen readers)

  • ARIA label “User menu”

Note: if the popover only needs to contain menu items, consider using a Menu Bar or Context Menu instead.

Notification Panel

Open in a
new tab
Popover popover = new Popover();
popover.setTarget(button);
popover.setWidth("300px");
popover.addThemeVariants(PopoverVariant.ARROW,
        PopoverVariant.LUMO_NO_PADDING);
popover.setPosition(PopoverPosition.BOTTOM);
popover.setAriaLabelledBy("notifications-heading");
  • Opens on click

  • Closes on Esc, outside click, target click

  • Modal, no modality curtain (small popovers like this usually don’t need them)

  • ARIA role dialog (although mainly a list, there interactive non-list elements as well)

  • ARIA labelled-by pointing to heading in overlay

  • Arrow variant

Rich, Interactive Tooltip

Open in a
new tab
IntegerField cvv = new IntegerField("CVV");
cvv.setWidth("60px");

Popover popover = new Popover();
popover.addThemeVariants(PopoverVariant.ARROW);
popover.setPosition(PopoverPosition.TOP);
popover.setOpenOnClick(false);
popover.setOpenOnHover(true);
popover.setOpenOnFocus(true);

H3 header = new H3("Card Verification Value");
header.setId("cvv-heading");
header.getStyle().set("margin", "0");
header.getStyle().set("font-size", "1rem");

Div content = new Div(
        "A three or four digit code, usually printed on the back of the card, "
                + "next to, or at the end of, the signature strip.");
content.getStyle().set("max-width", "300px");

Anchor link = new Anchor("https://www.cvvnumber.com/cvv.html",
        "See where to find CVV on different cards", AnchorTarget.BLANK);

popover.add(header, content, link);
popover.setAriaLabelledBy("cvv-heading");
popover.setTarget(cvv);

add(cvv, popover);
  • Opens on hover, focus

  • Closes on Esc, outside click (as well as mouseout and blur)

  • Non-modal

  • Not auto-focused

  • ARIA role dialog (tooltip would be invalid due to interactive contents)

  • ARIA labelled-by pointing to heading in overlay

  • Positioned above target

  • Arrow variant

Anchored Modal Dialog

Open in a
new tab
Popover popover = new Popover();
popover.setModal(true);
popover.setBackdropVisible(true);
popover.setPosition(PopoverPosition.BOTTOM_END);
popover.setTarget(button);

Div heading = new Div("Configure columns");
heading.getStyle().set("font-weight", "600");
heading.getStyle().set("padding", "var(--lumo-space-xs)");

List<String> columns = List.of("firstName", "lastName", "email",
        "phone", "birthday", "profession");

CheckboxGroup<String> group = new CheckboxGroup<>();
group.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL);
group.setItems(columns);
group.setItemLabelGenerator((item) -> {
    String label = StringUtils
            .join(StringUtils.splitByCharacterTypeCamelCase(item), " ");
    return StringUtils.capitalize(label.toLowerCase());
});
group.addValueChangeListener((e) -> {
    columns.stream().forEach((key) -> {
        grid.getColumnByKey(key).setVisible(e.getValue().contains(key));
    });
});

Set<String> defaultColumns = Set.of("firstName", "lastName", "email",
        "profession");
group.setValue(defaultColumns);

Button showAll = new Button("Show all", (e) -> {
    group.setValue(new HashSet<String>(columns));
});
showAll.addThemeVariants(ButtonVariant.LUMO_SMALL);

Button reset = new Button("Reset", (e) -> {
    group.setValue(defaultColumns);
});
reset.addThemeVariants(ButtonVariant.LUMO_SMALL);

HorizontalLayout footer = new HorizontalLayout(showAll, reset);
footer.setSpacing(false);
footer.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);

popover.add(heading, group, footer);
  • Opens on click

  • Closes on Esc, outside click

  • Modal, with curtain

  • Auto-focused

  • ARIA role dialog

  • ARIA labelled-by pointing to heading in the overlay

Note: if the dialog doesn’t benefit from being anchored-positioned to another element, consider using a Dialog instead.

Component Usage Recommendation

Dialog

Use instead of Popover if there is no need to visually associate it with another UI element. Modal dialogs are a better option for transactional operations. Modal dialogs provide full-stack modality (e.g. keyboard shortcuts defined in the UI behind are blocked while the Dialog is open)

Tooltip

Use instead of Popover if the content is just text.

Context Menu

Use instead of Popover if the content is a list of actions or toggles.

Menu Bar

Same as Context Menu, but with built-in trigger buttons.