Skip to content

Add ContextMenuButtonKind - #193528

Merged
auto-submit[bot] merged 6 commits into
flutter:masterfrom
LouiseHsu:context-menu-button-kind
Oct 14, 2026
Merged

auto-submit[bot] merged 6 commits into
flutter:masterfrom
LouiseHsu:context-menu-button-kind

Conversation

@LouiseHsu

@LouiseHsu LouiseHsu commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

part of #193527

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant in-code documentation (doc comments with ///).
  • If this PR introduces a new feature or capability, I created and linked a website documentation issue or PR in [flutter/website] (or verified none is needed).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

…Type

Prototype of replacing the ContextMenuButtonType enum with an enum-like class
so new button kinds (e.g. translate) can be added without breaking exhaustive
switches in cupertino_ui/material_ui or apps.
@github-actions github-actions Bot added a: text input Entering text in a text field or keyboard related problems framework flutter/packages/flutter repository. See also f: labels. labels Sep 29, 2026
@LouiseHsu
LouiseHsu marked this pull request as ready for review September 29, 2026 22:19

@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 deprecates ContextMenuButtonType in favor of a new ContextMenuButtonKind class, updating ContextMenuButtonItem, EditableText, SelectableRegion, and SystemContextMenu to use the new kind representation. It also adds unit tests for these changes. The feedback requests updating the documentation comments on private members in ContextMenuButtonKind to use /// instead of // to align with the Flutter style guide.

Comment on lines +78 to +80
// The closest ContextMenuButtonType for this kind, used to keep the
// deprecated ContextMenuButtonItem.type working. Kinds with no matching
// ContextMenuButtonType map to ContextMenuButtonType.custom.

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

According to the Flutter style guide, public-quality documentation (///) should be used even for private members. Please update this comment to use /// instead of //.

  /// The closest ContextMenuButtonType for this kind, used to keep the
  /// deprecated ContextMenuButtonItem.type working. Kinds with no matching
  /// ContextMenuButtonType map to ContextMenuButtonType.custom.
References
  1. Use /// for public-quality documentation, even on private members. (link)

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.

I agree here and elsewhere.

custom,
];

// Returns the kind that corresponds to a deprecated ContextMenuButtonType.

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

According to the Flutter style guide, public-quality documentation (///) should be used even for private members. Please update this comment to use /// instead of //.

  /// Returns the kind that corresponds to a deprecated ContextMenuButtonType.
References
  1. Use /// for public-quality documentation, even on private members. (link)

LouiseHsu added a commit to LouiseHsu/packages that referenced this pull request Sep 30, 2026
…Kind

Requires flutter/flutter#193528. Not for landing until that reaches stable.

@justinmc justinmc 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.

Looks good minus a few small comments. Was there a discussion somewhere about the choice to make this a final class to handle the breaking change? I agree, but I wanted to catch up on what you and others were thinking about it.

Comment on lines +78 to +80
// The closest ContextMenuButtonType for this kind, used to keep the
// deprecated ContextMenuButtonItem.type working. Kinds with no matching
// ContextMenuButtonType map to ContextMenuButtonType.custom.

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.

I agree here and elsewhere.

/// All of the kinds currently known to this version of Flutter.
///
/// New kinds may be added to this list in the future.
static const List<ContextMenuButtonKind> values = <ContextMenuButtonKind>[

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.

Should this be a Set?

@LouiseHsu LouiseHsu Oct 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I kept this as a List b/c Dart enums automatically generate static const List<T> values, so I feel that when we finally do this migration, it will be easier without any type mismatches!

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.

Sounds good.

/// * [ContextMenuButtonItem], which uses this class to describe a button in a
/// context menu.
@immutable
final class ContextMenuButtonKind {

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.

New kinds may be added in the future

Do you have any in mind in particular? I think we may end up adding some if/when Android goes down this path as well, so I agree with the choice.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is specifically for the Translate context menu work, if thats what you mean. Besides translate iOS also has other context menu items we may want to implement in the future (e.g. AutoFill, Writing Tools, Find/Replace), in addition to Android actions down the line

@dkwingsmt

Copy link
Copy Markdown
Contributor

I think we should not add the deprecation in this PR. cupertino_ui and material_ui currently support flutter: >=3.47.0, so they can't reference ContextMenuButtonKind until it reaches stable and they can bump their minimum. In the meantime they'd see deprecation warnings when tested against master with no way to resolve them.

I propose a phased transition:

  1. This PR adds ContextMenuButtonKind (including translate) without deprecating ContextMenuButtonType. The framework doesn't emit translate yet.
  2. Once this reaches stable, cupertino_ui and material_ui bump their Flutter minimum and switch from item.type to item.kind, handling translate with a localized label.
  3. After that, the framework deprecates ContextMenuButtonType and ContextMenuButtonItem.type, with data-driven fixes.
  4. Finally, the framework starts emitting translate. Older published versions of the design packages will see translate as custom. They render custom items using item.label and item.onPressed, so as long as the framework gives the item a localized label (e.g. a new WidgetsLocalizations.translateButtonLabel) and an onPressed that calls Translate.invoke, the button still works there, just without platform-specific wording.

@dkwingsmt

dkwingsmt commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

I agree with making it final with a private constructor. Opening it up later (removing final or adding a public constructor), if necessary at all, is non-breaking, while closing it later would be breaking.

The only concern I might have is if third-party packages want to tag their own buttons, and custom with a string label might not suffice. In such cases, we might add an Object? id to ContextMenuButtonItem, which serves that better than custom kinds, since custom kinds couldn't map to native menu items or be recognized by the design packages anyway. But such changes wouldn't be breaking and can be left to future PRs.

@LouiseHsu

Copy link
Copy Markdown
Contributor Author

I think we should not add the deprecation in this PR. cupertino_ui and material_ui currently support flutter: >=3.47.0, so they can't reference ContextMenuButtonKind until it reaches stable and they can bump their minimum. In the meantime they'd see deprecation warnings when tested against master with no way to resolve them.

I propose a phased transition:

  1. This PR adds ContextMenuButtonKind (including translate) without deprecating ContextMenuButtonType. The framework doesn't emit translate yet.
  2. Once this reaches stable, cupertino_ui and material_ui bump their Flutter minimum and switch from item.type to item.kind, handling translate with a localized label.
  3. After that, the framework deprecates ContextMenuButtonType and ContextMenuButtonItem.type, with data-driven fixes.
  4. Finally, the framework starts emitting translate. Older published versions of the design packages will see translate as custom. They render custom items using item.label and item.onPressed, so as long as the framework gives the item a localized label (e.g. a new WidgetsLocalizations.translateButtonLabel) and an onPressed that calls Translate.invoke, the button still works there, just without platform-specific wording.

This makes sense to me! Im not super familiar with the new cupertino/material packages processes 😅 Ill drop the deprecation in this PR.

@LouiseHsu
LouiseHsu requested a review from justinmc October 12, 2026 23:36
@LouiseHsu LouiseHsu changed the title Add ContextMenuButtonKind and deprecate ContextMenuButtonType Add ContextMenuButtonKind Oct 12, 2026
@LouiseHsu LouiseHsu added the CICD Run CI/CD label Oct 13, 2026

@justinmc justinmc 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.

LGTM 👍 . Good catch by @dkwingsmt, I agree that we shouldn't deprecate in this PR. Could you create an issue for the extra deprecation step, or maybe just add it to #193527?

@LouiseHsu LouiseHsu added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 13, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 13, 2026
@auto-submit

auto-submit Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/193528, because The base commit of the PR is older than 7 days and can not be merged. Please merge the latest changes from the main into this branch and resubmit the PR.

@LouiseHsu LouiseHsu added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 14, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Oct 14, 2026
Merged via the queue into flutter:master with commit 306a914 Oct 14, 2026
23 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 14, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Oct 15, 2026
flutter/flutter@426be96...5c7e45a

2026-10-15 [email protected] [web_paragraph] Honor TextHeightBehavior.leadingDistribution and default to proportional (flutter/flutter#193736)
2026-10-15 [email protected] Roll Skia from 79a00d7c4898 to d131b7789482 (2 revisions) (flutter/flutter#194446)
2026-10-15 [email protected] Roll Dart SDK from b8ffa9233096 to 84686ea04815 (1 revision) (flutter/flutter#194442)
2026-10-15 [email protected] Roll Dart SDK from e81af2dac9d1 to b8ffa9233096 (1 revision) (flutter/flutter#194432)
2026-10-15 [email protected] Roll Skia from ef24b8f87a2a to 79a00d7c4898 (4 revisions) (flutter/flutter#194431)
2026-10-15 [email protected] Roll Skia from 48c51004ee4e to ef24b8f87a2a (1 revision) (flutter/flutter#194427)
2026-10-15 [email protected] Roll Dart SDK from 6b50116630d0 to e81af2dac9d1 (5 revisions) (flutter/flutter#194422)
2026-10-15 [email protected] Roll Skia from b1be97266d3a to 48c51004ee4e (10 revisions) (flutter/flutter#194421)
2026-10-15 [email protected] RawAutocomplete: Fix focusNode listener mismatch in didUpdateWidget/dispose (flutter/flutter#190686)
2026-10-14 [email protected] [flutter_tools] Wait for iOS simulator log stream before launch (flutter/flutter#193142)
2026-10-14 [email protected] Move Material/Cupertino PRs from design triage to framework triage (flutter/flutter#194244)
2026-10-14 [email protected] refactor(flutter_tools): share FlutterCommand options and OptionBundles (flutter/flutter#194356)
2026-10-14 [email protected] Roll pub packages (flutter/flutter#194413)
2026-10-14 [email protected] Add ContextMenuButtonKind (flutter/flutter#193528)
2026-10-14 [email protected] Split SwiftPM plugin into multiple products (flutter/flutter#193521)
2026-10-14 [email protected] Roll Skia from 43d707a3be0e to b1be97266d3a (8 revisions) (flutter/flutter#194392)
2026-10-14 [email protected] Roll pub packages (flutter/flutter#194398)
2026-10-14 [email protected] [flutter_tools] Migrate AndroidSdk and AndroidStudio away from globals (flutter/flutter#193650)
2026-10-14 [email protected] [flutter_tools] Reload widget-preview when data assets change (flutter/flutter#193437)
2026-10-14 [email protected] [flutter tool] suppress sub-tool analytics during first run (flutter/flutter#194320)
2026-10-14 [email protected] Roll Skia from acde3755d2e2 to 43d707a3be0e (1 revision) (flutter/flutter#194385)

If this roll has caused a breakage, revert this CL and set the roller
to dry run mode using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
@LouiseHsu LouiseHsu added the cp: stable cherry pick this pull request to stable release candidate branch label Oct 21, 2026
suryaKommana2662 pushed a commit to suryaKommana2662/flutter that referenced this pull request Oct 29, 2026
part of flutter#193527

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant in-code documentation (doc comments with
`///`).
- [x] If this PR introduces a new feature or capability, I created and
linked a website documentation issue or PR in [flutter/website] (or
verified none is needed).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.
@reidbaker reidbaker added the cp: beta cherry pick this pull request to beta release candidate branch label Nov 3, 2026
@reidbaker reidbaker mentioned this pull request Nov 3, 2026
2 of 5 tasks
auto-submit Bot pushed a commit that referenced this pull request Nov 3, 2026
This pull request is created by [automatic cherry pick workflow](https://github.com/flutter/flutter/blob/main/docs/releases/Flutter-Cherrypick-Process.md#automatically-creates-a-cherry-pick-request)

Cherry-pick of #193528 (already cherry-picked to `3.47.9` stable in #195015, ensuring `3.50` does not regress public API shipped in `3.47.9`).

Also includes `e58c176fe4` / `7d0aca2908` (`+12/-1`, test-only) restoring the `no-shuffle` tag on `packages/flutter/test/material/text_field_test.dart` (reverting #193550 and restoring `no-shuffle` in `packages/flutter/dart_test.yaml`) because `3.50` branched before #194256 fixed #194008 (`Theme._kFallbackTheme` platform caching across shuffled `TargetPlatformVariant` tests).

### Issue Link:
#193527
#194008

### Impact Description:
`ContextMenuButtonKind` and `ContextMenuButtonItem.kind` shipped in Flutter `3.47.9` stable (`#195015`) after `flutter-3.50-candidate.0` branched. Without cherry-picking `#193528` into `flutter-3.50-candidate.0`, packages and apps adopting `ContextMenuButtonKind` on `3.47.9` stable (including `cupertino_ui` and `material_ui` for iOS Translate context menu support in `#180021`) would fail to compile on `3.50.0`. The change itself is purely additive and does not deprecate `ContextMenuButtonType` or alter existing behavior. Restoring `no-shuffle` on `text_field_test.dart` unblocks `framework_tests_libraries` and `Mac framework_tests_impeller` on `flutter-3.50-candidate.0` under daily shuffled test seeds.

### Changelog Description:
- [flutter/193527](#193527) When building custom text selection menus, packages can't add new actions such as Translate without breaking exhaustive switches on `ContextMenuButtonType`; adds the extensible `ContextMenuButtonKind`.

### Workaround:
No.

### Risk:
What is the risk level of this cherry-pick?

### Test Coverage:
Are you confident that your fix is well-tested by automated tests?

### Validation Steps:
Run `flutter test test/widgets/context_menu_button_item_test.dart test/widgets/editable_text_test.dart test/widgets/selectable_region_test.dart test/widgets/system_context_menu_test.dart` and `flutter test --test-randomize-ordering-seed=20261103 --fatal-warnings test/material/text_field_test.dart` to verify `ContextMenuButtonKind` backwards compatibility and `text_field_test.dart` execution under shuffled seeds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: text input Entering text in a text field or keyboard related problems CICD Run CI/CD cp: beta cherry pick this pull request to beta release candidate branch cp: stable cherry pick this pull request to stable release candidate branch framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants