Skip to content

Commit 4886f74

Browse files
authored
feat: appearance (#723)
## 📜 Description Added `appearance` property to `KeyboardEventData`. ## 💡 Motivation and Context If user uses `light` theme but prefer dark keyboard, then `KeyboardToolbar` will be white (though it should be `dark` to match the keyboard color). So I thought it will be useful to add this property (additionally this property can be needed for `KeyboardController.retain()` API). On Android keyboard color is controlled via settings and the keyboard color is not exposed through the public API. But on most of Android devices keyboard color by default matches system settings, so in `appearance` I expose system preference (this is the best what I can do to try to match this). ## 📢 Changelog <!-- High level overview of important changes --> <!-- For example: fixed status bar manipulation; added new types declarations; --> <!-- If your changes don't affect one of platform/language below - then remove this platform/language --> ### Docs - added a reference about `appearance` property in `KeyboardEvents` section; ### JS - updated `KeyboardEventData` type; ### iOS - added `UIKeyboardAppearance` extension; ### Android - added `ReactThemedContext.appearance` extension; ## 🤔 How Has This Been Tested? Tested manually on: - iPhone 15 Pro - Pixel 7 Pro (API 35). ## 📸 Screenshots (if appropriate): ![image](https://github.com/user-attachments/assets/54398782-2054-4a7c-8b41-8495532b50b1) ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
1 parent 76942c5 commit 4886f74

File tree

7 files changed

+46
-1
lines changed

7 files changed

+46
-1
lines changed

android/src/main/java/com/reactnativekeyboardcontroller/extensions/ThemedReactContext.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.reactnativekeyboardcontroller.extensions
22

3+
import android.content.Context
4+
import android.os.Build
35
import com.facebook.react.bridge.ReactContext
46
import com.facebook.react.bridge.WritableMap
57
import com.facebook.react.modules.core.DeviceEventManagerModule
@@ -34,3 +36,19 @@ fun ThemedReactContext?.emitEvent(
3436

3537
Logger.i("ThemedReactContext", event)
3638
}
39+
40+
val ThemedReactContext?.appearance: String
41+
get() =
42+
when {
43+
this == null -> "default"
44+
isSystemDarkMode(this) -> "dark"
45+
else -> "light"
46+
}
47+
48+
private fun isSystemDarkMode(context: Context): Boolean =
49+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
50+
(context.getSystemService(Context.UI_MODE_SERVICE) as? android.app.UiModeManager)
51+
?.nightMode == android.app.UiModeManager.MODE_NIGHT_YES
52+
} else {
53+
false
54+
}

android/src/main/java/com/reactnativekeyboardcontroller/listeners/KeyboardAnimationCallback.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import com.facebook.react.views.textinput.ReactEditText
1515
import com.facebook.react.views.view.ReactViewGroup
1616
import com.reactnativekeyboardcontroller.constants.Keyboard
1717
import com.reactnativekeyboardcontroller.events.KeyboardTransitionEvent
18+
import com.reactnativekeyboardcontroller.extensions.appearance
1819
import com.reactnativekeyboardcontroller.extensions.dispatchEvent
1920
import com.reactnativekeyboardcontroller.extensions.dp
2021
import com.reactnativekeyboardcontroller.extensions.emitEvent
@@ -428,6 +429,7 @@ class KeyboardAnimationCallback(
428429
params.putDouble("timestamp", System.currentTimeMillis().toDouble())
429430
params.putInt("target", viewTagFocused)
430431
params.putString("type", FocusedInputHolder.get()?.keyboardType)
432+
params.putString("appearance", context.appearance)
431433

432434
return params
433435
}

docs/docs/api/keyboard-events.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type KeyboardEventData = {
3232
timestamp: number; // timestamp of the event from native thread
3333
target: number; // tag of the focused TextInput
3434
type: string; // `keyboardType` property from focused `TextInput`
35+
appearance: string; // `keyboardAppearance` property from focused `TextInput`
3536
};
3637
```
3738

ios/events/KeyboardEventEmitterPayload.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public func buildEventParams(_ height: Double, _ duration: Int, _ tag: NSNumber)
1717
data["timestamp"] = Date.currentTimeStamp
1818
data["target"] = tag
1919
data["type"] = input?.keyboardType.name ?? "default"
20+
data["appearance"] = input?.keyboardAppearance.name ?? "default"
2021

2122
return data
2223
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//
2+
// UIKeyboardAppearance.swift
3+
// Pods
4+
//
5+
// Created by Kiryl Ziusko on 08/12/2024.
6+
//
7+
8+
import Foundation
9+
import UIKit
10+
11+
public extension UIKeyboardAppearance {
12+
var name: String {
13+
switch self {
14+
case .default: return "default"
15+
case .dark: return "dark"
16+
case .light: return "light"
17+
@unknown default:
18+
return "default"
19+
}
20+
}
21+
}

ios/protocols/TextInput.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import UIKit
1111

1212
public protocol TextInput: AnyObject {
1313
var keyboardType: UIKeyboardType { get }
14+
var keyboardAppearance: UIKeyboardAppearance { get }
1415
func focus()
1516
}
1617

src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ export type KeyboardEventData = {
148148
duration: number;
149149
timestamp: number;
150150
target: number;
151-
type: TextInputProps["keyboardType"];
151+
type: NonNullable<TextInputProps["keyboardType"]>;
152+
appearance: NonNullable<TextInputProps["keyboardAppearance"]>;
152153
};
153154
export type KeyboardEventsModule = {
154155
addListener: (

0 commit comments

Comments
 (0)