diff --git a/packages/rn-tester/js/examples/Keyboard/KeyboardExample.js b/packages/rn-tester/js/examples/Keyboard/KeyboardExample.js
new file mode 100644
index 00000000000..47d8883ea93
--- /dev/null
+++ b/packages/rn-tester/js/examples/Keyboard/KeyboardExample.js
@@ -0,0 +1,113 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ *
+ * @format
+ * @flow strict-local
+ */
+
+'use strict';
+
+import type {
+ RNTesterModule,
+ RNTesterModuleExample,
+} from '../../types/RNTesterTypes';
+import type {KeyboardEvent} from 'react-native/Libraries/Components/Keyboard/Keyboard';
+
+import * as React from 'react';
+import {useEffect, useState} from 'react';
+import {Keyboard, StyleSheet, Text, View} from 'react-native';
+
+type KeybpardEventViewerProps = {
+ showEvent: 'keyboardWillShow' | 'keyboardDidShow',
+ hideEvent: 'keyboardWillHide' | 'keyboardDidHide',
+};
+
+const KeyboardEventViewer = (props: KeybpardEventViewerProps): React.Node => {
+ const {showEvent, hideEvent} = props;
+ const [isShown, setIsShown] = useState(false);
+ const [lastEvent, setLastEvent] = useState();
+
+ useEffect(() => {
+ const subscription = Keyboard.addListener(showEvent, ev => {
+ setIsShown(true);
+ setLastEvent(ev);
+ });
+ return () => subscription.remove();
+ }, [showEvent]);
+
+ useEffect(() => {
+ const subscription = Keyboard.addListener(hideEvent, ev => {
+ setIsShown(false);
+ setLastEvent(ev);
+ });
+ return () => subscription.remove();
+ }, [hideEvent]);
+
+ return (
+
+
+ Keyboard is
+ {isShown ? (
+ open
+ ) : (
+ closed
+ )}
+
+
+
+ {lastEvent
+ ? JSON.stringify(lastEvent, null, 2)
+ : 'No events observed'}
+
+
+
+ );
+};
+
+const keyboardWillShowHideExample: RNTesterModuleExample = {
+ title: 'keyboardWillShow / keyboardWillHide',
+ platform: 'ios',
+ render: () => (
+
+ ),
+};
+
+const keyboardDidShowHideExample: RNTesterModuleExample = {
+ title: 'keyboardDidShow / keyboardDidHide',
+ render: () => (
+
+ ),
+};
+
+const styles = StyleSheet.create({
+ closeText: {
+ color: 'red',
+ },
+ openText: {
+ color: 'green',
+ },
+ eventBox: {
+ marginTop: 10,
+ padding: 5,
+ borderWidth: StyleSheet.hairlineWidth,
+ },
+});
+
+const KeyboardExample: RNTesterModule = {
+ title: 'Keyboard',
+ description: 'Demonstrates usage of the "Keyboard" static API',
+ documentationURL: 'https://reactnative.dev/docs/keyboard',
+ category: 'Basic',
+ examples: [keyboardWillShowHideExample, keyboardDidShowHideExample],
+};
+
+export default KeyboardExample;
diff --git a/packages/rn-tester/js/utils/RNTesterList.android.js b/packages/rn-tester/js/utils/RNTesterList.android.js
index 97ffe9759a1..e3a5ffcda4a 100644
--- a/packages/rn-tester/js/utils/RNTesterList.android.js
+++ b/packages/rn-tester/js/utils/RNTesterList.android.js
@@ -184,6 +184,11 @@ const APIs: Array = [
category: 'UI',
module: require('../examples/Dimensions/DimensionsExample'),
},
+ {
+ key: 'Keyboard',
+ category: 'Basic',
+ module: require('../examples/Keyboard/KeyboardExample').default,
+ },
{
key: 'LayoutEventsExample',
category: 'UI',
diff --git a/packages/rn-tester/js/utils/RNTesterList.ios.js b/packages/rn-tester/js/utils/RNTesterList.ios.js
index 42cb9027bd8..cb0e34893de 100644
--- a/packages/rn-tester/js/utils/RNTesterList.ios.js
+++ b/packages/rn-tester/js/utils/RNTesterList.ios.js
@@ -231,6 +231,11 @@ const APIs: Array = [
module: require('../examples/Dimensions/DimensionsExample'),
supportsTVOS: true,
},
+ {
+ key: 'Keyboard',
+ module: require('../examples/Keyboard/KeyboardExample').default,
+ supportsTVOS: true,
+ },
{
key: 'LayoutAnimationExample',
module: require('../examples/Layout/LayoutAnimationExample'),