-
Notifications
You must be signed in to change notification settings - Fork 28.5k
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
base: master
Are you sure you want to change the base?
Add focus support for CupertinoActionSheetAction #166398 #167119
Conversation
…upertinoTraversalGroup
/// | ||
/// * <https://developer.apple.com/design/human-interface-guidelines/focus-and-selection/> | ||
/// {@endtemplate} | ||
class CupertinoTraversalGroup extends StatefulWidget { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
It'll take me some time to review but first I want to say that this is a fascinating change! |
There was a problem hiding this 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, |
There was a problem hiding this comment.
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.
/// background of the button is drawn by [CupertinoActionSheet]. When | ||
/// [focusNode] has focus, this widget will draw the background of color | ||
/// [focusColor]. |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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]!; |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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 typedef
s for examples.
There was a problem hiding this comment.
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?
This PR fixes #166398
CupertinoActionSheetAction
. This makes it work with keyboard shortcutsCupertinoTraversalGroup
that applies a Cupertino style focus border around its child when any of its descendant has focusCupertinoTraversalGroup
inCupertinoActionSheet
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
///
).