Autosize dialog, handle max height, Dialog.ScrolLView not working

This commit is contained in:
Eric Bailey
2024-01-14 11:14:13 -06:00
parent cb1bfe0e6f
commit 4f71e4ee7d
4 changed files with 36 additions and 33 deletions
+25 -4
View File
@@ -1,6 +1,7 @@
import React, {useImperativeHandle} from 'react' import React, {useImperativeHandle} from 'react'
import {View, Dimensions} from 'react-native' import {View, Dimensions, LayoutChangeEvent} from 'react-native'
import BottomSheet, {BottomSheetBackdrop} from '@gorhom/bottom-sheet' import BottomSheet, {BottomSheetBackdrop} from '@gorhom/bottom-sheet'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {useTheme, atoms as a} from '#/alf' import {useTheme, atoms as a} from '#/alf'
import {Portal} from '#/components/Portal' import {Portal} from '#/components/Portal'
@@ -12,6 +13,13 @@ import {
} from '#/components/Dialog/types' } from '#/components/Dialog/types'
import {Context} from '#/components/Dialog/context' import {Context} from '#/components/Dialog/context'
/**
* Exports
*/
export {
BottomSheetScrollView as ScrollView,
BottomSheetTextInput as TextInput,
} from '@gorhom/bottom-sheet'
export {useDialogControl, useDialogContext} from '#/components/Dialog/context' export {useDialogControl, useDialogContext} from '#/components/Dialog/context'
export * from '#/components/Dialog/types' export * from '#/components/Dialog/types'
@@ -21,8 +29,12 @@ export function Outer({
onClose, onClose,
nativeOptions, nativeOptions,
}: React.PropsWithChildren<DialogOuterProps>) { }: React.PropsWithChildren<DialogOuterProps>) {
const insets = useSafeAreaInsets()
const t = useTheme() const t = useTheme()
const sheet = React.useRef<BottomSheet>(null) const sheet = React.useRef<BottomSheet>(null)
const [defaultSnapPoints, setDefaultSnapPoints] = React.useState<
string | number
>('25%')
const open = React.useCallback<DialogControlProps['open']>((i = 0) => { const open = React.useCallback<DialogControlProps['open']>((i = 0) => {
sheet.current?.snapToIndex(i) sheet.current?.snapToIndex(i)
@@ -33,6 +45,15 @@ export function Outer({
onClose?.() onClose?.()
}, [onClose]) }, [onClose])
const measureDefaultSnapPoint = React.useCallback(
(e: LayoutChangeEvent) => {
const min = e.nativeEvent.layout.height + insets.bottom + 40
const max = Dimensions.get('window').height - insets.top - 40
setDefaultSnapPoints(min < max ? min : max)
},
[insets, setDefaultSnapPoints],
)
useImperativeHandle( useImperativeHandle(
control.ref, control.ref,
() => ({ () => ({
@@ -47,9 +68,9 @@ export function Outer({
return ( return (
<Portal> <Portal>
<BottomSheet <BottomSheet
snapPoints={['90%']} snapPoints={[defaultSnapPoints]}
enablePanDownToClose enablePanDownToClose
keyboardBehavior="extend" keyboardBehavior="interactive"
android_keyboardInputMode="adjustResize" android_keyboardInputMode="adjustResize"
{...(nativeOptions?.sheet || {})} {...(nativeOptions?.sheet || {})}
ref={sheet} ref={sheet}
@@ -78,7 +99,7 @@ export function Outer({
}, },
]} ]}
/> />
{children} <View onLayout={measureDefaultSnapPoint}>{children}</View>
</Context.Provider> </Context.Provider>
</BottomSheet> </BottomSheet>
</Portal> </Portal>
+1
View File
@@ -11,6 +11,7 @@ import {Button} from '#/components/Button'
import {DialogOuterProps, DialogInnerProps} from '#/components/Dialog/types' import {DialogOuterProps, DialogInnerProps} from '#/components/Dialog/types'
import {Context, useDialogContext} from '#/components/Dialog/context' import {Context, useDialogContext} from '#/components/Dialog/context'
export {ScrollView, TextInput} from 'react-native'
export {useDialogControl, useDialogContext} from '#/components/Dialog/context' export {useDialogControl, useDialogContext} from '#/components/Dialog/context'
export * from '#/components/Dialog/types' export * from '#/components/Dialog/types'
+9 -29
View File
@@ -1,6 +1,5 @@
import React from 'react' import React from 'react'
import {View, PressableProps, LayoutChangeEvent} from 'react-native' import {View, PressableProps} from 'react-native'
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {useTheme, atoms as a} from '#/alf' import {useTheme, atoms as a} from '#/alf'
import {H4, P} from '#/components/Typography' import {H4, P} from '#/components/Typography'
@@ -24,43 +23,24 @@ export function Outer({
}: React.PropsWithChildren<{ }: React.PropsWithChildren<{
control: Dialog.DialogOuterProps['control'] control: Dialog.DialogOuterProps['control']
}>) { }>) {
const insets = useSafeAreaInsets()
const titleId = React.useId() const titleId = React.useId()
const descriptionId = React.useId() const descriptionId = React.useId()
const [defaultSnapPoints, setDefaultSnapPoints] = React.useState<
string | number
>('25%')
const context = React.useMemo( const context = React.useMemo(
() => ({titleId, descriptionId}), () => ({titleId, descriptionId}),
[titleId, descriptionId], [titleId, descriptionId],
) )
const measureDefaultSnapPoint = React.useCallback(
(e: LayoutChangeEvent) => {
setDefaultSnapPoints(e.nativeEvent.layout.height + insets.bottom + 50)
},
[insets, setDefaultSnapPoints],
)
return ( return (
<Dialog.Outer <Dialog.Outer control={control}>
control={control}
nativeOptions={{
sheet: {
snapPoints: [defaultSnapPoints],
},
}}>
<Context.Provider value={context}> <Context.Provider value={context}>
<View onLayout={measureDefaultSnapPoint}> <Dialog.Inner
<Dialog.Inner accessibilityLabelledBy={titleId}
accessibilityLabelledBy={titleId} accessibilityDescribedBy={descriptionId}
accessibilityDescribedBy={descriptionId} style={{width: 'auto', maxWidth: 400}}>
style={{width: 'auto', maxWidth: 400}}> <Dialog.Handle />
<Dialog.Handle /> {children}
{children} </Dialog.Inner>
</Dialog.Inner>
</View>
</Context.Provider> </Context.Provider>
</Dialog.Outer> </Dialog.Outer>
) )
+1
View File
@@ -50,6 +50,7 @@ export function Dialogs() {
accessibilityLabelledBy="dialog-title" accessibilityLabelledBy="dialog-title"
accessibilityDescribedBy="dialog-description"> accessibilityDescribedBy="dialog-description">
<Dialog.Handle /> <Dialog.Handle />
<View style={[a.gap_md]}> <View style={[a.gap_md]}>
<H3 nativeID="dialog-title">Dialog</H3> <H3 nativeID="dialog-title">Dialog</H3>
<P nativeID="dialog-description">Description</P> <P nativeID="dialog-description">Description</P>