Skip to main content
Version: 1.12.0

KeyboardToolbar

KeyboardToolbar is a view that sticky to the keyboard and has next and previous buttons for switching between inputs as well as Done button for closing the keyboard.

This component is fully customizable and allows you to define any behavior for provided buttons and also allows you to render additional content.

Features

  • Fully customizable UI 🎨: Tailor the appearance of the toolbar to match your app's design.
  • Supports dark/light theme 🌓: Adapts to the theme settings of the user's device for a seamless experience.
  • Extended accessibility support 🔍: Ensures that all users, including those with disabilities, can navigate through inputs effectively.
  • Full control over the buttons behavior 🔧: Customize the actions triggered by the next, previous, and done buttons according to your needs.

Props

button

This property allows to render custom touchable component for next, previous and done button.

import { TouchableOpacity } from "react-native-gesture-handler";
import {
KeyboardToolbar,
KeyboardToolbarProps,
} from "react-native-keyboard-controller";

const CustomButton: KeyboardToolbarProps["button"] = ({
children,
onPress,
}) => <TouchableOpacity onPress={onPress}>{children}</TouchableOpacity>;

// ...

<KeyboardToolbar button={CustomButton} />;

blur

This property allows to render custom blur effect for the toolbar (by default iOS keyboard is opaque and it blurs the content underneath, so if you want to follow HIG (Human Interface Guidelines) properly - consider to add this effect).

By default it is null and will not render any blur effect, because it's not a responsibility of this library to provide a blur effect. Instead it provides a property where you can specify your own blur effect and its provider, i. e. @react-native-community/blur, expo-blur or maybe even react-native-skia (based on your project preferences of course).

warning

Please, note, that you need to specify opacity prop for this prop to work. Because otherwise you will not see a blur effect.

import { BlurView } from "@react-native-community/blur";
import {
KeyboardToolbar,
KeyboardToolbarProps,
} from "react-native-keyboard-controller";

const CustomBlur: KeyboardToolbarProps["blur"] = ({ children }) => (
<BlurView
blurType="chromeMaterial"
blurAmount={10}
reducedTransparencyFallbackColor="white"
style={{ position: "absolute", top: 0, left: 0, bottom: 0, right: 0 }}
>
{children}
</BlurView>
);

// ...

<KeyboardToolbar blur={CustomBlur} opacity="4F" />;

content

This property allows you to show a custom content in the middle of the toolbar. It accepts JSX element. Default value is null.

<KeyboardToolbar
content={
showAutoFill ? (
<AutoFillContacts onContactSelected={onContactSelected} />
) : null
}
/>

doneText

The property that allows to specify custom text for Done button.

<KeyboardToolbar doneText="Close" />

icon

icon property allows to render custom icons for prev and next buttons.

import { Text } from "react-native";
import {
KeyboardToolbar,
KeyboardToolbarProps,
} from "react-native-keyboard-controller";

const Icon: KeyboardToolbarProps["icon"] = ({ type }) => {
return <Text>{type === "next" ? "⬇️" : "⬆️"}</Text>;
};

// ...

<KeyboardToolbar icon={Icon} />;

onDoneCallback

A callback that is called when the user presses the done button along with the default action.

import { Platform } from "react-native";
import { KeyboardToolbar } from "react-native-keyboard-controller";
import { trigger } from "react-native-haptic-feedback";

const options = {
enableVibrateFallback: true,
ignoreAndroidSystemSettings: false,
};
const haptic = () =>
trigger(Platform.OS === "ios" ? "impactLight" : "keyboardTap", options);

// ...

<KeyboardToolbar onDoneCallback={haptic} />;

onNextCallback

A callback that is called when the user presses the next button along with the default action.

import { Platform } from "react-native";
import { KeyboardToolbar } from "react-native-keyboard-controller";
import { trigger } from "react-native-haptic-feedback";

const options = {
enableVibrateFallback: true,
ignoreAndroidSystemSettings: false,
};
const haptic = () =>
trigger(Platform.OS === "ios" ? "impactLight" : "keyboardTap", options);

// ...

<KeyboardToolbar onNextCallback={haptic} />;

onPrevCallback

A callback that is called when the user presses the previous button along with the default action.

import { Platform } from "react-native";
import { KeyboardToolbar } from "react-native-keyboard-controller";
import { trigger } from "react-native-haptic-feedback";

const options = {
enableVibrateFallback: true,
ignoreAndroidSystemSettings: false,
};
const haptic = () =>
trigger(Platform.OS === "ios" ? "impactLight" : "keyboardTap", options);

// ...

<KeyboardToolbar onPrevCallback={haptic} />;

opacity

This property allows to specify the opacity of the toolbar container. The value must be specified in hexadecimal format. Default value is FF.

<KeyboardToolbar opacity="EE" />

showArrows

A boolean prop indicating whether to show next and prev buttons. Can be useful to set it to false if you have only one input and want to show only Done button. Default to true.

theme

Prop allowing you to specify the brand colors of your application for KeyboardToolbar component. If you want to re-use already platform specific colors you can import DefaultKeyboardToolbarTheme object and override colors only necessary colors:

import {
DefaultKeyboardToolbarTheme,
KeyboardToolbarProps,
} from "react-native-keyboard-controller";

const theme: KeyboardToolbarProps["theme"] = {
...DefaultKeyboardToolbarTheme,
dark: {
...DefaultKeyboardToolbarTheme.dark,
primary: "#FFCC00",
},
};
dark/light theme support

Don't forget that you need to specify colors for both dark and light theme. The theme will be selected automatically based on the device preferences.

Example

import React, { useCallback, useState } from "react";
import { StyleSheet, Text, TextInput as TextInputRN, View } from "react-native";
import {
KeyboardAwareScrollView,
KeyboardToolbar,
} from "react-native-keyboard-controller";

import type {
NativeSyntheticEvent,
TextInputFocusEventData,
TextInputProps,
} from "react-native";

export default function ToolbarExample() {
return (
<>
<KeyboardAwareScrollView bottomOffset={35} style={scrollViewStyles}>
<TextInput placeholder="Your name" title="Name" />
<TextInput placeholder="Your surname" title="Surname" />
<TextInput
placeholder="example@gmail.com"
title="Email"
editable={false}
/>
<TextInput
placeholder="Tell us funny facts about you"
title="About you"
editable={false}
/>
<View style={styles.row}>
<View style={styles.birthday}>
<TextInput placeholder="DD" title="Day" />
</View>
<View style={[styles.birthday, styles.withPadding]}>
<TextInput placeholder="MM" title="Month" />
</View>
<View style={styles.birthday}>
<TextInput placeholder="YYYY" title="Year" />
</View>
</View>
<TextInput placeholder="Country" title="Country" />
<TextInput placeholder="Region of the city" title="Region" />
<TextInput placeholder="City where you currently live" title="City" />
<TextInput placeholder="Street name" title="Street" />
<TextInput placeholder="House number" title="House" />
<TextInput placeholder="Flat number" title="Flat" />
</KeyboardAwareScrollView>
<KeyboardToolbar />
</>
);
}

const styles = StyleSheet.create({
container: {
backgroundColor: "white",
},
row: {
flexDirection: "row",
},
birthday: {
flex: 1 / 3,
},
withPadding: {
paddingHorizontal: 16,
},
});
const scrollViewStyles = [styles.withPadding, styles.container];

type CustomTextInputProps = {
title?: string;
} & TextInputProps;

const TextInput = (props: CustomTextInputProps) => {
const { title, ...rest } = props;
const [isFocused, setFocused] = useState(false);

const onFocus = useCallback(
(e: NativeSyntheticEvent<TextInputFocusEventData>) => {
setFocused(true);
props.onFocus?.(e);
},
[],
);

const onBlur = useCallback(
(e: NativeSyntheticEvent<TextInputFocusEventData>) => {
setFocused(false);
props.onBlur?.(e);
},
[],
);

return (
<>
{!!title && <Text style={textInputStyles.title}>{title}</Text>}
<TextInputRN
placeholderTextColor="#6c6c6c"
style={[
textInputStyles.container,
rest.editable === false && textInputStyles.disabled,
isFocused && textInputStyles.focused,
]}
multiline
numberOfLines={2}
testID={rest.placeholder}
{...rest}
placeholder={`${rest.placeholder}`}
onFocus={onFocus}
onBlur={onBlur}
/>
</>
);
};

const textInputStyles = StyleSheet.create({
title: {
marginBottom: 6,
marginLeft: 3,
color: "black",
fontSize: 16,
},
container: {
width: "100%",
minHeight: 50,
maxHeight: 200,
marginBottom: 50,
borderColor: "black",
borderWidth: 2,
marginRight: 160,
borderRadius: 10,
color: "black",
paddingHorizontal: 12,
},
disabled: {
opacity: 0.5,
},
focused: {
borderColor: "#20AAFF",
},
});
More comprehensive usage

For more comprehensive usage that covers more complex interactions please check example app.

Limitations

  • By default TextInput search happens within UIViewController/FragmentActivity (current screen if you are using react-native-screens)
  • The order of the navigation is defined by the view hierarchy (commonly referred to as the view-tree).