-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add BottomSheetV2 #42201
feat: Add BottomSheetV2 #42201
Changes from all commits
e29c53f
5930438
20f3447
16bcbfc
8e10784
6e8ac80
dfac406
6921d2b
ada3dc7
d1d6ed0
b9a9f1e
1aee28f
c0a14ab
a13fd7b
1e7baab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import BottomSheetExternal, { | ||
BottomSheetBackdrop, | ||
BottomSheetScrollView, | ||
useBottomSheetDynamicSnapPoints, | ||
} from '@gorhom/bottom-sheet'; | ||
import { Modal } from 'react-native'; | ||
import { GestureHandlerRootView } from 'react-native-gesture-handler'; | ||
|
||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { | ||
forwardRef, | ||
useCallback, | ||
useState, | ||
useImperativeHandle, | ||
useRef, | ||
} from '@wordpress/element'; | ||
import { usePreferredColorSchemeStyle } from '@wordpress/compose'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import styles from './style.scss'; | ||
|
||
function BottomSheetWithRef( | ||
{ children, index, onClose, snapPoints = [ '50%' ] } = {}, | ||
ref | ||
) { | ||
const backgroundStyle = [ | ||
styles[ 'bottom-sheet-v2__background' ], | ||
usePreferredColorSchemeStyle( | ||
null, | ||
styles[ 'bottom-sheet-v2__background--dark' ] | ||
), | ||
]; | ||
|
||
const renderBackdrop = useCallback( | ||
( props ) => ( | ||
<BottomSheetBackdrop | ||
{ ...props } | ||
opacity={ 0.2 } | ||
disappearsOnIndex={ -1 } | ||
appearsOnIndex={ 0 } | ||
/> | ||
), | ||
[] | ||
); | ||
|
||
const { | ||
animatedHandleHeight, | ||
animatedSnapPoints, | ||
animatedContentHeight, | ||
handleContentLayout, | ||
} = useBottomSheetDynamicSnapPoints( snapPoints ); | ||
Comment on lines
+53
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may make more sense to expect a consumer of |
||
|
||
return ( | ||
<BottomSheetExternal | ||
backdropComponent={ renderBackdrop } | ||
backgroundStyle={ backgroundStyle } | ||
enablePanDownToClose={ true } | ||
contentHeight={ animatedContentHeight } | ||
handleHeight={ animatedHandleHeight } | ||
handleIndicatorStyle={ | ||
styles[ 'bottom-sheet-v2__handle-indicator' ] | ||
} | ||
index={ index } | ||
onClose={ onClose } | ||
ref={ ref } | ||
snapPoints={ animatedSnapPoints } | ||
> | ||
<BottomSheetScrollView onLayout={ handleContentLayout }> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The current |
||
{ children } | ||
</BottomSheetScrollView> | ||
</BottomSheetExternal> | ||
); | ||
} | ||
|
||
const BottomSheet = forwardRef( BottomSheetWithRef ); | ||
|
||
const BottomSheetModalWithRef = ( | ||
{ index = 0, onClose, ...bottomSheetProps }, | ||
ref | ||
) => { | ||
const bottomSheetRef = useRef( null ); | ||
|
||
/** | ||
* `internalIndex` is used to allow displaying the modal on initial render, | ||
* which is required in some areas of the code base that do not easily support | ||
* a call to an imperative `present` method. | ||
*/ | ||
const [ internalIndex, setInternalIndex ] = useState( index ); | ||
const [ visible, setVisible ] = useState( index >= 0 ); | ||
|
||
const handlePresent = useCallback( () => { | ||
setVisible( true ); | ||
setInternalIndex( index >= 0 ? index : 0 ); | ||
}, [ index ] ); | ||
|
||
const handleDismiss = useCallback( () => { | ||
bottomSheetRef.current?.close(); | ||
}, [] ); | ||
|
||
/** | ||
* Utilize imperative handle to mimic the `@gorhom/bottom-sheet` API, which | ||
* would simplify migrating to `BottomSheetModal` in the future if the editor | ||
* header navigation is rendered by React Native, not the native host app. | ||
*/ | ||
useImperativeHandle( | ||
ref, | ||
() => ( { | ||
present: handlePresent, | ||
dismiss: handleDismiss, | ||
} ), | ||
[ handleDismiss, handlePresent ] | ||
); | ||
|
||
const handleClose = useCallback( () => { | ||
setVisible( false ); | ||
if ( onClose ) { | ||
onClose(); | ||
} | ||
}, [ onClose ] ); | ||
|
||
return ( | ||
<Modal | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
onRequestClose={ handleDismiss } | ||
transparent={ true } | ||
visible={ visible } | ||
> | ||
<GestureHandlerRootView | ||
style={ styles[ 'bottom-sheet-v2__gesture-handler' ] } | ||
> | ||
Comment on lines
+134
to
+136
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Android modals require a separate |
||
<BottomSheet | ||
{ ...bottomSheetProps } | ||
index={ internalIndex } | ||
ref={ bottomSheetRef } | ||
onClose={ handleClose } | ||
/> | ||
</GestureHandlerRootView> | ||
</Modal> | ||
); | ||
}; | ||
|
||
const BottomSheetModal = forwardRef( BottomSheetModalWithRef ); | ||
|
||
BottomSheetModal.CONTENT_HEIGHT = 'CONTENT_HEIGHT'; | ||
|
||
export default BottomSheetModal; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
.bottom-sheet-v2__gesture-handler { | ||
flex: 1; | ||
} | ||
|
||
.bottom-sheet-v2__background { | ||
border-radius: 8px; | ||
} | ||
|
||
.bottom-sheet-v2__background--dark { | ||
background-color: $modal-background-dark; | ||
} | ||
|
||
.bottom-sheet-v2__handle-indicator { | ||
background-color: $light-gray-400; | ||
border-radius: 2px; | ||
width: 36px; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The existing
BottomSheet
includes bottom offset to account for safe area and horizontal padding. I am undecided as to whether this should reside in theBottomSheetV2
abstraction. There are times where the horizontal padding is overridden in certain contexts. Should this be managed by theBottomSheet
or the individual context controlled by the child? E.g.PanelBody
provides its own padding equaling the padding provided byBottomSheet
.