WPopover
A flexible popover component for creating dropdown menus, notification panels, user menus, tooltips, and similar overlay patterns.
- Basic Usage
- Constructor
- Props
- Layout Modes
- Event Handling
- State Variants
- Styling Examples
- All Supported Classes
- Customizing Theme
- Related Documentation
WPopover(
alignment: PopoverAlignment.bottomRight,
className: 'w-64 bg-white dark:bg-gray-800 rounded-xl shadow-xl p-2',
triggerBuilder: (context, isOpen, isHovering) => WButton(
className: 'bg-blue-600 text-white',
child: Text('Open Menu'),
),
contentBuilder: (context, close) => Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(title: Text('Profile'), onTap: close),
ListTile(title: Text('Settings'), onTap: close),
],
),
)
Basic Usage
The WPopover widget uses two builders: triggerBuilder for the element that activates the popover, and contentBuilder for the overlay content. It manages the overlay state and positioning automatically.
WPopover(
triggerBuilder: (context, isOpen, isHovering) => WText(
'Click me',
className: 'text-blue-500 cursor-pointer',
),
contentBuilder: (context, close) => WDiv(
className: 'p-4',
child: WText('Hello from Popover!'),
),
)
Constructor
const WPopover({
Key? key,
required PopoverTriggerBuilder triggerBuilder,
required PopoverContentBuilder contentBuilder,
PopoverController? controller,
bool enableTriggerOnTap = true,
PopoverAlignment alignment = PopoverAlignment.bottomLeft,
String? className,
Offset offset = const Offset(0, 4),
double maxHeight = 400,
bool disabled = false,
bool closeOnContentTap = false,
VoidCallback? onOpen,
VoidCallback? onClose,
})
Props
| Prop | Type | Default | Description |
|---|---|---|---|
triggerBuilder |
PopoverTriggerBuilder |
Required | Builder for the trigger widget. Receives isOpen and isHovering states. |
contentBuilder |
PopoverContentBuilder |
Required | Builder for the popover content. Receives a close callback. |
className |
String? |
null |
Wind utility classes for the popover container styling. |
controller |
PopoverController? |
null |
Optional controller for programmatic show/hide/toggle. |
alignment |
PopoverAlignment |
bottomLeft |
Where to position the popover relative to the trigger. |
offset |
Offset |
Offset(0, 4) |
Gap between the trigger and the popover. |
maxHeight |
double |
400 |
Maximum height for the content. It will scroll if exceeded. |
enableTriggerOnTap |
bool |
true |
Whether tapping the trigger toggles the popover. |
closeOnContentTap |
bool |
false |
Whether tapping inside the content closes the popover. |
disabled |
bool |
false |
When true, the trigger will not respond to interactions. |
onOpen |
VoidCallback? |
null |
Callback fired when the popover is opened. |
onClose |
VoidCallback? |
null |
Callback fired when the popover is closed. |
autoFlip |
bool |
true |
When true, the popover flips its alignment to the opposite side if the natural position would render off-screen. |
Layout Modes
While WPopover itself isn't a layout container, it supports various Alignment Modes to determine how the overlay is positioned relative to the trigger.
Alignment
WPopover intelligently "flips" the alignment if the requested position would cause the overlay to overflow the screen edges.
| Alignment | Description |
|---|---|
bottomLeft |
Below trigger, aligned to left edge (Default). |
bottomRight |
Below trigger, aligned to right edge. |
bottomCenter |
Below trigger, centered horizontally. |
topLeft |
Above trigger, aligned to left edge. |
topRight |
Above trigger, aligned to right edge. |
topCenter |
Above trigger, centered horizontally. |
Event Handling
The triggerBuilder provides the isOpen and isHovering states, allowing you to reactively style the trigger. The contentBuilder provides a close callback to dismiss the popover from within the content (e.g., when a menu item is clicked).
WPopover(
triggerBuilder: (context, isOpen, isHovering) => WDiv(
className: 'p-2 rounded ${isOpen ? "bg-blue-100" : "bg-gray-100"}',
child: WText(isOpen ? 'Active' : 'Idle'),
),
contentBuilder: (context, close) => WButton(
onTap: close,
child: Text('Click to Close'),
),
)
State Variants
Since the popover trigger is built via triggerBuilder, you can apply state-based styling manually or use Wind's state prefixes if the trigger is a Wind widget like WButton or WDiv.
WPopover(
triggerBuilder: (context, isOpen, isHovering) => WButton(
// Use the isOpen boolean for manual state toggling
className: 'p-2 rounded-lg ${isOpen ? "bg-blue-600 text-white" : "bg-white text-gray-800"}',
child: Text('Toggle Menu'),
),
contentBuilder: (context, close) => MyContent(),
)
Styling Examples
Custom Size and Shadow
If no width is specified in className, the popover uses the trigger's width as a minimum. Use sizing utilities to define a specific width.
WPopover(
className: 'w-80 bg-white rounded-2xl shadow-2xl border border-gray-100',
triggerBuilder: (context, isOpen, isHovering) => Icon(Icons.more_horiz),
contentBuilder: (context, close) => MyLargeMenu(),
)
Dark Mode
WPopover fully supports dark mode styling using the dark: prefix.
WPopover(
className: 'bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-800 shadow-xl',
triggerBuilder: (context, isOpen, isHovering) => MyTrigger(),
contentBuilder: (context, close) => MyContent(),
)
All Supported Classes
The popover overlay container is a WDiv and supports all standard Wind utilities.
| Category | Classes |
|---|---|
| Sizing | w-{size}, max-w-{size}, h-{size}, max-h-{size} |
| Background | bg-{color}, bg-opacity-{n} |
| Borders | border, border-{color}, rounded-{size} |
| Shadow | shadow-{size}, shadow-{color}/{opacity} |
| Padding | p-{n}, px-{n}, py-{n} |
Customizing Theme
Popovers inherit from global theme scales. You can customize the default appearance by modifying the WindThemeData.
WindThemeData(
colors: {
'popover-bg': Colors.white,
},
baseSpacingUnit: 4.0,
)