diff --git a/packages/core/src/js/feedback/FeedbackForm.styles.ts b/packages/core/src/js/feedback/FeedbackForm.styles.ts index 57d407adf3..1e90af07c6 100644 --- a/packages/core/src/js/feedback/FeedbackForm.styles.ts +++ b/packages/core/src/js/feedback/FeedbackForm.styles.ts @@ -1,3 +1,5 @@ +import type { ViewStyle } from 'react-native'; + import type { FeedbackFormStyles } from './FeedbackForm.types'; const PURPLE = 'rgba(88, 74, 192, 1)'; @@ -77,10 +79,33 @@ const defaultStyles: FeedbackFormStyles = { width: 40, height: 40, }, - modalBackground: { - flex: 1, - justifyContent: 'center', - }, +}; + +export const modalWrapper: ViewStyle = { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, +}; + +export const modalBackground: ViewStyle = { + flex: 1, + justifyContent: 'flex-end', +}; + +export const modalSheetContainer: ViewStyle = { + backgroundColor: '#ffffff', + borderTopLeftRadius: 16, + borderTopRightRadius: 16, + overflow: 'hidden', + alignSelf: 'stretch', + height: '92%', + shadowColor: '#000', + shadowOffset: { width: 0, height: -3 }, + shadowOpacity: 0.1, + shadowRadius: 4, + elevation: 5, }; export default defaultStyles; diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index d8a295fa9b..5b8dc28b70 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -7,6 +7,7 @@ import { Image, Keyboard, KeyboardAvoidingView, + Platform, SafeAreaView, ScrollView, Text, @@ -130,8 +131,11 @@ export class FeedbackForm extends React.Component - - + + diff --git a/packages/core/src/js/feedback/FeedbackForm.types.ts b/packages/core/src/js/feedback/FeedbackForm.types.ts index fbeee76896..cffe54447a 100644 --- a/packages/core/src/js/feedback/FeedbackForm.types.ts +++ b/packages/core/src/js/feedback/FeedbackForm.types.ts @@ -204,7 +204,6 @@ export interface FeedbackFormStyles { screenshotText?: TextStyle; titleContainer?: ViewStyle; sentryLogo?: ImageStyle; - modalBackground?: ViewStyle; } /** diff --git a/packages/core/src/js/feedback/FeedbackFormManager.tsx b/packages/core/src/js/feedback/FeedbackFormManager.tsx index 4676f90258..b7b9f9fe55 100644 --- a/packages/core/src/js/feedback/FeedbackFormManager.tsx +++ b/packages/core/src/js/feedback/FeedbackFormManager.tsx @@ -1,9 +1,9 @@ import { logger } from '@sentry/core'; import * as React from 'react'; -import { Modal, View } from 'react-native'; +import { Animated, KeyboardAvoidingView, Modal, Platform, View } from 'react-native'; import { FeedbackForm } from './FeedbackForm'; -import defaultStyles from './FeedbackForm.styles'; +import { modalBackground, modalSheetContainer, modalWrapper } from './FeedbackForm.styles'; import type { FeedbackFormStyles } from './FeedbackForm.types'; import { getFeedbackOptions } from './integration'; import { isModalSupported } from './utils'; @@ -40,9 +40,15 @@ interface FeedbackFormProviderProps { styles?: FeedbackFormStyles; } +interface FeedbackFormProviderState { + isVisible: boolean; + backgroundOpacity: Animated.Value; +} + class FeedbackFormProvider extends React.Component { - public state = { + public state: FeedbackFormProviderState = { isVisible: false, + backgroundOpacity: new Animated.Value(0), }; public constructor(props: FeedbackFormProviderProps) { @@ -50,6 +56,21 @@ class FeedbackFormProvider extends React.Component { FeedbackFormManager.initialize(this._setVisibilityFunction); } + /** + * Animates the background opacity when the modal is shown. + */ + public componentDidUpdate(_prevProps: any, prevState: FeedbackFormProviderState): void { + if (!prevState.isVisible && this.state.isVisible) { + Animated.timing(this.state.backgroundOpacity, { + toValue: 1, + duration: 300, + useNativeDriver: true, + }).start(); + } else if (prevState.isVisible && !this.state.isVisible) { + this.state.backgroundOpacity.setValue(0); + } + } + /** * Renders the feedback form modal. */ @@ -59,8 +80,12 @@ class FeedbackFormProvider extends React.Component { return <>{this.props.children}; } - const { isVisible } = this.state; - const styles: FeedbackFormStyles = { ...defaultStyles, ...this.props.styles }; + const { isVisible, backgroundOpacity } = this.state; + + const backgroundColor = backgroundOpacity.interpolate({ + inputRange: [0, 1], + outputRange: ['rgba(0, 0, 0, 0)', 'rgba(0, 0, 0, 0.9)'], + }); // Wrapping the `Modal` component in a `View` component is necessary to avoid // issues like https://github.com/software-mansion/react-native-reanimated/issues/6035 @@ -68,16 +93,21 @@ class FeedbackFormProvider extends React.Component { <> {this.props.children} {isVisible && ( - + - - - + + + + + - + )} ); diff --git a/packages/core/test/feedback/__snapshots__/FeedbackForm.test.tsx.snap b/packages/core/test/feedback/__snapshots__/FeedbackForm.test.tsx.snap index a642bd88da..a3c2857ac9 100644 --- a/packages/core/test/feedback/__snapshots__/FeedbackForm.test.tsx.snap +++ b/packages/core/test/feedback/__snapshots__/FeedbackForm.test.tsx.snap @@ -31,7 +31,9 @@ exports[`FeedbackForm matches the snapshot with custom styles 1`] = ` ] } > - + - + - + - + - + - +