Skip to content

Commit 2fa894d

Browse files
committed
feat: rename components, move prop types into types file, update documentation
1 parent 0995e00 commit 2fa894d

6 files changed

Lines changed: 221 additions & 142 deletions

File tree

docs/docs/api/components/keyboard-toolbar/index.mdx

Lines changed: 122 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,56 @@ import toolbar from "./toolbar.lottie.json";
3737
- **Extended accessibility support** 🔍: Ensures that all users, including those with disabilities, can navigate through inputs effectively.
3838
- **Full control over the buttons behavior** 🔧: Customize the actions triggered by the next, previous, and done buttons according to your needs.
3939
- **Extends ViewProps** 📜: Supports all the props that `View` component has.
40+
- **Compound component pattern** 🔌: Mix and match sub-components for granular control over the toolbar's structure.
41+
42+
## Compound Components
43+
44+
The new API uses sub-components as children of `KeyboardToolbar`. These allow for precise customization, such as conditional rendering of buttons or injecting custom elements.
45+
46+
### `<KeyboardToolbar.Background>`
47+
48+
Renders a custom background (e.g., blur effect) that overlays the entire toolbar. Accepts any React node as children.
49+
50+
```tsx
51+
import { Platform } from "react-native";
52+
import { KeyboardToolbar } from "react-native-keyboard-controller";
53+
import { BlurView } from "@react-native-community/blur";
54+
55+
<KeyboardToolbar opacity="4F">
56+
<KeyboardToolbar.Background>
57+
<BlurView
58+
blurAmount={32}
59+
blurType={Platform.OS === "ios" ? "chromeMaterial" : "light"}
60+
reducedTransparencyFallbackColor="white"
61+
style={{ position: "absolute", top: 0, left: 0, bottom: 0, right: 0 }}
62+
/>
63+
</KeyboardToolbar.Background>
64+
{/* Other sub-components */}
65+
</KeyboardToolbar>;
66+
```
67+
68+
:::warning
69+
Please, note, that you need to specify `opacity` prop for this prop to work. Because otherwise you will not see a blur effect.
70+
:::
71+
72+
### `<KeyboardToolbar.Content>`
73+
74+
Renders a custom content (e.g., yours UI elements) in the middle of the toolbar. Accepts any React node as children.
75+
76+
```tsx
77+
import { KeyboardToolbar } from "react-native-keyboard-controller";
78+
79+
<KeyboardToolbar>
80+
<KeyboardToolbar.Content>
81+
{showAutoFill ? (
82+
<AutoFillContacts onContactSelected={onContactSelected} />
83+
) : null}
84+
</KeyboardToolbar.Content>
85+
{/* Other sub-components */}
86+
</KeyboardToolbar>;
87+
```
88+
89+
### `<KeyboardToolbar.Prev>`
4090

4191
## Props
4292

@@ -69,53 +119,6 @@ const CustomButton: KeyboardToolbarProps["button"] = ({
69119
<KeyboardToolbar button={CustomButton} />;
70120
```
71121

72-
### `blur`
73-
74-
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_](https://developer.apple.com/design/human-interface-guidelines/materials)) properly - consider to add this effect).
75-
76-
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).
77-
78-
:::warning
79-
Please, note, that you need to specify `opacity` prop for this prop to work. Because otherwise you will not see a blur effect.
80-
:::
81-
82-
```tsx
83-
import { BlurView } from "@react-native-community/blur";
84-
import {
85-
KeyboardToolbar,
86-
KeyboardToolbarProps,
87-
} from "react-native-keyboard-controller";
88-
89-
const CustomBlur: KeyboardToolbarProps["blur"] = ({ children }) => (
90-
<BlurView
91-
blurType="chromeMaterial"
92-
blurAmount={10}
93-
reducedTransparencyFallbackColor="white"
94-
style={{ position: "absolute", top: 0, left: 0, bottom: 0, right: 0 }}
95-
>
96-
{children}
97-
</BlurView>
98-
);
99-
100-
// ...
101-
102-
<KeyboardToolbar blur={CustomBlur} opacity="4F" />;
103-
```
104-
105-
### `content`
106-
107-
This property allows you to show a custom content in the middle of the toolbar. It accepts JSX element. Default value is `null`.
108-
109-
```tsx
110-
<KeyboardToolbar
111-
content={
112-
showAutoFill ? (
113-
<AutoFillContacts onContactSelected={onContactSelected} />
114-
) : null
115-
}
116-
/>
117-
```
118-
119122
### `doneText`
120123

121124
The property that allows to specify custom text for `Done` button.
@@ -345,7 +348,11 @@ export default function ToolbarExample() {
345348
<TextInput placeholder="House number" title="House" />
346349
<TextInput placeholder="Flat number" title="Flat" />
347350
</KeyboardAwareScrollView>
348-
<KeyboardToolbar />
351+
<KeyboardToolbar>
352+
<KeyboardToolbar.Prev />
353+
<KeyboardToolbar.Next />
354+
<KeyboardToolbar.Done />
355+
</KeyboardToolbar>
349356
</>
350357
);
351358
}
@@ -444,6 +451,73 @@ const textInputStyles = StyleSheet.create({
444451
For more comprehensive usage that covers more complex interactions please check [example](https://github.com/kirillzyusko/react-native-keyboard-controller/tree/main/example) app.
445452
:::
446453

454+
## Migration to compound component
455+
456+
To migrate from the legacy prop-based API to the compound API:
457+
458+
1. Add elements that you want to render in the toolbar (e.g., `Prev`, `Next`, `Done`, `Content`, `Background`).
459+
460+
```tsx
461+
// Old:
462+
<KeyboardToolbar />
463+
464+
// New:
465+
<KeyboardToolbar>
466+
<KeyboardToolbar.Prev />
467+
<KeyboardToolbar.Next />
468+
<KeyboardToolbar.Done />
469+
</KeyboardToolbar>
470+
```
471+
472+
2. Move props like `content`, `blur`, `doneText` into dedicated sub-components:
473+
474+
```tsx
475+
// Old:
476+
<KeyboardToolbar content={<AutoFillContacts />} blur={<BlurView />} />
477+
478+
// New:
479+
<KeyboardToolbar>
480+
<KeyboardToolbar.Background>
481+
<BlurView />
482+
</KeyboardToolbar.Background>
483+
<KeyboardToolbar.Content>
484+
<AutoFillContacts />
485+
</KeyboardToolbar.Content>
486+
<KeyboardToolbar.Done text="Close" />
487+
</KeyboardToolbar>
488+
```
489+
490+
3. If you used button callbacks, move them into dedicated sub-components:
491+
492+
```tsx
493+
// Old:
494+
<KeyboardToolbar
495+
onNextCallback={haptic}
496+
onPrevCallback={haptic}
497+
onDoneCallback={haptic}
498+
/>
499+
500+
// New:
501+
<KeyboardToolbar>
502+
<KeyboardToolbar.Next onPress={haptic} />
503+
<KeyboardToolbar.Prev onPress={haptic} />
504+
<KeyboardToolbar.Done onPress={haptic} />
505+
</KeyboardToolbar>
506+
```
507+
508+
4. If you used `showArrows` prop, move it into conditional rendering:
509+
510+
```tsx
511+
// Old:
512+
<KeyboardToolbar showArrows={false} />
513+
514+
// New:
515+
<KeyboardToolbar>
516+
{showArrows ? <KeyboardToolbar.Prev /> : null}
517+
{showArrows ? <KeyboardToolbar.Next /> : null}
518+
</KeyboardToolbar>
519+
```
520+
447521
## Limitations
448522

449523
- By default `TextInput` search happens within `UIViewController`/`FragmentActivity` (current screen if you are using `react-native-screens`)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from "react";
2+
3+
import type { ReactNode } from "react";
4+
5+
const Background: React.FC<{ children: ReactNode }> = ({ children }) => (
6+
<>{children}</>
7+
);
8+
9+
export default Background;

src/components/KeyboardToolbar/compound/components/Blur.tsx

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/components/KeyboardToolbar/compound/components/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export { default as Blur } from "./Blur";
1+
export { default as Background } from "./Background";
22
export { default as Content } from "./Content";
33
export { default as Done } from "./Done";
44
export { default as Next } from "./Next";

src/components/KeyboardToolbar/index.tsx

Lines changed: 6 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import KeyboardStickyView from "../KeyboardStickyView";
88
import Arrow from "./Arrow";
99
import Button from "./Button";
1010
import { colors } from "./colors";
11-
import { Blur, Content, Done, Next, Prev } from "./compound/components";
11+
import { Background, Content, Done, Next, Prev } from "./compound/components";
1212
import { ToolbarContext } from "./compound/context";
1313
import {
1414
DEFAULT_OPACITY,
@@ -18,80 +18,8 @@ import {
1818
TEST_ID_KEYBOARD_TOOLBAR,
1919
} from "./constants";
2020

21-
import type { HEX, KeyboardToolbarTheme } from "./types";
22-
import type { KeyboardStickyViewProps } from "../KeyboardStickyView";
21+
import type { KeyboardToolbarProps } from "./types";
2322
import type { ReactNode } from "react";
24-
import type { GestureResponderEvent, ViewProps } from "react-native";
25-
26-
type SafeAreaInsets = {
27-
left: number;
28-
right: number;
29-
};
30-
31-
export type KeyboardToolbarProps = Omit<
32-
ViewProps,
33-
"style" | "testID" | "children"
34-
> & {
35-
/**
36-
* An element that is shown in the middle of the toolbar.
37-
*
38-
* @deprecated Use compound API with `<KeyboardToolbar.Content />` component instead.
39-
*/
40-
content?: React.JSX.Element | null;
41-
/** A set of dark/light colors consumed by toolbar component. */
42-
theme?: KeyboardToolbarTheme;
43-
/**
44-
* Custom text for done button.
45-
*
46-
* @deprecated Use compound API with `<KeyboardToolbar.Done />` component and `text` prop instead.
47-
*/
48-
doneText?: ReactNode;
49-
/** Custom touchable component for toolbar (used for prev/next/done buttons). */
50-
button?: typeof Button;
51-
/** Custom icon component used to display next/prev buttons. */
52-
icon?: typeof Arrow;
53-
/**
54-
* Whether to show next and previous buttons. Can be useful to set it to `false` if you have only one input
55-
* and want to show only `Done` button. Default to `true`.
56-
*
57-
* @deprecated Use compound API and conditional rendering for `<KeyboardToolbar.Next />` and `<KeyboardToolbar.Prev />`.
58-
*/
59-
showArrows?: boolean;
60-
/**
61-
* A callback that is called when the user presses the next button along with the default action.
62-
*
63-
* @deprecated Use compound API with `<KeyboardToolbar.Next />` and `onPress` callback instead.
64-
*/
65-
onNextCallback?: (event: GestureResponderEvent) => void;
66-
/**
67-
* A callback that is called when the user presses the previous button along with the default action.
68-
*
69-
* @deprecated Use compound API with `<KeyboardToolbar.Prev />` and `onPress` callback instead.
70-
*/
71-
onPrevCallback?: (event: GestureResponderEvent) => void;
72-
/**
73-
* A callback that is called when the user presses the done button along with the default action.
74-
*
75-
* @deprecated Use compound API with `<KeyboardToolbar.Done />` and `onPress` callback instead.
76-
*/
77-
onDoneCallback?: (event: GestureResponderEvent) => void;
78-
/**
79-
* A component that applies blur effect to the toolbar.
80-
*
81-
* @deprecated Use compound API and `<KeyboardToolbar.Effect />` instead.
82-
*/
83-
blur?: React.JSX.Element | null;
84-
/**
85-
* A value for container opacity in hexadecimal format (e.g. `ff`). Default value is `ff`.
86-
*/
87-
opacity?: HEX;
88-
/**
89-
* A object containing `left`/`right` properties. Used to specify proper container padding in landscape mode.
90-
*/
91-
insets?: SafeAreaInsets;
92-
/** JSX children in case if compound API is used. */
93-
children?: ReactNode;
94-
} & Pick<KeyboardStickyViewProps, "offset" | "enabled">;
9523

9624
/**
9725
* `KeyboardToolbar` is a component that is shown above the keyboard with `Prev`/`Next` buttons from left and
@@ -108,7 +36,7 @@ export type KeyboardToolbarProps = Omit<
10836
* ```
10937
*/
11038
const KeyboardToolbar: React.FC<KeyboardToolbarProps> & {
111-
Blur: typeof Blur;
39+
Background: typeof Background;
11240
Content: typeof Content;
11341
Prev: typeof Prev;
11442
Next: typeof Next;
@@ -200,9 +128,8 @@ const KeyboardToolbar: React.FC<KeyboardToolbarProps> & {
200128
}
201129
const type = child.type;
202130

203-
if (type === Blur) {
204-
// @ts-expect-error props are untyped
205-
blurChild = child.props.children;
131+
if (type === Background) {
132+
blurChild = child;
206133
} else if (type === Content) {
207134
contentChild = child;
208135
} else if (type === Prev) {
@@ -288,7 +215,7 @@ const styles = StyleSheet.create({
288215
},
289216
});
290217

291-
KeyboardToolbar.Blur = Blur;
218+
KeyboardToolbar.Background = Background;
292219
KeyboardToolbar.Content = Content;
293220
KeyboardToolbar.Prev = Prev;
294221
KeyboardToolbar.Next = Next;

0 commit comments

Comments
 (0)