Unverified Commit f5343f4f authored by Mouad Debbar's avatar Mouad Debbar Committed by GitHub

[web] Arrow keys change selected item in dropdown (#76656)

parent f7823d58
......@@ -161,7 +161,10 @@ class _DropdownMenuItemButtonState<T> extends State<_DropdownMenuItemButton<T>>
}
static final Map<LogicalKeySet, Intent> _webShortcuts =<LogicalKeySet, Intent>{
LogicalKeySet(LogicalKeyboardKey.enter): const ActivateIntent(),
// On the web, up/down don't change focus, *except* in a <select>
// element, which is what a dropdown emulates.
LogicalKeySet(LogicalKeyboardKey.arrowDown): const DirectionalFocusIntent(TraversalDirection.down),
LogicalKeySet(LogicalKeyboardKey.arrowUp): const DirectionalFocusIntent(TraversalDirection.up),
};
@override
......@@ -188,8 +191,6 @@ class _DropdownMenuItemButtonState<T> extends State<_DropdownMenuItemButton<T>>
),
);
if (kIsWeb) {
// On the web, enter doesn't select things, *except* in a <select>
// element, which is what a dropdown emulates.
child = Shortcuts(
shortcuts: _webShortcuts,
child: child,
......
......@@ -2601,7 +2601,7 @@ void main() {
final Element element = tester.element(find.byKey(const ValueKey<String>('two')).last);
final FocusNode node = Focus.of(element);
expect(node.hasFocus, isTrue);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/55320
});
testWidgets('Selected element is correctly focused with dropdown that more items than fit on the screen', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'DropdownButton');
......@@ -2664,7 +2664,7 @@ void main() {
final Element element = tester.element(find.byKey(const ValueKey<int>(42)).last);
final FocusNode node = Focus.of(element);
expect(node.hasFocus, isTrue);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/55320
});
testWidgets("Having a focused element doesn't interrupt scroll when flung by touch", (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'DropdownButton');
......@@ -2738,7 +2738,66 @@ void main() {
// Scrolling to the top again has removed the one the focus was on from the
// tree, causing it to lose focus.
expect(Focus.of(tester.element(find.byKey(const ValueKey<int>(91)).last)).hasPrimaryFocus, isFalse);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/55320
});
testWidgets('DropdownButton changes selected item with arrow keys', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'DropdownButton');
String? value = 'one';
Widget buildFrame() {
return MaterialApp(
home: Scaffold(
body: Center(
child: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return DropdownButton<String>(
focusNode: focusNode,
autofocus: true,
onChanged: (String? newValue) {
setState(() {
value = newValue;
});
},
value: value,
itemHeight: null,
items: menuItems.map<DropdownMenuItem<String>>((String item) {
return DropdownMenuItem<String>(
key: ValueKey<String>(item),
value: item,
child: Text(item, key: ValueKey<String>(item + 'Text')),
);
}).toList(),
);
},
),
),
),
);
}
await tester.pumpWidget(buildFrame());
await tester.pump(); // Pump a frame for autofocus to take effect.
expect(focusNode.hasPrimaryFocus, isTrue);
await tester.sendKeyEvent(LogicalKeyboardKey.enter);
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // finish the menu animation
expect(value, equals('one'));
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); // Focus 'two'.
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.arrowDown); // Focus 'three'.
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.arrowUp); // Back to 'two'.
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.enter); // Select 'two'.
await tester.pump();
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // finish the menu animation
expect(value, equals('two'));
});
testWidgets('DropdownButton onTap callback is called when defined', (WidgetTester tester) async {
int dropdownButtonTapCounter = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment