Skip to content

fix(ios): prevent black QuickType bar when using Magic Keyboard on iPad + Fix Keyboard on iOS 26#52

Open
Daniele-rolli wants to merge 9 commits into
ionic-team:mainfrom
Daniele-rolli:main
Open

fix(ios): prevent black QuickType bar when using Magic Keyboard on iPad + Fix Keyboard on iOS 26#52
Daniele-rolli wants to merge 9 commits into
ionic-team:mainfrom
Daniele-rolli:main

Conversation

@Daniele-rolli
Copy link
Copy Markdown

Context

On iPads with a hardware keyboard (e.g., Magic Keyboard), iOS still fires UIKeyboardWillShow / UIKeyboardDidShow notifications even when no software keyboard is displayed. Only the QuickType suggestion bar appears at the bottom of the screen.
Currently, Capacitor interprets these events as a "real keyboard," resizing the WKWebView and causing visual glitches such as a black bar below the webview.

On iOS 26, a similar issue occurs with liquid glass the new keyboard is transparent with rounded edges, which can render a black box underneath.

iPad Example

Before After
iPad Before iPad After

iPhone Example

Before After
Simulator Screenshot - iPhone 16e - 2025-09-08 at 19 35 03 Simulator Screenshot - iPhone 16e - 2025-09-08 at 22 09 28

Solution

A height threshold guard was added in onKeyboardWillShow and onKeyboardDidShow in the iOS KeyboardPlugin:

  • If UIDevice.userInterfaceIdiom == .pad and keyboardHeight < 100px:

    • Treat the event as a QuickType bar, not a real keyboard.
    • Do not resize the WKWebView.
    • Fire JS events with keyboardHeight = 0 to indicate “no real keyboard.”
  • Otherwise, continue with normal resizing behavior.

Additional improvements:

  • WebView background is transparent, and its color is forced to match the DOM body via updateBackdropColorFromDOM.

Benefits

  • iPad + Magic Keyboard: no unnecessary resize, no black bar.
  • iPad + software keyboard: normal resize works as expected.
  • iPhone: keyboard backdrop displays the same color as DOM

@theproducer theproducer self-assigned this Apr 8, 2026
@theproducer theproducer self-requested a review April 8, 2026 16:54
Copy link
Copy Markdown
Collaborator

@theproducer theproducer left a comment

Choose a reason for hiding this comment

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

@Daniele-rolli Hello! Thanks for this, we've been running into similar issues that you've detailed here. I left some comments and suggestions to your PR.

Comment thread ios/Sources/KeyboardPlugin/Keyboard.m
Comment thread ios/Sources/KeyboardPlugin/Keyboard.m
@theproducer theproducer requested a review from a team April 9, 2026 15:37
@theproducer theproducer requested a review from a team May 19, 2026 14:07
@OS-pedrogustavobilro OS-pedrogustavobilro self-assigned this May 27, 2026
Copy link
Copy Markdown
Contributor

@OS-pedrogustavobilro OS-pedrogustavobilro left a comment

Choose a reason for hiding this comment

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

@theproducer leaving a few comments of things I noticed.

if ([[[UIApplication sharedApplication] delegate] respondsToSelector:@selector(window)]) {
window = [[[UIApplication sharedApplication] delegate] window];
}
if (!window && @available(iOS 13.0, *)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@available(iOS 13.0, *) should always be true for Capacitor 8+, so it's not needed right?

Comment on lines +195 to +200
// Make WKWebView transparent
if (self.webView) {
self.webView.opaque = NO;
self.webView.backgroundColor = UIColor.clearColor;
self.webView.scrollView.backgroundColor = UIColor.clearColor;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Due to how vastly different UIs of Web Apps / Capacitor Apps can be, I'm wondering if such a change could have unforeseen consequences in app's UI. Is this how it is on Android?

}

- (void)updateBackdropColor {
if (self.bridge.config.backgroundColor) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Capacitor config has config.backgroundColor and config.ios.backgroundColor, which is said that should override the global one. In that case we should check if config.ios.backgroundColor is defined and use that one, otherwise use config.backgroundColor, or update from the DOM?

Source: https://github.com/ionic-team/capacitor/blob/main/cli/src/declarations.ts

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants