Header blurred banner on overscroll (take 2) (#5474)

* grow banner when overscrolling

* add blurview

* make backdrop blur as it scrolls

* add activity indicator

* use rotated spinner instead of arrow

* persist position of back button

* make back button prettier

* make blur less jarring

* Unify effects

* Tweak impl

* determine if should animate based on scroll amount

* sign comment

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
This commit is contained in:
Samuel Newman
2024-09-25 15:01:25 +01:00
committed by GitHub
parent bd393b1b38
commit f7a2368100
11 changed files with 341 additions and 63 deletions
+41
View File
@@ -0,0 +1,41 @@
import React, {useContext} from 'react'
import {SharedValue} from 'react-native-reanimated'
import {isIOS} from '#/platform/detection'
export const PagerHeaderContext =
React.createContext<SharedValue<number> | null>(null)
/**
* Passes the scrollY value to the pager header's banner, so it can grow on
* overscroll on iOS. Not necessary to use this context provider on other platforms.
*
* @platform ios
*/
export function PagerHeaderProvider({
scrollY,
children,
}: {
scrollY: SharedValue<number>
children: React.ReactNode
}) {
return (
<PagerHeaderContext.Provider value={scrollY}>
{children}
</PagerHeaderContext.Provider>
)
}
export function usePagerHeaderContext() {
const scrollY = useContext(PagerHeaderContext)
if (isIOS) {
if (!scrollY) {
throw new Error(
'usePagerHeaderContext must be used within a HeaderProvider',
)
}
return {scrollY}
} else {
return null
}
}
+17 -14
View File
@@ -22,6 +22,7 @@ import {ScrollProvider} from '#/lib/ScrollContext'
import {isIOS} from '#/platform/detection'
import {Pager, PagerRef, RenderTabBarFnProps} from '#/view/com/pager/Pager'
import {ListMethods} from '../util/List'
import {PagerHeaderProvider} from './PagerHeaderContext'
import {TabBar} from './TabBar'
export interface PagerWithHeaderChildParams {
@@ -82,20 +83,22 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
const renderTabBar = React.useCallback(
(props: RenderTabBarFnProps) => {
return (
<PagerTabBar
headerOnlyHeight={headerOnlyHeight}
items={items}
isHeaderReady={isHeaderReady}
renderHeader={renderHeader}
currentPage={currentPage}
onCurrentPageSelected={onCurrentPageSelected}
onTabBarLayout={onTabBarLayout}
onHeaderOnlyLayout={onHeaderOnlyLayout}
onSelect={props.onSelect}
scrollY={scrollY}
testID={testID}
allowHeaderOverScroll={allowHeaderOverScroll}
/>
<PagerHeaderProvider scrollY={scrollY}>
<PagerTabBar
headerOnlyHeight={headerOnlyHeight}
items={items}
isHeaderReady={isHeaderReady}
renderHeader={renderHeader}
currentPage={currentPage}
onCurrentPageSelected={onCurrentPageSelected}
onTabBarLayout={onTabBarLayout}
onHeaderOnlyLayout={onHeaderOnlyLayout}
onSelect={props.onSelect}
scrollY={scrollY}
testID={testID}
allowHeaderOverScroll={allowHeaderOverScroll}
/>
</PagerHeaderProvider>
)
},
[
+1 -1
View File
@@ -202,7 +202,7 @@ const styles = StyleSheet.create({
},
bannerImage: {
width: '100%',
height: 150,
height: '100%',
},
defaultBanner: {
backgroundColor: '#0070ff',