Skip to content

Conversation

@bleroux
Copy link
Contributor

@bleroux bleroux commented Nov 27, 2025

Description

This PR adds DropdownMenu.selectOnly. This property allows users to get the DropdownMenu behave as a 'select' component.
It is meant as a future replacement for DropdownMenu.requestFocusOnTap.

Motivation

On mobile, a dropdown menu widget is usually used as a ‘select’ widget because opening the keyboard for searching/filtering is not convenient.

In Flutter, this is currently implemented through DropdownMenu.requestFocusOnTap which defaults to false on mobile and true on desktop.
The DropdownMenu.requestFocusOnTap property is currently used to set FocusNode.canRequestFocus. This leads do difficulties mainly related to focus traversal:

  • Keyboard traversal requires workarounds (for instance relying on the trailing icon to be focusable).
  • Keyboard shortcuts require also a workaround (currently relying on a Focus widget in a Stack).
  • The DropdownMenu decoration does not reflect the focus state.

This PR proposes a new property named DropdownMenu.selectOnly which does not require DropdownMenu.requestFocusOnTap to be false to make the DropdownMenu behave like a select widget.

With this property the DropdownMenu:

In the future this property could be used as a replacement for DropdownMenu.requestFocusOnTap. For the moment, for compatibility, it does not replace DropdownMenu.requestFocusOnTap.

Related Issue

Fixes Allow DropdownMenu to be non-editable and focusable (select control)
Also related to Make DropdownMenu's trailing icon not focusable by default and [Material3] DropdownMenu Keyboard Accessibility.

Tests

  • Adds 9 tests.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Nov 27, 2025
Copy link
Contributor

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

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 introduces a selectOnly property to the DropdownMenu widget, which is a valuable addition for creating 'select'-like behavior, especially on mobile platforms. The implementation is clean and includes a good set of tests to verify the new functionality.

I have two suggestions for improvement:

  1. The documentation for the new selectOnly property could be more explicit about its purpose and how it interacts with focusability.
  2. When selectOnly is true, the left and right arrow keys still allow cursor movement within the text field, which is inconsistent with a 'select' component. I've suggested a change to disable this behavior.

Overall, this is a great enhancement to the DropdownMenu widget.

@bleroux bleroux force-pushed the add_DropdownMenu.selectOnly branch from c21de33 to f75007c Compare November 27, 2025 22:19
@bleroux bleroux requested a review from QuncCccccc November 28, 2025 09:28
Copy link
Contributor

@QuncCccccc QuncCccccc left a comment

Choose a reason for hiding this comment

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

Sorry, I'm still a bit confused. What's the difference between this new API and requestFocusOnTap? Feels like super similar:)

@bleroux
Copy link
Contributor Author

bleroux commented Dec 2, 2025

Sorry, I'm still a bit confused. What's the difference between this new API and requestFocusOnTap? Feels like super similar:)

Yes, they are very similar because selectOnly is meant as a future replacement for requestFocusOnTap.
requestFocusOnTap has several drawbacks:

  • Keyboard traversal requires workarounds (for instance relying on the trailing icon to be focusable).
  • Keyboard shortcuts require also a workaround (currently relying on a Focus widget in a Stack).
  • The DropdownMenu decoration does not reflect the focus state.

@bleroux bleroux force-pushed the add_DropdownMenu.selectOnly branch from f75007c to 4b73da3 Compare December 2, 2025 10:24
@bleroux bleroux requested a review from QuncCccccc December 2, 2025 10:26
@QuncCccccc
Copy link
Contributor

requestFocusOnTap has several drawbacks:

Are there a way to just keep the current API (requestFocusOnTap) and add the behaviors by updating the implementation? Just feel deprecating an API and replacing it with a similar one might not be a good practice.

@bleroux
Copy link
Contributor Author

bleroux commented Dec 3, 2025

Are there a way to just keep the current API (requestFocusOnTap) and add the behaviors by updating the implementation?

While both properties target a similar use case: selecting an entry without editing the text field (so without opening the virtual keyboard on mobile), there is a main difference which is that requestFocusOnTap achieves this by not allowing the component to be focused, selectOnly does not prevent the component to be focused (it is mainly mapped to TextField.readOnly).

Maybe We can summarize this with:

requestFocusOnTap = selectOnly + canRequestFocus

(just for illustration because at the boolean level it is not correct 😅 )

Changing the current requestFocusOnTap behaviors would be problematic as the name will directly contradict the implementation (even when false the component will get the focus). Also it will break a lot of existing tests which assume that the DropdownMenu is not focusable at all when requestFocusOnTap is false.

I think both properties can coexist for the moment and at one time we might consider that requestFocusOnTap is only canRequestFocus and that it could be deprecated as one can rely on FocusNode.canRequestFocus. But to do so we first need to separate the behaviors related to the 'select' use case, this is what this PR does by adding this new DropdownMenu.selectOnly property.

@QuncCccccc
Copy link
Contributor

Got it. Yeah, it makes sense to me and requestFocusOnTap = selectOnly + canRequestFocus definitely make it easier to understand XD. Thanks for your explanation!

Copy link
Contributor

@QuncCccccc QuncCccccc left a comment

Choose a reason for hiding this comment

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

LGTM:) Thanks!

@bleroux bleroux force-pushed the add_DropdownMenu.selectOnly branch from 4b73da3 to 5b5d726 Compare December 4, 2025 08:23
@bleroux bleroux force-pushed the add_DropdownMenu.selectOnly branch from 5b5d726 to 617c47f Compare December 4, 2025 10:42
@bleroux bleroux added the autosubmit Merge PR when tree becomes green via auto submit App label Dec 4, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Dec 4, 2025
Merged via the queue into flutter:master with commit aa4f528 Dec 4, 2025
71 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Dec 4, 2025
@bleroux bleroux deleted the add_DropdownMenu.selectOnly branch December 4, 2025 14:50
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Dec 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Dec 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Dec 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Dec 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Dec 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Dec 4, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Dec 5, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Dec 5, 2025
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Dec 5, 2025
Roll Flutter from 69d8710fadcd to 5b8720312a94 (42 revisions)

flutter/flutter@69d8710...5b87203

2025-12-05 [email protected] Roll Packages from d39e481 to b17d3ff (3 revisions) (flutter/flutter#179505)
2025-12-05 [email protected] Move target_cpu into use_rbe block in Fuchsia build (flutter/flutter#179458)
2025-12-05 [email protected] Roll Skia from fe6bf18a3f6b to a31411879251 (3 revisions) (flutter/flutter#179499)
2025-12-05 [email protected] Force WASM single threading in Chrome extensions. (flutter/flutter#179400)
2025-12-05 [email protected] Roll Skia from aea282ea0bcd to fe6bf18a3f6b (7 revisions) (flutter/flutter#179489)
2025-12-05 [email protected] fix: check both pointer count and action before reusing MotionEvent (flutter/flutter#178528)
2025-12-05 [email protected] Roll Fuchsia Linux SDK from VtDPX2k1kosHxjKUE... to vDeTl_KBeLJY8nCAx... (flutter/flutter#179478)
2025-12-05 [email protected] [ Widget Preview ] Add embedded Widget Inspector support (flutter/flutter#178116)
2025-12-05 [email protected] bubble up fragment shader errors (flutter/flutter#179363)
2025-12-05 [email protected] Roll Dart SDK from eda82318e193 to 42fe3327abca (1 revision) (flutter/flutter#179472)
2025-12-05 [email protected] [Android 16] Use AVD With New Android Renderer (flutter/flutter#179306)
2025-12-05 [email protected] Unpin `package:dwds` dependency (flutter/flutter#179462)
2025-12-05 [email protected] [Impeller] include uniform info in impellerc json reflections (flutter/flutter#179317)
2025-12-05 [email protected] Roll Skia from 1591b066f49b to aea282ea0bcd (1 revision) (flutter/flutter#179468)
2025-12-04 [email protected] Roll Skia from e1923478562b to 1591b066f49b (3 revisions) (flutter/flutter#179460)
2025-12-04 [email protected] Cherry-pick flutter 3.38.4 changelog back to master. (flutter/flutter#179463)
2025-12-04 [email protected] [web] Add clone method to LayerPicture and dispose pictures in PictureLayer (flutter/flutter#179162)
2025-12-04 [email protected] Fixes merge conflict from high bitrate texture tests (flutter/flutter#179416)
2025-12-04 [email protected] Fix typos in `VirtualDisplayController.java` (flutter/flutter#179411)
2025-12-04 [email protected] Roll Dart SDK from 2de44cc08970 to eda82318e193 (1 revision) (flutter/flutter#179453)
2025-12-04 [email protected] Roll Skia from 55d94a54f453 to e1923478562b (1 revision) (flutter/flutter#179449)
2025-12-04 [email protected] Roll Packages from 8cb4903 to d39e481 (8 revisions) (flutter/flutter#179451)
2025-12-04 [email protected] Add DropdownMenu.selectOnly (flutter/flutter#179189)
2025-12-04 [email protected] Roll Dart SDK from 7e6bfc6af55c to 2de44cc08970 (6 revisions) (flutter/flutter#179443)
2025-12-04 [email protected] Roll Skia from b8f79d7316c0 to 55d94a54f453 (1 revision) (flutter/flutter#179439)
2025-12-04 [email protected] Revise README for link updates and terminology changes (flutter/flutter#179357)
2025-12-04 [email protected] Roll Skia from ce19122e3982 to b8f79d7316c0 (3 revisions) (flutter/flutter#179436)
2025-12-04 [email protected] Update some BottomNavigationBar comments to reflect theme normalization (flutter/flutter#179404)
2025-12-04 [email protected] Replace use of eglCreateImage with eglCreateImageKHR to reduce EGL requirement (flutter/flutter#179310)
2025-12-04 [email protected] Roll Skia from 81a9a0751f00 to ce19122e3982 (5 revisions) (flutter/flutter#179430)
2025-12-04 [email protected] [impellerc] adds entry prefix flag to avoid shader collisions (flutter/flutter#179160)
2025-12-04 [email protected] [Windows] Allow apps to prefer high power GPUs (flutter/flutter#177653)
2025-12-04 [email protected] [ Infra ] Shard `Windows tool_tests_commands` (flutter/flutter#179409)
2025-12-04 [email protected] [flutter_tools] Fix filename typo (flutter/flutter#179427)
2025-12-04 [email protected] Marks Linux_pixel_7pro draw_arcs_all_stroke_styles_perf__timeline_summary to be unflaky (flutter/flutter#179392)
2025-12-03 [email protected] Marks Mac_ios draw_arcs_all_fill_styles_perf_ios__timeline_summary to be unflaky (flutter/flutter#179391)
2025-12-03 [email protected] Marks Linux_pixel_7pro draw_arcs_all_fill_styles_perf__timeline_summary to be unflaky (flutter/flutter#179390)
2025-12-03 [email protected] Roll Abseil to 564023aa5376 (flutter/flutter#179421)
2025-12-03 [email protected] Made wide gamut tests give more information in their failure (flutter/flutter#179415)
2025-12-03 [email protected] Roll Skia from c20f797ab6f9 to 81a9a0751f00 (5 revisions) (flutter/flutter#179417)
2025-12-03 [email protected] Migrate samples and docs to RadioGroup (flutter/flutter#179158)
2025-12-03 [email protected] Roll Dart SDK to 3.11.0-200.1.beta (flutter/flutter#179399)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
...
reidbaker pushed a commit to AbdeMohlbi/flutter that referenced this pull request Dec 10, 2025
## Description

This PR adds `DropdownMenu.selectOnly`. This property allows users to
get the DropdownMenu behave as a 'select' component.
It is meant as a future replacement for
`DropdownMenu.requestFocusOnTap`.

## Motivation

On mobile, a dropdown menu widget is usually used as a ‘select’ widget
because opening the keyboard for searching/filtering is not convenient.

In Flutter, this is currently implemented through
`DropdownMenu.requestFocusOnTap` which defaults to false on mobile and
true on desktop.
The `DropdownMenu.requestFocusOnTap` property is currently used to set
`FocusNode.canRequestFocus`. This leads do difficulties mainly related
to focus traversal:
- Keyboard traversal requires workarounds (for instance relying on the
trailing icon to be focusable).
- Keyboard shortcuts require also a workaround (currently relying on a
Focus widget in a Stack).
- The `DropdownMenu` decoration does not reflect the focus state.

This PR proposes a new property named `DropdownMenu.selectOnly` which
does not require `DropdownMenu.requestFocusOnTap` to be false to make
the `DropdownMenu` behave like a select widget.

With this property the `DropdownMenu`:
- Supports keyboard navigation on mobile and desktop.
- Has a correct decoration when focused.
- Does not rely on the trailing icon to be focusable (see
flutter#174096).

In the future this property could be used as a replacement for
`DropdownMenu.requestFocusOnTap`. For the moment, for compatibility, it
does not replace `DropdownMenu.requestFocusOnTap`.

## Related Issue

Fixes [Allow DropdownMenu to be non-editable and focusable (select
control) ](flutter#178009)
Also related to [Make DropdownMenu's trailing icon not focusable by
default](flutter#174096) and
[[Material3] DropdownMenu Keyboard
Accessibility](flutter#123797).


## Tests

- Adds 9 tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow DropdownMenu to be non-editable and focusable (select control)

2 participants