Popover
A popover is a floating content container that appears relative to a trigger element. Popovers display richer, persistent content that requires explicit user interaction (click or tap), while tooltips appear automatically on hover or focus with brief, contextual information.
Ready to use
Tooltip and Popover share the same component base. Both display contextual information, but their behaviour and purpose differ. A Tooltip offers short contextual hints that appear on hover or focus and disappear automatically; a Popover is a persistent overlay that provides extra information or actions — links, preferences — and stays open until dismissed.
Anatomy
Section titled “Anatomy”- Bubble
- Title
- Close button
- Content slot
- Link
- Arrow
When to use it
Section titled “When to use it”Use a Tooltip when:
- You need to provide brief, contextual information about an element.
- The information clarifies a label, icon, or control without interrupting the flow.
- The content is short, non-essential, and disappears automatically.
Use a Popover when:
- You need to display additional information, options, or actions that require user interaction.
- The content is richer (title, link, button) and must persist until dismissed.
- The user needs time to read or interact before closing.
Avoid both when:
- The content is critical to completing a task — use a Modal instead.
- The message is too long to fit in a small floating container.
- The user might miss the message because of automatic disappearance or poor trigger placement.
Properties
Section titled “Properties”Variant
Tooltip for hover/focus-triggered hints (no close button, no link). Popover for click/tap-triggered overlays (includes a close button, optional title, and optional link). Both share the same bubble, padding, and elevation.
Arrow placement
Top, Bottom, Left, or Right — but actual placement adjusts dynamically based on context. The arrow can live anywhere along the bubble’s perimeter (top-left, bottom-centre, right-top), not just the four cardinal positions; the predefined directions are visual references.
Contrast
Two variants for legibility across surfaces: Contrast (True) uses a dark bubble for use on light backgrounds (default), Contrast (False) uses a light bubble for dark or overlay surfaces. Behaviour, spacing, and accessibility rules stay identical.
Content slot
The replaceable slot accepts custom content such as energy labels, formatted text, or component instances. Any interactive element inside follows the system’s touch-area and focus-order rules.
Width
The bubble uses hug-content auto layout with a 150 px minimum and a 320 px maximum, so short labels and longer translations both fit without truncation or horizontal scroll.
Platform considerations
Section titled “Platform considerations”Desktop
Use both Tooltip and Popover here. Tooltips trigger on hover or focus and disappear on blur or Escape; Popovers trigger on click and persist until dismissed.
Tablet
Mixed input — Popovers work well for click/tap actions. Tooltips become less reliable as hover affordances disappear; reserve them for keyboard-focusable controls.
Mobile
Avoid Tooltips entirely (no reliable hover). Replace Popovers with a Bottom Sheet (modal-style overlay) to keep accessibility and usability intact on touch interfaces. The Bottom Sheet keeps the same hierarchy and purpose but adapts the layout for smaller viewports.
Best practices
Section titled “Best practices”Pick the variant that matches the interaction model — Tooltips for hints, Popovers for actions.
Do
Use Tooltips for short, non-interactive explanations triggered on hover or focus, use Popovers for extended or actionable content, replace both with a Bottom Sheet on mobile, ensure clear close and dismissal actions for Popovers with proper focus management, position the arrow so it clearly references the trigger, and maintain consistent spacing and elevation across brands.
Don't
Don’t include interactive elements inside Tooltips (they must disappear when focus or hover is lost), don’t use Tooltips on mobile, don’t put critical task content inside either component (use a Modal), and don’t position the bubble so the arrow doesn’t clearly point back to the trigger.
Content guidelines
Section titled “Content guidelines”Keep Tooltip copy to a short sentence or phrase (max 80–100 characters in English), use simple punctuation and sentence case, and avoid formatting, links, or interactive elements inside them. Popovers can hold longer content with titles and links — aim for up to 300–350 characters and reach for a Modal or side panel if the copy keeps growing. Both components should resize vertically or horizontally for longer languages (German, Finnish), so avoid fixed text heights and check wrapping behaviour at mobile and tablet widths. Keep the title > body > link hierarchy regardless of language so the announcement order stays predictable.
Styles
Section titled “Styles”A popover is a floating content container that appears relative to a trigger element.
<div class="tng-popover is-contrast"> <div class="tng-popover-bubble"> <p class="tng-text-body">…</p> </div></div>Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
Elements
Section titled “Elements”An arrow can be placed at top, right, bottom or left using the data-placement attribute.
<div class="tng-popover is-contrast"> <div class="tng-popover-arrow" data-placement="top"></div> <div class="tng-popover-bubble"> <p class="tng-text-body">…</p> </div></div>Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
Backdrop
Section titled “Backdrop”<div class="tng-backdrop"></div><div class="tng-popover is-contrast"> <div class="tng-popover-bubble"> <p class="tng-text-body">…</p> </div></div>Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
Close button
Section titled “Close button”<div class="tng-popover is-contrast"> <div class="tng-popover-bubble"> <button class="tng-icon-button is-neutral" aria-label="Close"> <i class="tng-icon icon-close" aria-hidden="true"></i> </button> <p class="tng-text-body">…</p> </div></div>Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
<div class="tng-popover is-contrast"> <div class="tng-popover-bubble"> <div class="tng-text-title">…</div> <p class="tng-text-body">…</p> </div></div>Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
Compose the link with .is-neutral so it adopts the popover’s foreground colour instead of the default link blue.
<div class="tng-popover is-contrast"> <div class="tng-popover-bubble"> <p class="tng-text-body">…</p> <a class="tng-link is-neutral">Link</a> </div></div>Sit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
LinkSit sit occaecat minim aute tempor veniam Lorem non et anim. Id in quis eiusmod ea velit sit qui aute cillum aliquip ad aliqua ex. Proident irure proident labore occaecat ex velit Lorem.
LinkRecipes
Section titled “Recipes”Tooltip
Section titled “Tooltip”This is a tooltip.
Popover
Section titled “Popover”This is a popover with interactive content.
Popover
Section titled “Popover”The Popover is a provider component that displays rich interactive content when triggered by a click. Unlike tooltips which appear on hover, popovers require explicit user interaction to open and close.
This component must wrap PopoverTrigger and PopoverContent to function correctly.
Properties
Section titled “Properties”| Prop | Type | Description | Optional |
|---|---|---|---|
isContrast | boolean | Choose between dark or light version of the popover | ✅ |
initialOpen | boolean | Whether the popover is initially open, false by default | ✅ |
placement | Placement | Position of the popover relative to trigger (top, top-start, top-end | bottom, bottom-start, bottom-end | left, left-start, left-end | right, right-start, right-end). top by default | ✅ |
offset | number | Distance in pixels between trigger and tooltip, defaults to 8px | ✅ |
Example
Section titled “Example”import { Popover, PopoverTrigger, PopoverContent, IconButton,} from '@tmedxp/react-components';
const PopoverExample = () => { return ( <Popover placement="bottom" isContrast={false}> <PopoverTrigger> <IconButton iconName="info" size="sm" isNeutral /> </PopoverTrigger> <PopoverContent title="More Information" labels={{ Close: 'Close' }}> <p>This is detailed interactive content.</p> </PopoverContent> </Popover> );};
export { PopoverExample };PopoverTrigger
Section titled “PopoverTrigger”The PopoverTrigger component wraps an element that opens the popover when clicked. It toggles the popover’s visibility on each click.
Must be used within a Popover provider.
The children of this component must be an interactable element (button, link,..)
Example
Section titled “Example”import { Popover, PopoverTrigger, PopoverContent, IconButton,} from '@tmedxp/react-components';
const PopoverTriggerExample = () => { return ( <Popover placement="right"> <PopoverTrigger> <IconButton iconName="info" size="sm" isNeutral /> </PopoverTrigger> <PopoverContent title="Details" labels={{ Close: 'Close popover' }}> Click the icon to toggle this popover </PopoverContent> </Popover> );};
export { PopoverTriggerExample };PopoverContent
Section titled “PopoverContent”The PopoverContent component displays interactive content in a panel. It includes a close button, optional title, optional link button, and can render as a modal on mobile devices.
Must be used within a Popover provider.
Properties
Section titled “Properties”| Prop | Type | Description | Optional |
|---|---|---|---|
labels | PopoverLabels | Accessibility labels, requires Close property for close button | ❌ |
title | string | Optional title displayed at the top of the popover | ✅ |
linkProperties | LinkProperties | Optional link configuration displayed at the bottom | ✅ |
useModalOnMobile | boolean | Renders as a modal on mobile devices, false by default | ✅ |
className | string | Custom CSS class names for styling | ✅ |
Example
Section titled “Example”import { Popover, PopoverTrigger, PopoverContent, IconButton,} from '@tmedxp/react-components';
const PopoverContentExample = () => { return ( <Popover placement="bottom"> <PopoverTrigger> <IconButton iconName="info" size="sm" isNeutral /> </PopoverTrigger> <PopoverContent title="Additional Information" linkProperties={{ text: 'Learn More', href: '/more-info', }} useModalOnMobile={true} labels={{ Close: 'Close popover' }} > <p>This is detailed content with interactive elements.</p> <ul> <li>Feature 1</li> <li>Feature 2</li> </ul> </PopoverContent> </Popover> );};
export { PopoverContentExample };Tooltip
Section titled “Tooltip”The Tooltip is a provider component that displays short contextual hints on hover or focus. It manages the state and positioning of tooltips, ensuring proper coordination between the trigger element and tooltip content.
This component must wrap TooltipTrigger and TooltipContent to function correctly.
Properties
Section titled “Properties”| Prop | Type | Description | Optional |
|---|---|---|---|
isContrast | boolean | Choose between dark or light version of the tooltip | ✅ |
initialOpen | boolean | Whether the tooltip is initially open, false by default | ✅ |
placement | Placement | Position of the tooltip relative to trigger (top, top-start, top-end | bottom, bottom-start, bottom-end | left, left-start, left-end | right, right-start, right-end). top by default | ✅ |
offset | number | Distance in pixels between trigger and tooltip, defaults to 8px | ✅ |
Example
Section titled “Example”import { Tooltip, TooltipTrigger, TooltipContent, IconButton,} from '@tmedxp/react-components';
const TooltipExample = () => { return ( <Tooltip placement="top" isContrast={false}> <TooltipTrigger> <IconButton iconName="info" size="sm" isNeutral /> </TooltipTrigger> <TooltipContent>This is helpful information</TooltipContent> </Tooltip> );};
export { TooltipExample };TooltipTrigger
Section titled “TooltipTrigger”The TooltipTrigger component wraps an element that triggers the tooltip display. When the user hovers over or focuses on this element, the associated tooltip content appears.
Must be used within a Tooltip provider.
The children of this component must be an interactable element (button, link,…)
Example
Section titled “Example”import { Tooltip, TooltipTrigger, TooltipContent, IconButton,} from '@tmedxp/react-components';
const TooltipTriggerExample = () => { return ( <Tooltip placement="top"> <TooltipTrigger> <IconButton iconName="info" size="sm" isNeutral /> </TooltipTrigger> <TooltipContent>Helpful information appears here</TooltipContent> </Tooltip> );};
export { TooltipTriggerExample };TooltipContent
Section titled “TooltipContent”The TooltipContent component displays the actual content of the tooltip. It appears in a floating bubble with an arrow pointing to the trigger element. The content automatically positions itself relative to the trigger and viewport.
Must be used within a Tooltip provider.
Properties
Section titled “Properties”TooltipContentProperties extends HTMLProps<HTMLElement> which means it includes all standard HTML element attributes.
| Prop | Type | Description | Optional |
|---|---|---|---|
className | string | Custom CSS class names for styling | ✅ |
Example
Section titled “Example”import { Tooltip, TooltipTrigger, TooltipContent, IconButton,} from '@tmedxp/react-components';
const TooltipContentExample = () => { return ( <Tooltip placement="bottom" isContrast={true}> <TooltipTrigger> <IconButton iconName="help" size="sm" isNeutral /> </TooltipTrigger> <TooltipContent className="custom-tooltip"> <p>This is detailed information that helps the user.</p> <p>It can contain multiple elements.</p> </TooltipContent> </Tooltip> );};
export { TooltipContentExample };useTooltipContext hook
Section titled “useTooltipContext hook”The useTooltipContext hook provides access to the tooltip context, allowing child components to interact with the tooltip state and positioning. This hook must be used within a Tooltip or Popover provider component.
Returns
Section titled “Returns”The hook returns an object with the following properties:
| Property | Type | Description |
|---|---|---|
open | boolean | Current open/closed state of the tooltip |
setOpen | (open: boolean) => void | Function to programmatically open or close the tooltip |
This hook is primarily used internally by TooltipTrigger, TooltipContent, PopoverTrigger, and PopoverContent components but it can be used in custom components that need access to the tooltip state.
Example
Section titled “Example”import { useTooltipContext } from '@tmedxp/react-components';
const CustomText = () => { const { open } = useTooltipContext(); return <p>Tooltip is {open ? 'open' : 'closed'}</p>;};
const CustomComponent = () => { return ( <Popover> <CustomText /> <PopoverTrigger> <button>Toggle Tooltip</button> </PopoverTrigger> <PopoverContent> <span>Some text</span> </PopoverContent> </Popover> );};
export { CustomTooltipComponent };Quick summary
Section titled “Quick summary”- Both Tooltip and Popover must comply with WCAG 2.1 (1.4.3, 1.4.13, 2.1.1) and EN 301 549 standards.
- Ensure a minimum contrast ratio of 4.5:1 between text and background.
- Tooltip: Triggered by hover or focus, dismissed on blur or Escape. Must be accessible via keyboard and announced using
aria-describedby. - Popover: Triggered by click or tap, dismissed via close button, external click, or Escape. Browser-managed focus: the popover is inserted into the tab order after the trigger, and focus returns to the trigger on close. Include
aria-labelledbywhen a title is present. - Always position the pointer or arrow so it clearly references the triggering element.
- Maintain consistent spacing and elevation across brands and viewports.
For designers
Section titled “For designers”- Ensure sufficient colour contrast between text, icons, and background (minimum ratio 4.5:1, WCAG 2.1 AA).
- Both Tooltip and Popover must remain fully readable and dismissible across light and dark themes.
- Tooltip text should not rely solely on colour or animation to convey meaning.
- Maintain clear spacing between Tooltip or Popover and the triggering element.
- Avoid placing interactive elements too close to the Tooltip or Popover to prevent focus traps.
- Ensure consistent alignment, padding, and border radius according to tokenised structure.
- Focus styles must remain visible and meet WCAG AA contrast requirements across all supported surfaces. Focus should be clearly distinguishable from hover.
- Colour tokens used within the component should be semantic (e.g.
color-foreground-neutral-default) rather than fixed values. This ensures the component adapts correctly to different themes or surfaces.
For developers
Section titled “For developers”- Tooltip and Popover must be fully accessible via keyboard.
- Tooltips should appear on focus and hover, and dismiss on blur or Escape.
- Popovers should rely on the native Popover API for focus management — the browser inserts the popover into the tab order after the trigger and restores focus to the trigger on close. Avoid implementing custom focus traps.
- Use
aria-describedbyfor tooltips andaria-labelledbyoraria-controlsfor popovers when referencing content. - Decorative icons must be marked with
aria-hidden="true". - Each interactive element inside a Popover must be reachable and operable via keyboard.
- Ensure all instances are tested through automated accessibility tools (e.g. Axe, Lighthouse) before release.
- Manually verify focus order and visibility in both themes to confirm expected behaviour.
Roles & attributes
Section titled “Roles & attributes”- Tooltips — use
role="tooltip"and link them to their trigger witharia-describedby. - Popovers with interactive content — use
role="dialog"(orrole="alertdialog"when the user must acknowledge something). Link the trigger to the popover witharia-controlsor usepopovertarget.
HTML Popover API
Section titled “HTML Popover API”The Popover API provides built-in accessibility benefits — including focus management, light-dismiss, and top-layer promotion — without custom JavaScript.
| Attribute | Behaviour |
|---|---|
popover (or popover="auto") | Light-dismiss enabled. Opening one auto popover closes other open auto popovers (unless they are nested or ancestral). |
popover="manual" | No light-dismiss. Must be closed explicitly via popovertarget or JavaScript. |
popover="hint" | Light-dismiss enabled. Hint popovers do not close auto popovers — allowing a tooltip to appear while a menu or dialog popover is still open. Only one hint popover can be open at a time. Ideal for tooltips. |
Keyboard interaction
Section titled “Keyboard interaction”| Key | Action |
|---|---|
| Tab | Moves focus into and out of the popover. For auto and hint popovers the browser updates the tab order automatically. |
| Escape | Closes the popover (light-dismiss). When using popover="manual", implement this yourself or use a CloseWatcher. |
Screen readers
Section titled “Screen readers”- Always provide an accessible name. Use
aria-label,aria-labelledby, or a visible title inside the popover bubble. - For tooltips, ensure the trigger has
aria-describedbypointing to the tooltip’sidso the description is announced when the trigger receives focus. - For dialog popovers, set
aria-expandedon the trigger to communicate the open / closed state.
Focus behaviour
Section titled “Focus behaviour”Tooltip
Section titled “Tooltip”- The Tooltip appears when its trigger element receives focus or hover.
- The Tooltip never receives focus itself — focus must always remain on the trigger element.
- It disappears automatically when focus moves away, the element is blurred, or the user presses Escape.
- When the trigger regains focus, the Tooltip reappears automatically to preserve context.
- The focus indicator on the trigger must remain visible and clearly distinguishable while the Tooltip is active.
- Tooltips must contain only short, non-interactive text. If the content requires links, buttons, or other actions, use a Popover instead.
Popover
Section titled “Popover”- Focus starts on the trigger element — The trigger element (e.g. a button, icon, or link with
popovertarget) must receive focus first. The trigger must have a visible focus indicator. - When the popover opens — Focus stays on the trigger. The browser inserts the popover into the sequential focus navigation order so the next Tab moves into the popover content. The popover content must be associated with the trigger using
aria-labelledbyoraria-describedby. - While the popover is open — Tab moves through the focusable elements inside the popover. Pressing Tab past the last focusable element moves focus to the next focusable element after the trigger in document order, as if the popover were inline at that position — popovers are not focus-trapped. Pressing Escape closes the popover (light-dismiss). For
popover="auto", clicking outside the popover also closes it. - When the popover closes — Focus returns to the original trigger element automatically. The trigger’s focus ring should remain visible.