RemixRemix
Overlays

Tooltip

A contextual overlay component for displaying helpful information on hover

Open catalog
Starting Flutter example…
Live Flutter from the pinned Remix component catalog. Examples include Fortal styling; the source tab shows the catalog code, not a standalone application.

A contextual overlay component for displaying helpful information when hovering.

When to use this

  • Additional information: Provide extra context or details on hover
  • Icon explanations: Explain the purpose of icons or buttons
  • Truncated text: Show full text when space is limited
  • Help text: Offer guidance or tips to users

Basic implementation

Basic implementation

import 'package:flutter/material.dart';
import 'package:remix/remix.dart';

class TooltipExample extends StatelessWidget {
  const TooltipExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      spacing: 24,
      children: [
        RemixTooltip(
          tooltipChild: const Text('Default tooltip'),
          style: styleDefault,
          child: const _TriggerButton(label: 'Default'),
        ),
        RemixTooltip(
          tooltipChild: const Text('Quick tooltip!'),
          style: styleFast,
          child: const _TriggerButton(label: 'Fast'),
        ),
        RemixTooltip(
          tooltipChild: const Text('Slow tooltip'),
          style: styleSlow,
          child: const _TriggerButton(label: 'Slow'),
        ),
      ],
    );
  }

  TooltipStyler get styleDefault {
    return TooltipStyler()
        .padding(EdgeInsetsGeometryMix.symmetric(horizontal: 12, vertical: 8))
        .color(Colors.black87)
        .borderRadius(BorderRadiusGeometryMix.all(const Radius.circular(6)))
        .wrap(.defaultTextStyle(style: TextStyleMix().color(Colors.white).fontSize(14)));
  }

  TooltipStyler get styleFast {
    return styleDefault
        .waitDuration(const Duration(milliseconds: 100))
        .showDuration(const Duration(milliseconds: 800)) // touch wait
        .dismissDuration(const Duration(milliseconds: 100)); // hover exit
  }

  TooltipStyler get styleSlow {
    return styleDefault
        .waitDuration(const Duration(seconds: 1))
        .showDuration(const Duration(seconds: 3));
  }
}

class _TriggerButton extends StatelessWidget {
  const _TriggerButton({required this.label});

  final String label;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      decoration: BoxDecoration(
        color: Colors.blue,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(label, style: const TextStyle(color: Colors.white)),
    );
  }
}

Imperative visibility

RemixTooltip and FortalTooltip open automatically on hover, keyboard focus, and touch long-press. Only one tooltip is visible at a time: opening another, by any of these or by tooltipKey, replaces the visible one at once.

To show a tooltip imperatively, pass a GlobalKey<RawTooltipState> to tooltipKey and call tooltipKey.currentState?.ensureTooltipVisible(). Use onOpenChanged to observe visibility changes.

When closed, the tooltip delegates the Escape key to enclosing DismissIntent actions, allowing a parent drawer or menu to close. When open, pressing Escape closes the tooltip and keeps focus on the trigger.

Reduced motion

The tooltip shows and hides at once when the user asks to reduce motion: MediaQuery.disableAnimations is set, or the platform's Reduce Motion setting is on (iOS reports it separately). A change applies to the next show or hide, and a tooltip that has not been shown yet when the setting is turned off may still show once without motion.

Fortal widgets

The application-owned Fortal preset provides a themed widget for this component:

Fortal widget

import 'package:flutter/material.dart';
import 'ui/ui.dart';

class FortalTooltipExample extends StatelessWidget {
  const FortalTooltipExample({super.key});

  @override
  Widget build(BuildContext context) {
    return Row(
      spacing: 16,
      children: [
        FortalTooltip(
          tooltipChild: const Text('Information tooltip'),
          child: const Icon(Icons.info),
        ),
        FortalTooltip(
          tooltipChild: const Text('Help tooltip'),
          child: const Icon(Icons.help),
        ),
      ],
    );
  }
}

See the fortalTooltipStyle source code for all available options.

Constructor

Constructor

import 'package:flutter/material.dart';
import 'package:remix/remix.dart';

RemixTooltip remixTooltipConstructor({
  Key? key,
  required Widget tooltipChild,
  required Widget child,
  GlobalKey<RawTooltipState>? tooltipKey,
  ValueChanged<bool>? onOpenChanged,
  String? tooltipSemantics,
  OverlayPositionConfig positioning = const OverlayPositionConfig(),
  TooltipStyler style = const TooltipStyler.create(),
  TooltipSpec? styleSpec,
}) => throw UnimplementedError();

Properties

Widget Properties

key → Key?

Optional. Controls how one widget replaces another widget in the tree.

style → TooltipStyler

Optional. The style configuration for the tooltip.

styleSpec → TooltipSpec?

Optional. The style spec for the tooltip.

tooltipChild → Widget

Required. The widget to display in the tooltip.

child → Widget

Required. The child widget that triggers the tooltip.

tooltipKey → GlobalKey<RawTooltipState>?

Optional. A key for imperative control via RawTooltipState.ensureTooltipVisible.

onOpenChanged → ValueChanged<bool>?

Optional. A callback invoked when the tooltip visible state changes.

tooltipSemantics → String?

Optional. The semantic label for the tooltip.

positioning → OverlayPositionConfig

Optional. The overlay positioning configuration.

Style Methods

container(BoxStyler value)

Sets the tooltip container style.

label(TextStyler value)

Sets the tooltip label style.

padding(EdgeInsetsGeometryMix value)

Sets the container padding.

margin(EdgeInsetsGeometryMix value)

Sets the container margin.

alignment(Alignment value)

Sets the container alignment.

color(Color value)

Sets the container background color.

borderRadius(BorderRadiusGeometryMix radius)

Sets the container border radius.

decoration(DecorationMix value)

Sets the container decoration.

waitDuration(Duration value)

Sets the wait duration before showing the tooltip.

showDuration(Duration value)

Sets the touch long-press wait duration (NakedTooltip.touchDelay).

dismissDuration(Duration value)

Sets the hover-exit dismiss delay (NakedTooltip.dismissDelay).

wrap(WidgetModifierConfig value)

Applies widget modifiers such as clipping, opacity, or scaling.

animate(AnimationConfig value)

Configures implicit animation for style transitions.

variants(List<VariantStyle<TooltipSpec>> value)

Sets style variants.

constraints(BoxConstraintsMix value)

Sets size constraints on the component.

foregroundDecoration(DecorationMix value)

Sets a foreground decoration painted on top of the component.

transform(Matrix4 value, AlignmentGeometry alignment = Alignment.center)

Applies a matrix transformation to the component.

modifier(WidgetModifierConfig value)

Sets the widget modifier.

call({Key? key, required Widget tooltipChild, required Widget child, GlobalKey<RawTooltipState>? tooltipKey, ValueChanged<bool>? onOpenChanged, String? tooltipSemantics, OverlayPositionConfig positioning = const OverlayPositionConfig()})

Creates a RemixTooltip widget with this style applied.

View page source on GitHub