Skip to content

Commit e6ca08b

Browse files
committed
feat(scroll): replace useHideOnScroll with ScrollToHideProvider for better performance
- Add new ScrollToHideProvider context for scroll-based animations - Implement useScrollToHide and useScrollValues hooks - Add animated scroll components (AnimatedVScroll, AnimatedHScroll, AnimatedVList, AnimatedHList) - Update documentation with new scroll-to-hide implementation - Remove deprecated useHideOnScroll hook and related types - Bump rnc-theme version to 0.1.0
1 parent 918b76c commit e6ca08b

File tree

16 files changed

+1879
-1392
lines changed

16 files changed

+1879
-1392
lines changed

apps/docs/astro.config.mjs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ export default defineConfig({
5555
// { label: 'Overview', slug: 'hooks/overview' },
5656
{ label: 'useTheme', slug: 'hooks/use-theme' },
5757
{ label: 'useThemeStyle', slug: 'hooks/use-themed-styles' },
58-
{ label: 'useHideOnScroll', slug: 'hooks/use-hide-on-scroll' },
58+
{
59+
label: 'useScrollToHide',
60+
slug: 'hooks/use-scroll-to-hide',
61+
badge: { text: 'New', variant: 'success' },
62+
},
5963
],
6064
},
6165
{
@@ -198,6 +202,10 @@ export default defineConfig({
198202
{
199203
label: 'Scroll',
200204
slug: 'components/disclosure/scroll',
205+
badge: {
206+
text: 'Updated',
207+
variant: 'tip',
208+
},
201209
},
202210
],
203211
},

apps/docs/src/content/docs/api/provider.mdx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Provider component is used to wrap your app content and provide the theme contex
1616
| `bottomSheetProps` | <a href='/api/provider#bottomsheetprops'>`BottomSheetProps`</a> | `{}` | Global props for bottom sheet components |
1717
| `toast` | <a href='/api/provider#toastconfig'>`ToastConfig`</a> | `{}` | Configuration for toast notifications |
1818
| `i18nConfig` | <a href='/api/provider#i18nconfig'>`I18nConfig`</a> | `undefined` | Internationalization configuration |
19+
| `scrollToHideProps` | <a href='/api/provider#scrolltohideprops'>`ScrollToHideProps`</a> | `undefined` | Configuration for scroll-to-hide behavior |
1920

2021
### BottomSheetProps
2122

@@ -28,18 +29,25 @@ Provider component is used to wrap your app content and provide the theme contex
2829
| `lineBackgroundColor` | <a href='https://reactnative.dev/docs/view-style-props#backgroundcolor'>`ViewStyle['backgroundColor']`</a> | No | `undefined` | Color of the drag indicator line |
2930
| `borderTopLeftRadius` | <a href='https://reactnative.dev/docs/view-style-props#borderradius'>`ViewStyle['borderTopLeftRadius']`</a> | No | `undefined` | Top left border radius |
3031
| `borderTopRightRadius` | <a href='https://reactnative.dev/docs/view-style-props#borderradius'>`ViewStyle['borderTopRightRadius']`</a> | No | `undefined` | Top right border radius |
31-
| `isBorderBottomTitleVisible` | `boolean` | `false` | Whether to show border below title |
32-
| `onStateChange` | `(state: boolean) => void` | `undefined` | Callback when bottom sheet state changes |
33-
| `variant` | `'scroll' \| 'flatlist'` | `'scroll'` | Type of scrollable content in bottom sheet |
34-
| `flatListProps` | `Omit<FlatListProps<T>, 'ref'>` | `undefined` | Props for FlatList when variant is 'flatlist' |
32+
| `isBorderBottomTitleVisible` | `boolean` | No | `false` | Whether to show border below title |
33+
| `onStateChange` | `(state: boolean) => void` | No | `undefined` | Callback when bottom sheet state changes |
34+
| `variant` | `'scroll' \| 'flatlist'` | No | `'scroll'` | Type of scrollable content in bottom sheet |
35+
| `flatListProps` | `Omit<FlatListProps<T>, 'ref'>` | No | `undefined` | Props for FlatList when variant is 'flatlist' |
3536

3637
### ToastConfig
3738

3839
| Property | Type | Default | Description |
3940
|----------|------|---------|-------------|
40-
| `position` | `'top' or 'bottom'` | `'bottom'` | Position of the toast notifications |
41+
| `position` | `'top' \| 'bottom'` | `'bottom'` | Position of the toast notifications |
4142
| `maxToasts` | `number` | `5` | Maximum number of toast notifications to show at once |
4243

44+
### ScrollToHideProps
45+
46+
| Property | Type | Required | Default | Description |
47+
|----------|------|----------|---------|-------------|
48+
| `headerHeight` | `number` | No | `100` | Height of the header component in pixels |
49+
| `tabBarHeight` | `number` | No | `60` | Height of the tab bar component in pixels |
50+
4351
### I18nConfig
4452

4553
| Property | Type | Required | Default | Description |

apps/docs/src/content/docs/components/data-display/list.mdx

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ List provides versatile vertical and horizontal list components built on React N
1313
import {
1414
VList,
1515
HList,
16+
AnimatedVList,
17+
AnimatedHList,
1618
VFlashList,
1719
HFlashList
1820
} from 'rnc-theme';
19-
import type { ListProps, InfiniteScrollProps } from 'rnc-theme';
21+
import type { ListProps, AnimatedListProps, InfiniteScrollProps } from 'rnc-theme';
2022
```
2123

2224
## Available Components
@@ -25,6 +27,10 @@ import type { ListProps, InfiniteScrollProps } from 'rnc-theme';
2527
- **VList** - Vertical list component based on FlatList
2628
- **HList** - Horizontal list component based on FlatList
2729

30+
### Animated List Components <Badge text="New" variant="tip" />
31+
- **AnimatedVList** - Vertical list component with animation support
32+
- **AnimatedHList** - Horizontal list component with animation support
33+
2834
### High-Performance List Components <Badge text="New" variant="tip" />
2935
- **VFlashList** - Vertical high-performance list based on Shopify's FlashList
3036
- **HFlashList** - Horizontal high-performance list based on Shopify's FlashList
@@ -125,6 +131,20 @@ import type { ListProps, InfiniteScrollProps } from 'rnc-theme';
125131
| `hideOnScroll` | `HideOnScrollConfig` | - | Configuration for hide-on-scroll animation |
126132
| `infiniteScroll` | `InfiniteScrollProps` | - | Configuration for infinite scrolling |
127133

134+
### `AnimatedListProps<T>` <Badge text="New" variant="tip" /> (AnimatedVList & AnimatedHList)
135+
136+
| Prop | Type | Default | Description |
137+
|------|------|---------|-------------|
138+
| `data` | `readonly T[]` | - | Array of data items to render |
139+
| `renderItem` | `(item: { item: T; index: number }) => React.ReactElement` | - | Function to render each list item |
140+
| `keyExtractor` | `(item: T, index: number) => string` | - | Function to extract unique key for each item |
141+
| `padding` | `keyof Theme['spacing']` | - | Internal padding using theme spacing |
142+
| `margin` | `keyof Theme['spacing']` | - | External margin using theme spacing |
143+
| `backgroundColor` | `keyof Theme['colors']` | `'background'` | Background color from theme |
144+
| `borderRadius` | `keyof Theme['components']['borderRadius']` | - | Border radius from theme |
145+
| `themed` | `boolean` | `false` | Enable theme-based styling |
146+
| `infiniteScroll` | `InfiniteScrollProps` | - | Configuration for infinite scrolling |
147+
128148
### `FlashListProps<T>` <Badge text="New" variant="tip" /> (VFlashList & HFlashList)
129149

130150
| Prop | Type | Default | Description |
@@ -553,6 +573,42 @@ const InfiniteProductList = () => {
553573
```
554574
</TabItem>
555575

576+
<TabItem label="AnimatedVList (Vertical)">
577+
<Badge text="New" variant="tip" />
578+
```tsx
579+
// Animated vertical list with scroll-based animations
580+
<AnimatedVList
581+
data={items}
582+
renderItem={renderItem}
583+
keyExtractor={keyExtractor}
584+
padding="md"
585+
infiniteScroll={{
586+
onLoadMore: loadMore,
587+
loading: loading,
588+
hasMore: hasMore
589+
}}
590+
/>
591+
```
592+
</TabItem>
593+
594+
<TabItem label="AnimatedHList (Horizontal)">
595+
<Badge text="New" variant="tip" />
596+
```tsx
597+
// Animated horizontal list with scroll-based animations
598+
<AnimatedHList
599+
data={items}
600+
renderItem={renderItem}
601+
keyExtractor={keyExtractor}
602+
showsHorizontalScrollIndicator={false}
603+
infiniteScroll={{
604+
onLoadMore: loadMore,
605+
loading: loading,
606+
hasMore: hasMore
607+
}}
608+
/>
609+
```
610+
</TabItem>
611+
556612
<TabItem label="VFlashList (Vertical)">
557613
<Badge text="New" variant="tip" />
558614
```tsx
@@ -668,6 +724,15 @@ const InfiniteProductList = () => {
668724
- **Real-time data** updates requiring smooth performance
669725
</Card>
670726

727+
<Card title="When to Use AnimatedList" icon="right-arrow"> <Badge text="New" variant="tip" />
728+
729+
- Lists requiring **smooth animations** on scroll or item updates
730+
- **Interactive feeds** with dynamic content transitions
731+
- **Social media-like** interfaces with engaging animations
732+
- **Item-level animations** for entering/exiting elements
733+
- **Gesture-based** interactions with animated feedback
734+
</Card>
735+
671736
<Card title="When to Use Standard List" icon="setting">
672737
- **Simple lists** with fewer than 100 items
673738
- **Static content** that doesn't change frequently
@@ -701,6 +766,78 @@ const InfiniteProductList = () => {
701766

702767
## Advanced Usage
703768

769+
### Animated List with Scroll-Based Animations <Badge text="New" variant="tip" />
770+
771+
```tsx
772+
const AnimatedFeed = () => {
773+
const [posts, setPosts] = useState<Post[]>([]);
774+
const [loading, setLoading] = useState(false);
775+
const [hasMore, setHasMore] = useState(true);
776+
777+
const loadMorePosts = useCallback(async () => {
778+
if (loading || !hasMore) return;
779+
780+
setLoading(true);
781+
try {
782+
const newPosts = await fetchPosts(posts.length, 10);
783+
setPosts(prev => [...prev, ...newPosts]);
784+
setHasMore(newPosts.length === 10);
785+
} catch (error) {
786+
console.error('Failed to load posts:', error);
787+
} finally {
788+
setLoading(false);
789+
}
790+
}, [posts.length, loading, hasMore]);
791+
792+
const renderPost = useCallback(({ item }: { item: Post }) => (
793+
<Animated.View
794+
entering={FadeIn.duration(300)}
795+
exiting={FadeOut.duration(300)}
796+
>
797+
<Card style={styles.postCard}>
798+
<Box style={styles.postHeader}>
799+
<Image source={{ uri: item.avatar }} style={styles.avatar} />
800+
<Box style={styles.userInfo}>
801+
<Typography weight="semibold">{item.username}</Typography>
802+
<Typography variant="caption" color="muted">
803+
{item.timestamp}
804+
</Typography>
805+
</Box>
806+
</Box>
807+
808+
<Image source={{ uri: item.image }} style={styles.postImage} />
809+
810+
<Box style={styles.postActions}>
811+
<TouchableOpacity style={styles.actionButton}>
812+
<Typography>❤️ {item.likes}</Typography>
813+
</TouchableOpacity>
814+
<TouchableOpacity style={styles.actionButton}>
815+
<Typography>💬 {item.comments}</Typography>
816+
</TouchableOpacity>
817+
</Box>
818+
</Card>
819+
</Animated.View>
820+
), []);
821+
822+
return (
823+
<AnimatedVList
824+
data={posts}
825+
renderItem={renderPost}
826+
keyExtractor={(item) => item.id}
827+
infiniteScroll={{
828+
onLoadMore: loadMorePosts,
829+
loading,
830+
hasMore,
831+
threshold: 0.5
832+
}}
833+
themed
834+
backgroundColor="background"
835+
showsVerticalScrollIndicator={false}
836+
/>
837+
);
838+
};
839+
```
840+
704841
### Custom List with Ref
705842

706843
```tsx

0 commit comments

Comments
 (0)