Skip to content

WPopover

View raw .md

A flexible popover component for creating dropdown menus, notification panels, user menus, tooltips, and similar overlay patterns.

On this page
Preview popover/popover_basic The live demo is not available for this example. popover_basic.dart View source
dart
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.

dart
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#

dart
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,
  double? width,
  double? maxWidth,
  bool disabled = false,
  bool closeOnContentTap = false,
  VoidCallback? onOpen,
  VoidCallback? onClose,
  bool autoFlip = true,
})

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.
width double? null Pins the overlay to a fixed width (like WSelect's menuWidth). Overrides a w-* token in className.
maxWidth double? null Upper bound for the overlay width. Falls back to a max-w-* token, then to the screen width, so the overlay never stretches off-screen. Ignored when a fixed width (or w-*) is set.
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.

Preview widgets/w_popover_alignment The live demo is not available for this example. w_popover_alignment.dart View source
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).

When enableTriggerOnTap is true (the default), tapping the trigger toggles the popover, and this works even when the trigger is an interactive widget that owns its own onTap (a WButton or WAnchor): the trigger's own callback and the popover toggle both fire on the same tap. Set enableTriggerOnTap: false for manual control via a PopoverController.

dart
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.

dart
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.

dart
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.

dart
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.

dart
WindThemeData(
  colors: {
    'popover-bg': Colors.white,
  },
  baseSpacingUnit: 4.0,
)
esc

Search index did not load.

No match for "".

Try a class like rounded-lg or a widget like WButton.