reaction_overlay 0.1.0 copy "reaction_overlay: ^0.1.0" to clipboard
reaction_overlay: ^0.1.0 copied to clipboard

A floating reaction bar (like iMessage/WhatsApp) for Flutter. Wrap any widget to add emoji reactions with animations, haptic feedback, dark mode, and smart positioning.

Reaction Overlay #

A floating reaction bar for Flutter, inspired by WhatsApp and iMessage. It anchors to any widget and provides quick reactions, an emoji picker, adaptive positioning, accessibility, and light/dark theme support.

Installation #

dependencies:
  reaction_overlay: ^0.1.0
import 'package:reaction_overlay/reaction_overlay.dart';

Quick start #

Wrap a message, or any widget, with ReactionTarget. Long press it to open the reaction bar.

ReactionTarget(
  reactions: [
    Reaction('👍', label: 'Like', onTap: () => saveReaction('👍')),
    Reaction('❤️', label: 'Love', onTap: () => saveReaction('❤️')),
    Reaction('😂', label: 'Funny', onTap: () => saveReaction('😂')),
  ],
  child: const MessageBubble(text: 'Hello'),
)

ReactionTarget does not require a GlobalKey: it uses the widget's BuildContext to calculate its position.

WhatsApp-style double tap and full bar #

Set quickReactionIndex to react immediately on double tap. Long press still opens the full reaction picker.

ReactionTarget(
  reactions: ReactionSet.standard.reactions,
  quickReactionIndex: 0, // 👍
  onReactionChanged: (index, reaction) {
    saveReaction(reaction.emoji!);
  },
  child: MessageBubble(text: message.text),
)

If you do not set quickReactionIndex, TriggerMode.doubleTap opens the full reaction bar instead.

Centralized configuration #

Use ReactionOverlayConfig when you reuse the same configuration or want to keep ReactionOverlay.show calls readable.

final messageReactions = ReactionOverlayConfig(
  reactions: ReactionSet.social.reactions,
  position: OverlayPosition.auto,
  maxVisibleButtons: 6,
  dimBackground: true,
  showExpandButton: true,
  recentEmojis: const ['👍', '❤️', '🙏'],
  enableDragPreview: true,
  enableSelectionParticles: false,
);

ReactionOverlay.show(
  context: context,
  config: messageReactions,
  onReactionChanged: (index, reaction) {
    saveReaction(reaction.emoji!);
  },
  onDismissed: () => debugPrint('Reaction picker closed'),
);

Do not mix config with individual styling parameters in ReactionOverlay.show; use the centralized configuration as the source of truth for those values. Callbacks passed to the method (onDismissed, onReactionChanged, and onEmojiSelected) can be supplied normally.

Common configuration options #

Option Default Purpose
reactions required The list of Reaction objects shown in the bar.
position OverlayPosition.auto Position: auto, above, below, left, or right.
maxVisibleButtons 6 Maximum before horizontal navigation appears.
showExpandButton true Opens the full emoji panel.
recentEmojis [] Emojis shown first in the full panel.
dimBackground / dimColor true / 20% black Controls the background behind the bar.
enableDragPreview true Magnifies the reaction under the finger while dragging.
enableSelectionParticles true Shows particles on selection; disable for a quieter style.
allowMultipleSelections false Keeps the picker open after a selection.

Buttons keep a minimum 48×48 px tap target even if buttonSize or buttonHeight is smaller. The package also respects the system's reduce-motion preference.

Show the overlay manually #

Use ReactionOverlay.show when you provide your own gesture. The context must belong to a widget that has already been laid out.

GestureDetector(
  onTap: () {
    ReactionOverlay.show(
      context: context,
      reactions: [Reaction('👍'), Reaction('❤️')],
      position: OverlayPosition.above,
      onReactionChanged: (index, reaction) => saveReaction(reaction.emoji!),
    );
  },
  child: const MessageBubble(text: 'Tap me'),
)

Custom reactions and presets #

final reactions = [
  Reaction('👍', label: 'Like'),
  Reaction.custom(
    child: const Icon(Icons.star, color: Colors.amber),
    label: 'Favorite',
  ),
];

// Presets: standard, social, work, gaming, and minimal.
final socialReactions = ReactionSet.social.reactions;

Global theme #

Configure visual values that apply to all ReactionTarget widgets.

MaterialApp(
  theme: ThemeData(
    extensions: const [
      ReactionOverlayThemeData(
        position: OverlayPosition.above,
        enableHapticFeedback: true,
        buttonSize: 44,
        buttonHeight: 48,
      ),
    ],
  ),
  home: const ChatPage(),
)

Properties passed directly to ReactionTarget take precedence over this theme.

Programmatic control #

ReactionOverlayController lets you inspect visibility and the most recently selected reaction.

final controller = ReactionOverlayController();

controller.show(
  context: context,
  reactions: ReactionSet.standard.reactions,
);

// controller.isVisible
// controller.selectedReaction
controller.dismiss();

// Call dispose when the controller is no longer needed.
controller.dispose();

Migrating from 0.0.3 #

Version 0.1.0 simplifies the API and removes manual key management.

In 0.0.3 In 0.1.0
AppReactionOverlayManager ReactionOverlay.show, ReactionTarget, or ReactionOverlayController.
itemKey / itemId Remove these parameters; pass the BuildContext to ReactionOverlay.show or use ReactionTarget.
List<IconButton> buttons List<Reaction> reactions.
Manually building the overlay ReactionTarget for the usual case.

1. Replace IconButton with Reaction #

Previously, reactions were built with IconButton widgets. Use the simpler model now:

// 0.0.3
final buttons = [
  IconButton(icon: const Icon(Icons.thumb_up), onPressed: onLike),
];

// 0.1.0
final reactions = [
  Reaction('👍', label: 'Like', onTap: onLike),
];

To keep a custom icon, use Reaction.custom:

Reaction.custom(
  child: const Icon(Icons.thumb_up),
  label: 'Like',
  onTap: onLike,
)

2. Remove GlobalKey, itemKey, and itemId #

Instead of managing position through a key, wrap the content:

// 0.1.0
ReactionTarget(
  reactions: reactions,
  child: MessageBubble(text: message.text),
)

If you need to open the picker from your own gesture, call ReactionOverlay.show with that widget's context, as shown above.

3. Replace the manager #

Replace AppReactionOverlayManager with one of these options:

  • ReactionTarget: recommended declarative integration.
  • ReactionOverlay.show: when you already have a gesture callback.
  • ReactionOverlayController: when another part of your app needs to close, toggle, or observe the overlay.

Accessibility and interaction #

  • Long press opens the reaction bar; quick double tap is optional.
  • Left/right arrows navigate, Enter/Space selects, and Escape closes.
  • Give every Reaction a label so screen readers announce a useful action.
  • Use onReactionChanged to synchronize a selection with your backend.

Demo #

See the example directory for a demo application.

Reaction Overlay demo

Author #

GitHub: Ignaciomanchu1998

4
likes
160
points
82
downloads

Documentation

API reference

Publisher

verified publisherignacio-manchu.com

Weekly Downloads

A floating reaction bar (like iMessage/WhatsApp) for Flutter. Wrap any widget to add emoji reactions with animations, haptic feedback, dark mode, and smart positioning.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on reaction_overlay