Skip to content

[material_ui] Add tertiary tap callbacks to InkResponse and InkWell - #12676

Open
Ahtsham0715 wants to merge 2 commits into
flutter:mainfrom
Ahtsham0715:inkwell-tertiary-tap
Open

[material_ui] Add tertiary tap callbacks to InkResponse and InkWell#12676
Ahtsham0715 wants to merge 2 commits into
flutter:mainfrom
Ahtsham0715:inkwell-tertiary-tap

Conversation

@Ahtsham0715

@Ahtsham0715 Ahtsham0715 commented Aug 28, 2026

Copy link
Copy Markdown

Ported from flutter/flutter#191971, which was opened against flutter/flutter before I noticed the Material code freeze (flutter/flutter#188444). That PR has been closed in favour of this one.

GestureDetector exposes onTertiaryTapDown, onTertiaryTapUp and onTertiaryTapCancel, but InkResponse/InkWell only forward the primary and secondary button callbacks. That means a middle click on an InkWell — the usual way to open a link in a new tab or window on desktop and web — can't be handled without wrapping the widget in a second gesture detector, which then has to be reconciled with the ink splash.

This PR adds the three tertiary callbacks to InkResponse and InkWell, mirroring the existing secondary button plumbing:

  • The pressed highlight and ink splash start on tertiary tap down and are resolved on tap up or cancel, exactly as they are for the secondary button.
  • The tertiary button is only listened for when onTertiaryTapDown or onTertiaryTapUp is non-null, so widgets that don't opt in behave exactly as before (no splash on middle click, same as today).
  • onTertiaryTapCancel alone does not enable the button, which matches how onSecondaryTapCancel already behaves.

There is no onTertiaryTap because TapGestureRecognizer/GestureDetector don't have one; onTertiaryTapUp is the completion signal for that button.

This follows the approach suggested in the issue: a specific widget with a concrete use case, rather than a general reworking of the button callback pattern.

Tests added to packages/material_ui/test/ink_well_test.dart:

  • InkWell tertiary tap test — verifies the down/up ordering on a completed middle click, and down/cancel when the pointer is dragged away.
  • InkWell tertiary tap highlights only when a tertiary callback is defined — verifies the pressed highlight is raised and lowered on a tertiary press when a tertiary callback is supplied, and that a tertiary press is ignored when one is not.

A pending changelog entry is included with a minor version bump, since this is additive API.

Fixes flutter/flutter#129058

Pre-Review Checklist

`GestureDetector` exposes `onTertiaryTapDown`, `onTertiaryTapUp` and
`onTertiaryTapCancel`, but `InkResponse`/`InkWell` only forwarded the
primary and secondary button callbacks. This meant a middle click on an
`InkWell` (a common way to open a link in a new tab or window) could not
be handled without wrapping the widget in another gesture detector.

This adds the three tertiary callbacks, mirroring the existing secondary
button plumbing: the ink splash and pressed highlight are started on
tertiary tap down and resolved on tap up or cancel, and the widget only
listens for the tertiary button when at least one of
`onTertiaryTapDown`/`onTertiaryTapUp` is provided, so existing widgets
are unaffected.

Fixes flutter/flutter#129058
@Ahtsham0715
Ahtsham0715 marked this pull request as ready for review August 28, 2026 17:21

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for tertiary (middle-click) tap gestures (onTertiaryTapDown, onTertiaryTapUp, and onTertiaryTapCancel) to InkResponse and InkWell, along with corresponding tests and a changelog entry. The reviewer suggests expanding the test coverage to verify that the highlight is correctly shown when only onTertiaryTapDown or both tertiary callbacks are provided, rather than only testing onTertiaryTapUp.

Comment on lines +2549 to +2566
Widget buildFrame({required bool withTertiaryCallback}) {
return Directionality(
textDirection: TextDirection.ltr,
child: Material(
child: Center(
child: SizedBox(
width: 100.0,
height: 100.0,
child: InkWell(
onTap: () {},
onHighlightChanged: log.add,
onTertiaryTapUp: withTertiaryCallback ? (TapUpDetails details) {} : null,
),
),
),
),
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test is great for verifying that highlights are shown for tertiary taps only when a callback is provided. However, it only checks for the presence of onTertiaryTapUp. The logic in _tertiaryButtonEnabled also enables tertiary tap handling if onTertiaryTapDown is provided.

To make this test more comprehensive, consider parameterizing it to check that the highlight is correctly shown when:

  1. Only onTertiaryTapUp is provided.
  2. Only onTertiaryTapDown is provided.
  3. Both are provided.
  4. Neither is provided (as is already tested).

This would provide stronger guarantees about the correctness of the enabling logic.

@github-actions github-actions Bot added p: material_ui triage-design Should be looked at in design triage labels Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p: material_ui triage-design Should be looked at in design triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

InkWell does not expose callbacks for handling tertiary taps

1 participant