Skip to content

[Proposal] Add keyboard support for CupertinoAlertDialog #165977

Open

Description

@fedorstepanovv

Steps to reproduce

  1. Create and show CupertinoAlertDialog
  2. Connect apple's official ipad keyboard to your ipad.
  3. Try to use an arrow key to navigate between options in your dialog.
  4. The same problem can be reproduced using CupertinoActionSheet.

Expected results

IOS native apps the typical outcome is:

  • Navigation between different options is done by using an arrow key.
  • User presses enter to close a dialog with the option he has chosen before (by using an arrow key).

Actual results

Nothing happens.

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.22.2, on macOS 14.3.1 23D60 darwin-arm64, locale
en-US)

Activity

  1. maheshj01 commented on Mar 26, 2025

    @maheshj01
    Member

    Hey @fedorstepanovv, Thanks for filing the issue. PlatformAlertDialog or showPlatformDialog doesn't seem to be part of material or cupertino package or the flutter sdk.
    If that is a third party package/widget you will need to file the issue with the maintainer to add keyboard support.

    Btw if you check AlertDialog it does support keyboard

    code sample
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key? key, required this.title}) : super(key: key);
      final String title;
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
      void _incrementCounter() {
        // delete confirmation dialog
        showDialog(
            context: context,
            builder: (context) {
              return AlertDialog(
                title: const Text('Delete Confirmation'),
                content: const Text('Are you sure you want to delete this item?'),
                actions: <Widget>[
                  TextButton(
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                    child: const Text('No'),
                  ),
                  TextButton(
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                    child: const Text('Yes'),
                  ),
                ],
              );
            });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '$_counter',
                  style: Theme.of(context).textTheme.bodyLarge,
                ),
              ],
            ),
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
        );
      }
    }
    

    Closing as invalid in case you disagree, please feel free to write in the comments, and we will reopen it

  2. added
    r: invalidIssue is closed as not valid
    and removed
    in triagePresently being triaged by the triage team
    on Mar 26, 2025
  3. changed the title [-]Keyboard navigation support issue in dialogs (Ipad, IOS)[/-] [+]Keyboard navigation support issue in CupertinoAlertDialog (Ipad, IOS)[/+] on Apr 1, 2025
  4. fedorstepanovv commented on Apr 1, 2025

    @fedorstepanovv
    Author

    Hi @maheshj01. Thanks for your response. You are right that the following methods are not the part of a cupertino package directly, sorry for the misunderstanding. However the package that provide those methods is based on cupertino/material. I agree that there is no issue with AlertDialog. However when it comes to Cupertino, it seems like it doesn't provide a lot of keyboard support features. For example: CupertinoAlertDialog. I updated this issue to address this problem.

  5. added
    in triagePresently being triaged by the triage team
    and removed
    r: invalidIssue is closed as not valid
    on Apr 1, 2025
  6. maheshj01 commented on Apr 1, 2025

    @maheshj01
    Member

    Thank you for the clarification @fedorstepanovv.

    I'm going to label this as a proposal to add keyboard support for CupertinoAlertDialog

    AlertDialog CupertinoAlertDialog
    Screen.Recording.2025-04-01.at.19.23.32.mov
    Screen.Recording.2025-04-01.at.19.26.28.mov
    code sample (Cupertino Dialog)v
    import 'package:flutter/cupertino.dart';
    
    /// Flutter code sample for [CupertinoAlertDialog].
    
    void main() => runApp(const AlertDialogApp());
    
    class AlertDialogApp extends StatelessWidget {
      const AlertDialogApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return const CupertinoApp(
          theme: CupertinoThemeData(brightness: Brightness.light),
          home: AlertDialogExample(),
        );
      }
    }
    
    class AlertDialogExample extends StatelessWidget {
      const AlertDialogExample({super.key});
    
      void _showAlertDialog(BuildContext context) {
        showCupertinoDialog<void>(
          context: context,
          builder: (BuildContext context) => CupertinoAlertDialog(
            title: const Text('Alert'),
            content: const Text('Proceed with destructive action?'),
            actions: <CupertinoDialogAction>[
              CupertinoDialogAction(
                /// This parameter indicates this action is the default,
                /// and turns the action's text to bold text.
                isDefaultAction: true,
                onPressed: () {
                  Navigator.pop(context);
                },
                child: const Text('No'),
              ),
              CupertinoDialogAction(
                /// This parameter indicates the action would perform
                /// a destructive action such as deletion, and turns
                /// the action's text color to red.
                isDestructiveAction: true,
                onPressed: () {
                  Navigator.pop(context);
                },
                child: const Text('Yes'),
              ),
            ],
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return CupertinoPageScaffold(
          navigationBar: const CupertinoNavigationBar(
              middle: Text('CupertinoAlertDialog Sample')),
          child: Center(
            child: CupertinoButton(
              onPressed: () => _showAlertDialog(context),
              child: const Text('CupertinoAlertDialog'),
            ),
          ),
        );
      }
    }
    
    code sample(AlertDialog)
    import 'package:flutter/material.dart';
    
    /// Flutter code sample for [AlertDialog].
    
    void main() => runApp(const AlertDialogExampleApp());
    
    class AlertDialogExampleApp extends StatelessWidget {
      const AlertDialogExampleApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(title: const Text('AlertDialog Sample')),
            body: const Center(child: DialogExample()),
          ),
        );
      }
    }
    
    class DialogExample extends StatelessWidget {
      const DialogExample({super.key});
    
      @override
      Widget build(BuildContext context) {
        return TextButton(
          onPressed: () => showDialog<String>(
            context: context,
            builder: (BuildContext context) => AlertDialog(
              title: const Text('AlertDialog Title'),
              content: const Text('AlertDialog description'),
              actions: <Widget>[
                TextButton(
                  onPressed: () => Navigator.pop(context, 'Cancel'),
                  child: const Text('Cancel'),
                ),
                TextButton(
                  onPressed: () => Navigator.pop(context, 'OK'),
                  child: const Text('OK'),
                ),
              ],
            ),
          ),
          child: const Text('Show Dialog'),
        );
      }
    }
    
    flutter doctor -v

    master

    ✓] Flutter (Channel master, 3.31.0-1.0.pre.345, on macOS 15.1.1 24B2091 darwin-arm64, locale en-US) [2.6s]
        • Flutter version 3.31.0-1.0.pre.345 on channel master at /Users/mahesh/Development/flutter_master
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision 9ce60b743d (2 hours ago), 2025-03-31 23:50:27 +0300
        • Engine revision 9ce60b743d
        • Dart version 3.8.0 (build 3.8.0-245.0.dev)
        • DevTools version 2.45.0-dev.0
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [3.1s]
        • Android SDK at /Users/mahesh/Library/Android/sdk
        • Platform android-35, build-tools 35.0.0
        • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
          This is the JDK bundled with the latest Android Studio installation on this machine.
          To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
        • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 16.0) [1,745ms]
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Build 16A242d
        • CocoaPods version 1.16.2
    
    [✓] Chrome - develop for the web [147ms]
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 2024.3) [146ms]
        • Android Studio at /Applications/Android Studio.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
    
    [✓] IntelliJ IDEA Community Edition (version 2021.2.1) [144ms]
        • IntelliJ at /Applications/IntelliJ IDEA CE.app
        • Flutter plugin version 61.2.4
        • Dart plugin version 212.5080.8
    
    [✓] VS Code (version 1.96.2) [19ms]
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.102.0
    
    [✓] Connected device (2 available) [7.0s]
        • macOS (desktop) • macos  • darwin-arm64   • macOS 15.1.1 24B2091 darwin-arm64
        • Chrome (web)    • chrome • web-javascript • Google Chrome 131.0.6778.265
    
    [✓] Network resources [688ms]
        • All expected network resources are available.
    
    • No issues found!

    stable

    [✓] Flutter (Channel stable, 3.29.2, on macOS 15.1.1 24B2091 darwin-arm64, locale en-US) [822ms]
        • Flutter version 3.29.2 on channel stable at /Users/mahesh/Development/flutter
        • Upstream repository https://github.com/flutter/flutter.git
        • Framework revision c236373904 (2 weeks ago), 2025-03-13 16:17:06 -0400
        • Engine revision 18b71d647a
        • Dart version 3.7.2
        • DevTools version 2.42.3
    [✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [3.2s]
        • Android SDK at /Users/mahesh/Library/Android/sdk
        • Platform android-35, build-tools 35.0.0
        • ANDROID_HOME = /Users/mahesh/Library/Android/sdk
        • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
          This is the JDK bundled with the latest Android Studio installation on this machine.
          To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
        • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
        • All Android licenses accepted.
    
    [✓] Xcode - develop for iOS and macOS (Xcode 16.0) [3.1s]
        • Xcode at /Applications/Xcode.app/Contents/Developer
        • Build 16A242d
        • CocoaPods version 1.16.2
    
    [✓] Chrome - develop for the web [136ms]
        • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
    
    [✓] Android Studio (version 2024.3) [135ms]
        • Android Studio at /Applications/Android Studio.app/Contents
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • Java version OpenJDK Runtime Environment (build 21.0.5+-12932927-b750.29)
    
    [✓] IntelliJ IDEA Community Edition (version 2021.2.1) [134ms]
        • IntelliJ at /Applications/IntelliJ IDEA CE.app
        • Flutter plugin version 61.2.4
        • Dart plugin version 212.5080.8
    
    [✓] VS Code (version 1.96.2) [18ms]
        • VS Code at /Applications/Visual Studio Code.app/Contents
        • Flutter extension version 3.102.0
    
    [✓] Connected device (4 available) [6.7s]
        • iPad Pro 11-inch (M4) (mobile)  • A97192B5-5CFD-4164-BF2A-A6E2972614FF • ios            • com.apple.CoreSimulator.SimRuntime.iOS-18-0
          (simulator)
        • macOS (desktop)                 • macos                                • darwin-arm64   • macOS 15.1.1 24B2091 darwin-arm64
        • Mac Designed for iPad (desktop) • mac-designed-for-ipad                • darwin         • macOS 15.1.1 24B2091 darwin-arm64
        • Chrome (web)                    • chrome                               • web-javascript • Google Chrome 131.0.6778.265
    
    [✓] Network resources [294ms]
        • All expected network resources are available.
    
    ! Doctor found issues in 1 category.
  7. added
    c: new featureNothing broken; request for a new capability
    frameworkflutter/packages/flutter repository. See also f: labels.
    p: cupertino_uicupertino_ui package in flutter/packages
    and removed
    in triagePresently being triaged by the triage team
    on Apr 1, 2025
  8. 4 remaining items

  9. added
    triaged-designTriaged by Design Languages team
    P2Important issues not at the top of the work list
    on Apr 2, 2025
  10. O-Hannonen commented on Apr 12, 2025

    @O-Hannonen
    Contributor

    I'd be interested to work on this if someone could assign it to me!

    The real issue is not in CupertinoAlertDialog, its the widget that is passed to it as action. It does focus the actions just fine when eg. TextButton is used as action.

    In the examples, it is the CupertinoDialogAction widget that is not focusable, thus making it seem like keyboard focus would not work on CupertinoAlertDialog. So the title of the issue could be changed to talk about adding keyboard focus support for CupertinoDialogAction.

  11. maheshj01 commented on Apr 14, 2025

    @maheshj01
    Member

    @O-Hannonen Thank you for your interest to contribute. I have assigned the issue to you.

  12. visma-onnimanni-hannonen commented on May 30, 2025

    @visma-onnimanni-hannonen

    Just a small status update here too: most of the changes are already done, but the rest are pending on the changes from this PR.

  13. added
    ⏳Bot is counting down the days until it unassigns the issue
    on Aug 18, 2025
  14. flutter-triage-bot commented on Aug 18, 2025

    @flutter-triage-bot

    This issue is assigned to @O-Hannonen but has had no recent status updates. Please consider unassigning this issue if it is not going to be addressed in the near future. This allows people to have a clearer picture of what work is actually planned. Thanks!

  15. flutter-triage-bot commented on Oct 22, 2025

    @flutter-triage-bot

    This issue was assigned to @O-Hannonen but has had no status updates in a long time. To remove any ambiguity about whether the issue is being worked on, the assignee was removed.

  16. removed
    ⏳Bot is counting down the days until it unassigns the issue
    on Oct 22, 2025
  17. added
    packageflutter/packages repository. See also p: labels.
    and removed
    frameworkflutter/packages/flutter repository. See also f: labels.
    on Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listc: new featureNothing broken; request for a new capabilityc: proposalA detailed proposal for a change to Flutterp: cupertino_uicupertino_ui package in flutter/packagespackageflutter/packages repository. See also p: labels.team-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions