Patterns
Quick Actions
When to use:
- Several small actions should stay attached to one trigger.
Composition notes:
- Keep the content compact.
- Prefer action lists or short grouped commands over paragraph-heavy content.
- Control
openand close the popover when an action runs; it does not close on its own.
Trade-offs:
- Fast contextual access.
- Easy to overload with too many actions.
import { useState } from 'react';
import {
Button,
Popover,
PopoverContent,
PopoverTrigger,
Text,
} from '@vega-ui/react';
const actions = ['Duplicate', 'Move to folder', 'Download as PDF', 'Archive'];
export default function MenuClosesOnSelect() {Inline Rename Flow
When to use:
- A tiny form should stay near its trigger.
Composition notes:
- Keep validation and submit behavior simple.
Trade-offs:
- Efficient for small edits.
- Too small for longer form flows.
import { useId, useState, type CSSProperties, type FormEvent } from 'react';
import {
Button,
Heading,
Icon,
IconButton,
Label,
Popover,
PopoverContent,
PopoverTrigger,
TextField,
TextFieldInput,Anchored User Menu
When to use:
- Account or context actions should stay visibly attached to the trigger.
Composition notes:
- Keep the content narrow and scannable.
- Do not turn the menu into a full settings surface.
Trade-offs:
- Strong spatial relationship to the trigger.
- Weaker fit once the content becomes form-heavy or destructive.
import {
Button,
Popover,
PopoverContent,
PopoverTrigger,
Separator,
Text,
} from '@vega-ui/react';
export default function AnchoredUserMenu() {
return (
<Popover role='dialog' placement='bottom-end'>Comparison
Quick Decision Rule
Choose Popover when the content is contextual, brief, and should stay anchored to a trigger without becoming modal.
Popover vs Tooltip
Use Popover when:
- the content is richer than a simple hint
- it may contain actions or form controls
Use Tooltip when:
- the content is purely supplemental information
Popover vs Dialog
Use Popover when:
- the interaction is non-modal and lightweight
- the user should keep page context and not enter a trapped modal flow
Use Dialog when:
- the task needs stronger modal focus and containment
Popover vs Drawer
Use Popover when:
- the content is short and anchored
Use Drawer when:
- the content grows into a side-panel workflow
Choose This Component When
- the content is contextual and brief
- the UI should stay non-modal
- anchored placement is part of the interaction model
Do Not Choose This Component When
- the task is large, modal, or destructive enough to deserve a stronger overlay
Troubleshooting
Popover Feels Too Heavy
Symptom
The content technically works, but the overlay feels too big or modal.
Likely Cause
The task belongs in Dialog or Drawer.
How To Verify
- Review content length and task criticality.
Fix
- Switch to a stronger overlay when the flow is no longer lightweight.
Placement Breaks In Scroll Containers
Symptom
The floating layer feels detached from the trigger.
Likely Cause
The real container or overlay stack was not tested.
How To Verify
- Place the popover inside the real scrolling or clipped layout.
Fix
- Retest the exact production container structure.
PopoverContentrenders in the top layer, sooverflowandz-indexon ancestors do not clip or cover it; look at placement instead.
Nested Popovers Feel Confusing
Symptom
Open state and focus order become unclear with popovers inside popovers.
Likely Cause
Nested floating layers are being used for a task that needs a stronger pattern.
How To Verify
- Test nested open and close behavior.
Fix
- Simplify the flow or switch to a larger overlay pattern.
Trigger Meaning Is Unclear Without The Popover
Symptom
Users only understand the trigger after the popover opens.
Likely Cause
The trigger relies on floating content as its primary label or explanation.
How To Verify
- Hide the popover and inspect whether the trigger still makes sense.
- Test with keyboard and screen reader flows.
Fix
- Give the trigger its own accessible meaning.
- Keep popover content supplemental and contextual.
Popover Does Not Open From A Custom Trigger
Symptom
Clicking a custom PopoverTrigger asChild child does nothing.
Likely Cause
The child does not render a <button>, so the native popovertarget has no effect.
How To Verify
- Inspect the trigger element and check that it is a
<button>withpopovertarget.
Fix
- Use
Buttonor another component that renders a<button>as theasChildchild.