Preview
Usage
A Popover contains a dialog that will appear above other content when activated. It will always appear in a location relative to the anchor. If you are looking for a dialog that does not display relative to the anchor, see Modal. Some common examples of popover usage: dropdown list, emoji picker dialog, add comment dialog. A popover can be modal or non-modal. Below are some guidelines on when to use a modal vs non-modal popover.
Migration note: DtOldPopover is deprecated. Replace all uses with DtPopover (this component). DtOldPopover will be removed in a future major version. See the whats-new posts for migration details.
Your popover should be modal when:
- It contains scrollable content.
- It contains components that hold user input state (input, checkbox).
Your popover should be non-modal when:
- It is not scrollable.
- It contains only components that do not hold state (link, button).
The content slot will be rendered lazily when the popover is open. By default, the popover content will be opened when the anchor is clicked, and closed when clicking outside the content or on ESC key press. You may override this behaviour by using .sync on the open prop (or v-model:open in Vue 3) in which you can open or close the content using whichever condition you wish.
Do
- Smaller sized dialogs that trigger on user activation of an anchor element.
- Dialogs that should be positioned relative to the anchor.
- Dialogs that contain interactive components.
Don’t
- Content that is displayed on hover. Instead, use a Tooltip.
- Dialogs that should be positioned in the center of the screen.
- Dialogs that are very large.
- Alerts.
Best Practices
- Popovers should be fairly small. If you are looking for more of a full size dialog solution see Modal
- Trigger using an anchor element, such as a button.
- Render the dialog at the body element.
- Focus the first interactive element within the dialog after it is opened.
- Close the dialog when ESC is pressed.
- Close non-modal dialogs if they are scrolled out of visibility.
- Set the z-index of the dialog to var(--zi-modal-element) if modal, var(--zi-popover) if not.
Variants and Examples
Popover - Modal
Popover - Non Modal
With Header - Modal
With Footer - Modal
Fallback Placements
The popover uses headless-tippy and
popper, if the popover opens in a placement where it will
be clipped, it will move to a new position. It will do this automatically by default, but if you want to
manually specify which position it will move to in what order you can do so via the fallbackPlacements prop.
Padding
Padding options for the popover content are provided via size classes "small", "medium" or "large" in order to standardize the look of the popover content between usages. To remove the padding from the content, you can pass "none". Setting none will also allow you to set custom padding via utility classes (Ex: you only want padding on the left.).
Force Close All Opened Instances
When the popover is open, it will attach an event listener into the window object, so you can close the instances dispatching the dt-popover-close event in the window object:
const e = new Event('dt-popover-close');
window.dispatchEvent(e);
Content Mode
Popover content renders outside the DOM tree. Use the contentMode prop to apply color mode (invert, light, dark) to the positioned content. See Positioned Components for details.
Vue API
import { DtPopover } from '@dialpad/dialtone-vue';Slots
Props
Events
Classes
Popover must contain an anchor and content element. d-modal--transparent can be used as a sibling before the popover container if you wish to make the popover modal.
Accessibility
If your popover is modal, please see the accessibility section of this page regarding "focus trapping": Modal Accessibility. The same rules will apply here if your popover is modal.
Popovers, in their current implementation, are accessible when used as interactive components. Content will be read to screen reader users, and the popover markup by is appended to the <body>.
There are a few important considerations to ensure popover controls are accessible:
- The popover content will have a generic role of "dialog" ( "menu" and "listbox" are also possible roles as well).
- On open, focus will be transferred to the first focusable element within the popover, after close the triggering element will be focused.
- A screen reader visible only close button is added by default when setting the
showCloseButtonprop tofalse.
Anchor
The anchor element that activates the popover should be fully accessible by keyboard. The easiest way to do this is by using an element like an DtButton that is already accessible. The user should also be able to close the popover content using the ESC key for most ARIA roles.
There are some required ARIA attributes for the anchor element (such as aria-expanded set based on open and aria-haspopup that matches the role). To make this as straightforward as possible, these ARIA attributes are passed with the correct values as the attrs slot-scope to the anchor slot. Applying them is as simple as using v-bind:
<template #anchor="{ attrs }">
<dt-button v-bind="attrs">I'm accessible now!</dt-button>
</template>
By default, the dialog content will be labeled by the entire anchor element. To change this, you can do one of 2 things:
- Pass
aria-label, which is the text label that will be applied to the dialog content. - Pass
aria-labelledby, which is an ID of the element that should be used as the descriptive label.
Keyboard Support
The below keyboard functionality is automatically implemented when using the popover component:
- The user can dismiss the popover pressing the
ESCkey, after that the focus will be returned to the element that launched it. - The user can traverse focusable elements using the
TABkey. If the popover has a defined header, the focus will be moved to the header buttons after the last focusable element inside content's container.
Additionally you must use the "initialFocusElement" prop to set which element is initially focused when the popover opens. You can set this to "first" to focus the first focusable element, "dialog" to focus the dialog itself, a string starting with '#' to focus an element by id within the dialog or you may pass in an HTMLElement directly. If set to "none" the focus will remain on the anchor, however this is invalid behavior if the popover is modal.