Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add focus support for CupertinoActionSheetAction #166398 #167119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

O-Hannonen
Copy link

This PR fixes #166398

  • Adds focus support for CupertinoActionSheetAction. This makes it work with keyboard shortcuts
  • Creates new widget, CupertinoTraversalGroup that applies a Cupertino style focus border around its child when any of its descendant has focus
  • Employs CupertinoTraversalGroup in CupertinoActionSheet

How the new implementation looks and behaves:
https://github.com/user-attachments/assets/ea6789f1-921d-4598-bcca-489dc063ff73

How the native counterpart looks and behaves:
https://github.com/user-attachments/assets/4c6ae2a0-7205-4de2-b981-ec7f4839da6e

Pre-launch Checklist

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: cupertino flutter/packages/flutter/cupertino repository f: focus Focus traversal, gaining or losing focus labels Apr 14, 2025
///
/// * <https://developer.apple.com/design/human-interface-guidelines/focus-and-selection/>
/// {@endtemplate}
class CupertinoTraversalGroup extends StatefulWidget {
Copy link
Author

Choose a reason for hiding this comment

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

Where should this live? And should it be exported outside the package or not? Most likely also needed in #165977 and #167114.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would create a new file under cupertino/, since it's a new aspect for the cupertino library.

I feel the name not intuitive enough though, because IMO the most important aspect of this class is "focus", which is missing from the name. At least we should call it CupertinoFocusTraversalGroup. I know it's long, but if we must delete a word we might consider the other two words. What do you think?

Copy link
Author

Choose a reason for hiding this comment

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

Thats a good point! I think CupertinoFocusTraversalGroup would be good if its not too long? Its a wrapper around FocusTraversalGroup so just adding the Cupertino prefix would be nice for consistency.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep I think the length isn't a major concern, since this class isn't mostly used by end developers but by libraries.

…eyboard-focus-support-for-cupertino-action-sheet-action
@dkwingsmt dkwingsmt self-requested a review April 23, 2025 18:10
@dkwingsmt
Copy link
Contributor

It'll take me some time to review but first I want to say that this is a fascinating change!

Copy link
Contributor

@dkwingsmt dkwingsmt left a comment

Choose a reason for hiding this comment

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

A first round of comments.

@@ -1077,6 +1080,7 @@ class CupertinoActionSheet extends StatefulWidget {
this.messageScrollController,
this.actionScrollController,
this.cancelButton,
this.focusColor,
Copy link
Contributor

Choose a reason for hiding this comment

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

I recommend removing customization for focusColor for the following reasons:

  • A single color might not be sufficient to describe the border. The video for the native case displayed two borders with two colors. I don't mean that this PR must reach 100% fidelity, since it's already a great start, but describing the border with a single color is in the end not correct and will be problematic when we try to improve the fidelity.
  • This feature is a system wide accessibility feature and probably shouldn't need customization.

Comment on lines +1385 to +1387
/// background of the button is drawn by [CupertinoActionSheet]. When
/// [focusNode] has focus, this widget will draw the background of color
/// [focusColor].
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, in the ideal world, every focusable area in Cupertino will display this focus border when focused, a natural behavior that shouldn't need explanation. Therefore I think we don't need to add documentation for it. Although I can also understand that it's a behavior and document readers might want to know all behaviors (or do they?).

What do you think?

///
/// * <https://developer.apple.com/design/human-interface-guidelines/focus-and-selection/>
/// {@endtemplate}
class CupertinoFocusTraversalGroup extends StatefulWidget {
Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I noticed that this effect is called UIFocusHaloEffect in iOS's API and referred to as a "focus ring" in Apple's guide. I think either one would be a great simple name: CupertinoHalo, CupertinoFocusHalo or CupertinoFocusRing.

(We don't have to change it right now. Unless you have a clear opinion, we can postpone this decision while I ask round for opinions.)

context,
const BorderRadius borderRadius = BorderRadius.all(Radius.circular(_kCornerRadius));

child = ClipRRect(
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this clip for?

class CupertinoFocusTraversalGroup extends StatefulWidget {
/// {@macro flutter.cupertino.CupertinoFocusTraversalGroup}
const CupertinoFocusTraversalGroup({
this.borderRadius,
Copy link
Contributor

Choose a reason for hiding this comment

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

The borderRadius is very limiting. The API used by iOS has different initializer for different shapes, which I think is a good design. I suggest using named constructors, such as CupertinoFocusTraversalGroup.onRRect CupertinoFocusTraversalGroup.onRect to leave room for other shapes in the future.

/// The radius of the border that highlights active focus.
///
/// When [borderRadius] is null, it defaults to [CupertinoFocusTraversalGroup.defaultBorderRadius]
final BorderRadiusGeometry? borderRadius;
Copy link
Contributor

Choose a reason for hiding this comment

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

Leave this property private so that this class can support other shapes.


/// The default radius of the border that highlights active focus.
static BorderRadius get defaultBorderRadius =>
kCupertinoButtonSizeBorderRadius[CupertinoButtonSize.large]!;
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't make much sense to me, since the border radius should follow exactly the child widget and should be provided explicitly. If there must be any default, then the default should be a rectangle.

///
/// Called with true if any node within the group has focus, and false
/// otherwise.
final ValueChanged<bool>? onFocusChange;
Copy link
Contributor

Choose a reason for hiding this comment

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

By Flutter's style, functional types must be typedef'd before being used. Search for other typedefs for examples.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also: I'm not an expert on focus, but is this really not achievable with existing APIs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
f: cupertino flutter/packages/flutter/cupertino repository f: focus Focus traversal, gaining or losing focus framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CupertinoActionSheet: Add keyboard support (Ipad, IOS)
2 participants