@utilitywarehouse/hearth-react-native 0.28.6 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.storybook/preview.tsx +7 -4
  2. package/.turbo/turbo-build.log +1 -1
  3. package/.turbo/turbo-lint.log +15 -18
  4. package/CHANGELOG.md +44 -0
  5. package/build/components/Combobox/Combobox.js +1 -1
  6. package/build/components/Modal/Modal.d.ts +1 -1
  7. package/build/components/Modal/Modal.js +6 -95
  8. package/build/components/Modal/Modal.props.d.ts +2 -31
  9. package/build/components/Modal/Modal.shared.types.d.ts +22 -0
  10. package/build/components/Modal/Modal.web.d.ts +1 -1
  11. package/build/components/Modal/Modal.web.js +6 -71
  12. package/build/components/NavModal/NavModal.d.ts +3 -0
  13. package/build/components/NavModal/NavModal.js +190 -0
  14. package/build/components/NavModal/NavModal.props.d.ts +15 -0
  15. package/build/components/NavModal/NavModal.props.js +1 -0
  16. package/build/components/NavModal/index.d.ts +2 -0
  17. package/build/components/NavModal/index.js +1 -0
  18. package/build/components/Select/Select.js +1 -1
  19. package/build/components/index.d.ts +2 -1
  20. package/build/components/index.js +2 -1
  21. package/docs/changelog.mdx +34 -0
  22. package/docs/components/AllComponents.web.tsx +709 -689
  23. package/package.json +3 -1
  24. package/src/components/Combobox/Combobox.tsx +1 -1
  25. package/src/components/Modal/Modal.docs.mdx +5 -122
  26. package/src/components/Modal/Modal.props.ts +2 -34
  27. package/src/components/Modal/Modal.shared.types.ts +23 -0
  28. package/src/components/Modal/Modal.stories.tsx +0 -1
  29. package/src/components/Modal/Modal.tsx +11 -174
  30. package/src/components/Modal/Modal.web.tsx +29 -127
  31. package/src/components/NavModal/NavModal.docs.mdx +178 -0
  32. package/src/components/NavModal/NavModal.figma.tsx +13 -0
  33. package/src/components/NavModal/NavModal.props.ts +23 -0
  34. package/src/components/NavModal/NavModal.stories.tsx +131 -0
  35. package/src/components/NavModal/NavModal.tsx +375 -0
  36. package/src/components/NavModal/index.ts +2 -0
  37. package/src/components/Select/Select.tsx +1 -1
  38. package/src/components/index.ts +3 -1
  39. package/build/components/SafeAreaView/SafeAreaView.d.ts +0 -5
  40. package/build/components/SafeAreaView/SafeAreaView.js +0 -117
  41. package/build/components/SafeAreaView/SafeAreaView.props.d.ts +0 -17
  42. package/build/components/SafeAreaView/index.d.ts +0 -2
  43. package/build/components/SafeAreaView/index.js +0 -1
  44. package/src/components/SafeAreaView/SafeAreaView.props.ts +0 -20
  45. package/src/components/SafeAreaView/SafeAreaView.tsx +0 -173
  46. package/src/components/SafeAreaView/index.ts +0 -2
  47. /package/build/components/{SafeAreaView/SafeAreaView.props.js → Modal/Modal.shared.types.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilitywarehouse/hearth-react-native",
3
- "version": "0.28.6",
3
+ "version": "0.29.0",
4
4
  "description": "Utility Warehouse React Native UI library",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -46,6 +46,7 @@
46
46
  "react-native-gesture-handler": "2.28.0",
47
47
  "react-native-nitro-modules": "0.31.4",
48
48
  "react-native-reanimated": "4.1.3",
49
+ "react-native-safe-area-context": "5.6.1",
49
50
  "react-native-svg": "^15.12.1",
50
51
  "react-native-unistyles": "3.0.17",
51
52
  "react-native-web": "^0.20.0",
@@ -69,6 +70,7 @@
69
70
  "react-native": ">=0.77",
70
71
  "react-native-gesture-handler": ">=2",
71
72
  "react-native-reanimated": "3.x || ^4.x",
73
+ "react-native-safe-area-context": "5.x",
72
74
  "react-native-svg": ">=13.4.0",
73
75
  "react-native-unistyles": ">=3.0.0",
74
76
  "react-native-web": ">=0.19"
@@ -1,6 +1,7 @@
1
1
  import { CloseSmallIcon, SearchMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
2
2
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { GestureResponderEvent, Pressable, TextInput, View } from 'react-native';
4
+ import { SafeAreaView } from 'react-native-safe-area-context';
4
5
  import { StyleSheet } from 'react-native-unistyles';
5
6
  import { useTheme } from '../../hooks';
6
7
  import { BodyText } from '../BodyText';
@@ -9,7 +10,6 @@ import { DetailText } from '../DetailText';
9
10
  import { FormField, useFormFieldContext } from '../FormField';
10
11
  import { Icon } from '../Icon';
11
12
  import { Input } from '../Input';
12
- import { SafeAreaView } from '../SafeAreaView';
13
13
  import { Spinner } from '../Spinner';
14
14
  import { UnstyledIconButton } from '../UnstyledIconButton';
15
15
  import { ComboboxContext, ComboboxSelection } from './Combobox.context';
@@ -1,8 +1,6 @@
1
1
  import { Canvas, Controls, Meta, Story } from '@storybook/addon-docs/blocks';
2
2
  import { BodyText, BottomSheetModal, Box, Button, Center, Heading, Modal } from '../../';
3
3
  import StorybookLink from '../../../../../shared/storybook/StorybookLink';
4
- import modalAndroidVideo from '../../../docs/assets/modal-android.mp4';
5
- import modaliOSVideo from '../../../docs/assets/modal-ios.mp4';
6
4
  import { BackToTopButton, UsageWrap, ViewFigmaButton } from '../../../docs/components';
7
5
  import * as Stories from './Modal.stories';
8
6
 
@@ -18,6 +16,8 @@ The `Modal` component provides a versatile dialog interface that slides up from
18
16
 
19
17
  The Modal component is ideal for displaying important information, collecting user input, or presenting choices that require user attention without navigating away from the current screen.
20
18
 
19
+ If you need a modal layout inside a React Navigation modal screen, use <StorybookLink to="components-navmodal">`NavModal`</StorybookLink> instead.
20
+
21
21
  - [Playground](#playground)
22
22
  - [Usage](#usage)
23
23
  - [Props](#props)
@@ -31,7 +31,6 @@ The Modal component is ideal for displaying important information, collecting us
31
31
  - [Loading State](#loading-state)
32
32
  - [Without Close Button](#without-close-button)
33
33
  - [Single Action Modal](#single-action-modal)
34
- - [Modal in Navigation Modal](#modal-in-navigation-modal)
35
34
  - [Integration Notes](#integration-notes)
36
35
  - [External Resources](#external-resources)
37
36
 
@@ -108,10 +107,7 @@ The Modal component extends the `BottomSheetModal` component and accepts all of
108
107
  | `primaryButtonProps` | `Omit<ButtonWithoutChildrenProps, 'children'>` | Additional props to pass to the primary button (colorScheme defaults to 'highlight', variant to 'solid') | - |
109
108
  | `secondaryButtonProps` | `Omit<ButtonWithoutChildrenProps, 'children'>` | Additional props to pass to the secondary button (colorScheme defaults to 'functional', variant to 'outline') | - |
110
109
  | `closeButtonProps` | `Omit<UnstyledIconButtonProps, 'children'>` | Additional props to pass to the close button | - |
111
- | `fullscreen` | `boolean` | Whether the modal should take up the full screen height. Only applies when `inNavModal` is `false` | `false` |
112
- | `inNavModal` | `boolean` | Renders the modal correctly when used inside a navigation modal | `false` |
113
- | `background` | `'default' \| 'brand'` | Sets the modal background. Only applies when `inNavModal` is `true` | `'default'` |
114
- | `scrollable` | `boolean` | Whether the modal's content should be placed in a `ScrollView`. Only applies when `inNavModal` is `true` | `true` |
110
+ | `fullscreen` | `boolean` | Whether the modal should take up the full screen height | `false` |
115
111
 
116
112
  \* use this to detect if the modal has been opened or closed, index 0 indicates open state and -1 indicates closed state
117
113
 
@@ -462,122 +458,9 @@ const AlertModal = () => {
462
458
  };
463
459
  ```
464
460
 
465
- ### Modal In Navigation Modal
466
-
467
- When wanting to use the Modal component in a navigation context using [React Navigation](https://reactnavigation.org/docs/modal), you can set `inNavModal` to `true` to make it behave like a standard modal screen.
468
-
469
- Within React Navigation, you can set `presentation: 'modal'` in the screen's settings to have the Modal look and behave like a standard modal/bottom sheet, or you can set `presentation: 'fullScreenModal'` to have the Modal fill the entire screen.
470
-
471
- When using `inNavModal`, by default the content will be rendered inside a `ScrollView` to ensure it is scrollable, especially on smaller devices or smaller modals. You can disable this by setting `scrollable={false}` if, for example, you need to center your content or add some custom content.
472
-
473
- Here's an example of how to implement this with custom close animations for Android:
474
-
475
- ```tsx
476
- import { useNavigation } from '@react-navigation/native';
477
- import { useCallback, useEffect, useRef } from 'react';
478
- import { Platform, StyleSheet, View } from 'react-native';
479
-
480
- import { BodyText, Heading, InlineLink, Modal } from '@utilitywarehouse/hearth-react-native';
481
- import type { NavigationAction } from '@react-navigation/native';
482
-
483
- export default function ModalScreen({ onClose }: { onClose?: () => void }) {
484
- const modalRef = useRef<Modal>(null);
485
- const navigation = useNavigation();
486
- const isClosingRef = useRef(false);
487
-
488
- const handleClose = useCallback(
489
- (action?: NavigationAction) => {
490
- if (Platform.OS === 'ios') {
491
- if (onClose) {
492
- onClose();
493
- } else {
494
- navigation.goBack();
495
- }
496
-
497
- return;
498
- }
499
-
500
- if (isClosingRef.current) {
501
- return;
502
- }
503
-
504
- isClosingRef.current = true;
505
- // Trigger our custom animation first
506
- modalRef.current?.triggerCloseAnimation?.();
507
-
508
- // Delay the actual navigation to allow our animation to play
509
- setTimeout(() => {
510
- if (onClose) {
511
- onClose();
512
- } else if (action) {
513
- // Dispatch the original action (e.g. popToTop, replace, reset)
514
- // so we don't override the caller's intended navigation behaviour
515
- navigation.dispatch(action);
516
- } else {
517
- navigation.goBack();
518
- }
519
- }, 100); // Match Modal animation duration
520
- },
521
- [navigation, onClose]
522
- );
523
-
524
- useEffect(() => {
525
- if (Platform.OS === 'android') {
526
- const unsubscribe = navigation.addListener('beforeRemove', e => {
527
- if (!isClosingRef.current) {
528
- // Prevent default behavior of the navigation action so we can
529
- // play the close animation before letting navigation proceed
530
- e.preventDefault();
531
- handleClose(e.data.action);
532
- }
533
- });
534
-
535
- return unsubscribe;
536
- }
537
- }, [navigation, handleClose]);
538
-
539
- return (
540
- <Modal
541
- ref={modalRef}
542
- inNavModal
543
- onPressCloseButton={handleClose}
544
- primaryButtonText="Action"
545
- onPressPrimaryButton={handleClose}
546
- secondaryButtonText="Cancel"
547
- onPressSecondaryButton={handleClose}
548
- >
549
- <View style={styles.container}>
550
- <Heading size="xl">This is a modal</Heading>
551
- <BodyText>
552
- <InlineLink onPress={handleClose} style={styles.link}>
553
- Go to home screen
554
- </InlineLink>
555
- </BodyText>
556
- </View>
557
- </Modal>
558
- );
559
- }
560
-
561
- const styles = StyleSheet.create({
562
- container: {
563
- flex: 1,
564
- alignItems: 'center',
565
- justifyContent: 'center',
566
- padding: 20,
567
- },
568
- link: {
569
- marginTop: 15,
570
- paddingVertical: 15,
571
- },
572
- });
573
- ```
574
-
575
- The above example demonstrates how to create a fullscreen modal that integrates with navigation.
576
- It includes custom close animations for Android to enhance the user experience. See the videos below for platform-specific behavior:
461
+ ### Navigation Modals
577
462
 
578
- | ios | android |
579
- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- |
580
- | <video src={modaliOSVideo} width={300} height="auto" controls loop autoPlay /> | <video src={modalAndroidVideo} width={300} height="auto" controls loop autoPlay /> |
463
+ For React Navigation modal screens, use <StorybookLink to="components-navmodal">`NavModal`</StorybookLink>. It contains the extracted screen-based modal layout, background variants, scrollable content handling, and the Android `triggerCloseAnimation()` ref used during navigation dismissal.
581
464
 
582
465
  ## Integration Notes
583
466
 
@@ -1,42 +1,10 @@
1
- import { ReactNode } from 'react';
2
- import { ViewProps } from 'react-native';
3
1
  import { BottomSheetProps } from '../BottomSheet';
4
- import { ButtonWithoutChildrenProps } from '../Button/Button.props';
5
- import { UnstyledIconButtonProps } from '../UnstyledIconButton';
2
+ import { ModalCommonProps } from './Modal.shared.types';
6
3
 
7
- interface ModalPropsBase extends Omit<BottomSheetProps, 'children'> {
8
- loading?: boolean;
9
- image?: ReactNode;
10
- showCloseButton?: boolean;
11
- heading?: string;
12
- loadingHeading?: string;
13
- description?: string;
4
+ interface ModalProps extends Omit<BottomSheetProps, 'children'>, ModalCommonProps {
14
5
  fullscreen?: boolean;
15
- stickyFooter?: boolean;
16
- children?: ViewProps['children'];
17
- onPressPrimaryButton?: () => void;
18
- primaryButtonText?: string;
19
- onPressSecondaryButton?: () => void;
20
6
  closeOnPrimaryButtonPress?: boolean;
21
- secondaryButtonText?: string;
22
- onPressCloseButton?: () => void;
23
7
  closeOnSecondaryButtonPress?: boolean;
24
- primaryButtonProps?: Omit<ButtonWithoutChildrenProps, 'children'>;
25
- secondaryButtonProps?: Omit<ButtonWithoutChildrenProps, 'children'>;
26
- closeButtonProps?: Omit<UnstyledIconButtonProps, 'children'>;
27
8
  }
28
9
 
29
- type ModalProps =
30
- | (ModalPropsBase & {
31
- inNavModal?: false | undefined;
32
- scrollable?: never;
33
- background?: never;
34
- })
35
- | (ModalPropsBase & {
36
- inNavModal: true;
37
- fullscreen?: never;
38
- scrollable?: boolean;
39
- background?: 'default' | 'brand';
40
- });
41
-
42
10
  export default ModalProps;
@@ -0,0 +1,23 @@
1
+ import { ReactNode } from 'react';
2
+ import { ViewProps } from 'react-native';
3
+ import { ButtonWithoutChildrenProps } from '../Button/Button.props';
4
+ import { UnstyledIconButtonProps } from '../UnstyledIconButton';
5
+
6
+ export interface ModalCommonProps {
7
+ loading?: boolean;
8
+ image?: ReactNode;
9
+ showCloseButton?: boolean;
10
+ heading?: string;
11
+ loadingHeading?: string;
12
+ description?: string;
13
+ stickyFooter?: boolean;
14
+ children?: ViewProps['children'];
15
+ onPressPrimaryButton?: () => void;
16
+ primaryButtonText?: string;
17
+ onPressSecondaryButton?: () => void;
18
+ secondaryButtonText?: string;
19
+ onPressCloseButton?: () => void;
20
+ primaryButtonProps?: Omit<ButtonWithoutChildrenProps, 'children'>;
21
+ secondaryButtonProps?: Omit<ButtonWithoutChildrenProps, 'children'>;
22
+ closeButtonProps?: Omit<UnstyledIconButtonProps, 'children'>;
23
+ }
@@ -66,7 +66,6 @@ const meta = {
66
66
  onPressCloseButton: () => null,
67
67
  onPressPrimaryButton: () => null,
68
68
  onPressSecondaryButton: () => null,
69
- background: 'brand',
70
69
  },
71
70
  } satisfies Meta<typeof Modal>;
72
71
 
@@ -6,23 +6,13 @@ import {
6
6
  } from '@gorhom/bottom-sheet';
7
7
  import { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types';
8
8
  import { CloseMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
9
- import { useCallback, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
10
- import { AccessibilityInfo, Platform, ScrollView, View, findNodeHandle } from 'react-native';
11
- import Animated, {
12
- Easing,
13
- useAnimatedStyle,
14
- useSharedValue,
15
- withDelay,
16
- withTiming,
17
- } from 'react-native-reanimated';
9
+ import { useCallback, useImperativeHandle, useMemo, useRef } from 'react';
10
+ import { AccessibilityInfo, Platform, View, findNodeHandle } from 'react-native';
18
11
  import { StyleSheet } from 'react-native-unistyles';
19
- import { useTheme } from '../../hooks';
20
- import { hexWithOpacity } from '../../utils';
21
12
  import { BodyText } from '../BodyText';
22
13
  import { BottomSheetModal, BottomSheetScrollView } from '../BottomSheet';
23
14
  import { Button } from '../Button';
24
15
  import { Heading } from '../Heading';
25
- import { SafeAreaView } from '../SafeAreaView';
26
16
  import { Spinner } from '../Spinner';
27
17
  import { UnstyledIconButton } from '../UnstyledIconButton';
28
18
  import ModalProps from './Modal.props';
@@ -49,74 +39,15 @@ const Modal = ({
49
39
  primaryButtonProps,
50
40
  secondaryButtonProps,
51
41
  closeButtonProps,
52
- inNavModal = false,
53
42
  stickyFooter = true,
54
- background = 'default',
55
- scrollable = true,
56
43
  ...props
57
44
  }: ModalProps) => {
58
45
  const bottomSheetModalRef = useRef<BottomSheetModal>(null);
59
46
  const viewRef = useRef<View>(null);
60
47
  const scrollViewRef = useRef<BottomSheetScrollViewMethods>(null);
61
- const theme = useTheme();
62
- const backgroundOpacity = useSharedValue(0);
63
- const pretendContentTranslateY = useSharedValue(20);
64
- const isBrandBackground = background === 'brand';
65
-
66
- const triggerCloseAnimation = useCallback(() => {
67
- if (Platform.OS === 'android' && inNavModal) {
68
- pretendContentTranslateY.value = withTiming(20, {
69
- duration: 50,
70
- easing: Easing.in(Easing.quad),
71
- });
72
- backgroundOpacity.value = withTiming(0, {
73
- duration: 100,
74
- easing: Easing.in(Easing.quad),
75
- });
76
- }
77
- }, [inNavModal, pretendContentTranslateY, backgroundOpacity]);
78
48
 
79
49
  useImperativeHandle(ref, () => ({
80
50
  ...(bottomSheetModalRef.current as BottomSheetModal),
81
- triggerCloseAnimation,
82
- }));
83
-
84
- // Trigger animations on render for inNavModal Android modal
85
- useEffect(() => {
86
- if (Platform.OS === 'android' && inNavModal) {
87
- backgroundOpacity.value = withDelay(
88
- 300,
89
- withTiming(1, {
90
- duration: 200,
91
- easing: Easing.out(Easing.quad),
92
- })
93
- );
94
- pretendContentTranslateY.value = withDelay(
95
- 500,
96
- withTiming(0, {
97
- duration: 300,
98
- easing: Easing.out(Easing.quad),
99
- })
100
- );
101
- }
102
- }, [inNavModal, backgroundOpacity, pretendContentTranslateY]);
103
-
104
- const animatedBackgroundStyle = useAnimatedStyle(() => ({
105
- backgroundColor: hexWithOpacity(
106
- theme.components.overlay.backgroundColor,
107
- backgroundOpacity.value * (theme.components.overlay.opacity / 100)
108
- ),
109
- }));
110
-
111
- const animatedInNavModalStyle = useAnimatedStyle(() => ({
112
- backgroundColor: hexWithOpacity(
113
- theme.components.overlay.backgroundColor,
114
- backgroundOpacity.value * (theme.components.overlay.opacity / 100)
115
- ),
116
- }));
117
-
118
- const animatedPretendContentStyle = useAnimatedStyle(() => ({
119
- transform: [{ translateY: pretendContentTranslateY.value }],
120
51
  }));
121
52
 
122
53
  const handleChange = (index: number, position: number, type: SNAP_POINT_TYPE) => {
@@ -174,7 +105,6 @@ const Modal = ({
174
105
  noButtons,
175
106
  stickyFooter,
176
107
  showHandle: props.showHandle,
177
- background: isBrandBackground ? 'brand' : 'primary',
178
108
  });
179
109
 
180
110
  const footer = useMemo(
@@ -184,7 +114,6 @@ const Modal = ({
184
114
  <Button
185
115
  onPress={handlePrimaryButtonPress}
186
116
  text={primaryButtonText}
187
- inverted={isBrandBackground && inNavModal}
188
117
  {...primaryButtonProps}
189
118
  variant={(primaryButtonProps?.variant as 'solid') ?? 'solid'}
190
119
  colorScheme={(primaryButtonProps?.colorScheme as 'highlight') ?? 'highlight'}
@@ -194,7 +123,6 @@ const Modal = ({
194
123
  <Button
195
124
  onPress={handleSecondaryButtonPress}
196
125
  text={secondaryButtonText}
197
- inverted={isBrandBackground && inNavModal}
198
126
  {...secondaryButtonProps}
199
127
  variant={(secondaryButtonProps?.variant as 'outline') ?? 'outline'}
200
128
  colorScheme={(secondaryButtonProps?.colorScheme as 'functional') ?? 'functional'}
@@ -205,8 +133,6 @@ const Modal = ({
205
133
  [
206
134
  handlePrimaryButtonPress,
207
135
  handleSecondaryButtonPress,
208
- inNavModal,
209
- isBrandBackground,
210
136
  onPressPrimaryButton,
211
137
  onPressSecondaryButton,
212
138
  primaryButtonProps,
@@ -216,8 +142,6 @@ const Modal = ({
216
142
  ]
217
143
  );
218
144
 
219
- const InNavModalContainer = scrollable ? ScrollView : View;
220
-
221
145
  const content = (
222
146
  <>
223
147
  {loading ? (
@@ -228,11 +152,8 @@ const Modal = ({
228
152
  screenReaderFocusable
229
153
  ref={viewRef}
230
154
  >
231
- <Spinner
232
- size="lg"
233
- color={isBrandBackground && inNavModal ? theme.color.icon.inverted : undefined}
234
- />
235
- <Heading size="lg" textAlign="center" inverted={isBrandBackground && inNavModal}>
155
+ <Spinner size="lg" />
156
+ <Heading size="lg" textAlign="center">
236
157
  {loadingHeading}
237
158
  </Heading>
238
159
  </View>
@@ -247,22 +168,17 @@ const Modal = ({
247
168
  <View style={styles.header}>
248
169
  <View style={styles.headerTextContent}>
249
170
  {heading && !image ? (
250
- <Heading size="lg" accessible inverted={isBrandBackground && inNavModal}>
171
+ <Heading size="lg" accessible>
251
172
  {heading}
252
173
  </Heading>
253
174
  ) : null}
254
- {description && !image ? (
255
- <BodyText accessible inverted={isBrandBackground && inNavModal}>
256
- {description}
257
- </BodyText>
258
- ) : null}
175
+ {description && !image ? <BodyText accessible>{description}</BodyText> : null}
259
176
  </View>
260
177
  {showCloseButton ? (
261
178
  <UnstyledIconButton
262
179
  icon={CloseMediumIcon}
263
180
  onPress={handleCloseButtonPress}
264
181
  accessibilityLabel="Close modal"
265
- inverted={isBrandBackground && inNavModal}
266
182
  {...closeButtonProps}
267
183
  />
268
184
  ) : null}
@@ -272,45 +188,20 @@ const Modal = ({
272
188
  {image}
273
189
  <View style={styles.textContent}>
274
190
  {heading ? (
275
- <Heading
276
- size="lg"
277
- textAlign="center"
278
- accessible
279
- inverted={isBrandBackground && inNavModal}
280
- >
191
+ <Heading size="lg" textAlign="center" accessible>
281
192
  {heading}
282
193
  </Heading>
283
194
  ) : null}
284
195
  {description ? (
285
- <BodyText
286
- textAlign="center"
287
- accessible
288
- inverted={isBrandBackground && inNavModal}
289
- >
196
+ <BodyText textAlign="center" accessible>
290
197
  {description}
291
198
  </BodyText>
292
199
  ) : null}
293
200
  </View>
294
201
  </View>
295
202
  ) : null}
296
- {inNavModal && (
297
- <InNavModalContainer
298
- style={{
299
- flex: stickyFooter ? 1 : 0,
300
- ...(scrollable ? { marginHorizontal: -1 } : {}),
301
- }}
302
- {...(scrollable ? { contentContainerStyle: { paddingHorizontal: 1 } } : {})}
303
- >
304
- {children}
305
- {!stickyFooter ? (
306
- <View style={styles.inNavModalFooterContainer}>{footer}</View>
307
- ) : null}
308
- </InNavModalContainer>
309
- )}
310
- {!inNavModal && children}
311
- {((!stickyFooter && !inNavModal) || (inNavModal && stickyFooter)) && !noButtons
312
- ? footer
313
- : null}
203
+ {children}
204
+ {!stickyFooter && !noButtons ? footer : null}
314
205
  </View>
315
206
  )}
316
207
  </>
@@ -325,27 +216,7 @@ const Modal = ({
325
216
  [footer]
326
217
  );
327
218
 
328
- return inNavModal ? (
329
- <View
330
- style={{
331
- flex: 1,
332
- backgroundColor: theme.color.background[isBrandBackground ? 'brand' : 'primary'],
333
- }}
334
- >
335
- {Platform.OS === 'android' ? (
336
- <Animated.View style={[styles.androidContainer, animatedBackgroundStyle]}>
337
- <Animated.View style={[styles.pretendContent, animatedPretendContentStyle]} />
338
- </Animated.View>
339
- ) : null}
340
- <Animated.View
341
- style={[styles.inNavModalContainer, Platform.OS === 'android' && animatedInNavModalStyle]}
342
- >
343
- <SafeAreaView edges={['top', 'bottom']} style={styles.inNavModalContent}>
344
- {content}
345
- </SafeAreaView>
346
- </Animated.View>
347
- </View>
348
- ) : (
219
+ return (
349
220
  <BottomSheetModal
350
221
  ref={bottomSheetModalRef}
351
222
  enableDynamicSizing={true}
@@ -464,40 +335,6 @@ const styles = StyleSheet.create((theme, rt) => ({
464
335
  paddingHorizontal: theme.components.bottomSheet.padding,
465
336
  paddingBottom: theme.components.bottomSheet.padding + rt.insets.bottom,
466
337
  },
467
- inNavModalContainer: {
468
- flex: 1,
469
- ...(Platform.OS === 'ios' ? { backgroundColor: theme.components.overlay.backgroundColor } : {}),
470
- },
471
- inNavModalContent: {
472
- flex: 1,
473
- borderTopLeftRadius: theme.components.modal.borderRadius,
474
- borderTopRightRadius: theme.components.modal.borderRadius,
475
- backgroundColor: theme.color.surface.neutral.strong,
476
- padding: theme.components.bottomSheet.padding,
477
- variants: {
478
- background: {
479
- primary: {},
480
- brand: {
481
- backgroundColor: theme.color.background.brand,
482
- },
483
- },
484
- },
485
- },
486
- inNavModalFooterContainer: {
487
- paddingTop: theme.components.bottomSheet.padding,
488
- },
489
- androidContainer: {
490
- height: rt.insets.top + 18,
491
- paddingLeft: theme.components.bottomSheet.padding,
492
- paddingRight: theme.components.bottomSheet.padding,
493
- justifyContent: 'flex-end',
494
- },
495
- pretendContent: {
496
- borderTopLeftRadius: theme.components.modal.borderRadius,
497
- borderTopRightRadius: theme.components.modal.borderRadius,
498
- height: 12,
499
- backgroundColor: theme.components.parts.modalStack.backgroundColorCardTop,
500
- },
501
338
  }));
502
339
 
503
340
  export default Modal;