Skip to content

Commit 167a000

Browse files
authored
feat: add ScrollViewWithBottomPadding component (#1294)
## 📜 Description Added `ScrollViewWithBottomPadding` component. ## 💡 Motivation and Context This PR is a logical continuation of #1289 In this PR I'm building a foundational component that adds scrollable padding on both iOS/Android without modifying layout. As a result it gives super smooth keyboard interactions, because we don't recalculate layout on each frame and we still add scrollable space. Also we achieve it without additional views, which is also super helpful, since we don't accidentally break styling. This component will power next-gen implementation of `KeyboardAwareScrollView` and future `ChatKit` component. ## 📢 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 --> ### JS - added `ScrollViewWithBottomPadding` component; ## 🤔 How Has This Been Tested? Tested manually in example project. At the moment not used in the package, but will be eventually used in `KeyboardAwareScrollView` and `ChatKit`. ## 📸 Screenshots (if appropriate): |KeyboardAwareScrollView|Non inverted chat list| |--------------------------|---------------------| |<video src="https://github.com/user-attachments/assets/0f7efef7-ec15-4fe6-96cb-40334f0c91ad">|<video src="https://github.com/user-attachments/assets/92093e87-434a-4c82-91d5-1c7e9706e5f0">| ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
1 parent 36abe0b commit 167a000

2 files changed

Lines changed: 81 additions & 0 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import React, { forwardRef } from "react";
2+
import { Platform } from "react-native";
3+
import Reanimated, { useAnimatedProps } from "react-native-reanimated";
4+
5+
import { ClippingScrollView } from "../../bindings";
6+
7+
import styles from "./styles";
8+
9+
import type { ScrollViewProps } from "react-native";
10+
import type { SharedValue } from "react-native-reanimated";
11+
12+
const ReanimatedClippingScrollView =
13+
Platform.OS === "android"
14+
? Reanimated.createAnimatedComponent(ClippingScrollView)
15+
: ClippingScrollView;
16+
17+
type AnimatedScrollViewProps = React.ComponentProps<
18+
typeof Reanimated.ScrollView
19+
>;
20+
21+
export type AnimatedScrollViewComponent = React.ForwardRefExoticComponent<
22+
AnimatedScrollViewProps & React.RefAttributes<Reanimated.ScrollView>
23+
>;
24+
25+
type ScrollViewWithBottomPaddingProps = {
26+
ScrollViewComponent: AnimatedScrollViewComponent;
27+
children?: React.ReactNode;
28+
bottomPadding: SharedValue<number>;
29+
} & ScrollViewProps;
30+
31+
const ScrollViewWithBottomPadding = forwardRef<
32+
Reanimated.ScrollView,
33+
ScrollViewWithBottomPaddingProps
34+
>(
35+
(
36+
{ ScrollViewComponent, bottomPadding, contentInset, children, ...rest },
37+
ref,
38+
) => {
39+
const animatedProps = useAnimatedProps(
40+
() => ({
41+
// iOS prop
42+
contentInset: {
43+
bottom: bottomPadding.value + (contentInset?.bottom || 0),
44+
top: contentInset?.top,
45+
right: contentInset?.right,
46+
left: contentInset?.left,
47+
},
48+
// Android prop
49+
contentInsetBottom: bottomPadding.value,
50+
}),
51+
[
52+
contentInset?.bottom,
53+
contentInset?.top,
54+
contentInset?.right,
55+
contentInset?.left,
56+
],
57+
);
58+
59+
return (
60+
<ReanimatedClippingScrollView
61+
animatedProps={animatedProps}
62+
style={styles.container}
63+
>
64+
<ScrollViewComponent ref={ref} animatedProps={animatedProps} {...rest}>
65+
{children}
66+
</ScrollViewComponent>
67+
</ReanimatedClippingScrollView>
68+
);
69+
},
70+
);
71+
72+
export default ScrollViewWithBottomPadding;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { StyleSheet } from "react-native";
2+
3+
const styles = StyleSheet.create({
4+
container: {
5+
flex: 1,
6+
},
7+
});
8+
9+
export default styles;

0 commit comments

Comments
 (0)