From c75f2f1cab152c90b066e65c463fc0babb4ecaea Mon Sep 17 00:00:00 2001 From: Axel Delafosse Date: Wed, 27 Apr 2022 13:09:42 +0200 Subject: [PATCH 1/9] use the new modal screen hoc --- packages/app/components/list/index.tsx | 131 +++++++++++++----- packages/app/components/list/listing-card.tsx | 115 --------------- .../app/components/list/listing-modal.tsx | 33 ----- packages/app/components/transfer.tsx | 13 +- packages/app/components/unlist/index.tsx | 131 +++++++++++++++--- .../app/components/unlist/unlisting-card.tsx | 123 ---------------- .../app/components/unlist/unlisting-modal.tsx | 33 ----- packages/app/hooks/use-modal.ts | 61 -------- packages/app/navigation/with-modal-screen.tsx | 25 ---- packages/app/screens/activities.tsx | 18 ++- packages/app/screens/comments.tsx | 3 +- packages/app/screens/create.tsx | 26 ++-- packages/app/screens/delete.tsx | 25 +--- packages/app/screens/details.tsx | 30 +--- packages/app/screens/list.tsx | 4 +- packages/app/screens/login.tsx | 36 ++--- packages/app/screens/transfer.tsx | 36 +---- packages/app/screens/unlist.tsx | 4 +- .../use-back-press-handler.android.tsx | 3 +- .../modal-screen/use-back-press-handler.tsx | 0 .../modal-screen/with-modal-screen.tsx | 5 +- .../modal-screen/with-modal-screen.web.tsx | 6 +- 22 files changed, 264 insertions(+), 597 deletions(-) delete mode 100644 packages/app/components/list/listing-card.tsx delete mode 100644 packages/app/components/list/listing-modal.tsx delete mode 100644 packages/app/components/unlist/unlisting-card.tsx delete mode 100644 packages/app/components/unlist/unlisting-modal.tsx delete mode 100644 packages/app/hooks/use-modal.ts delete mode 100644 packages/app/navigation/with-modal-screen.tsx rename packages/{app/navigation => design-system}/modal-screen/use-back-press-handler.android.tsx (83%) rename packages/{app/navigation => design-system}/modal-screen/use-back-press-handler.tsx (100%) rename packages/{app/navigation => design-system}/modal-screen/with-modal-screen.tsx (89%) rename packages/{app/navigation => design-system}/modal-screen/with-modal-screen.web.tsx (89%) diff --git a/packages/app/components/list/index.tsx b/packages/app/components/list/index.tsx index 893560cc05..2497ee83e3 100644 --- a/packages/app/components/list/index.tsx +++ b/packages/app/components/list/index.tsx @@ -1,47 +1,114 @@ -import { useEffect } from "react"; -import { Platform, ScrollView } from "react-native"; - -import { - BottomSheetModalProvider, - BottomSheetScrollView, -} from "@gorhom/bottom-sheet"; +import { formatDistanceToNowStrict } from "date-fns"; +import { PolygonScanButton } from "app/components/polygon-scan-button"; +import { useCurrentUserAddress } from "app/hooks/use-current-user-address"; +import { useListNFT } from "app/hooks/use-list-nft"; import { useUser } from "app/hooks/use-user"; -import { useRouter } from "app/navigation/use-router"; import type { NFT } from "app/types"; +import { findAddressInOwnerList } from "app/utilities"; + +import { Media, Spinner, Text, View } from "design-system"; +import { Owner } from "design-system/card"; +import { Collection } from "design-system/card/rows/collection"; +import { PolygonScan } from "design-system/icon"; +import { tw } from "design-system/tailwind"; -import { ListingCard } from "./listing-card"; -import { ListingModal } from "./listing-modal"; +import { ListingForm } from "./listing-form"; +import { ListingUnavailable } from "./listing-unavailable"; type Props = { nft?: NFT; }; -const ListingScrollView = - Platform.OS === "android" ? BottomSheetScrollView : ScrollView; - const List = ({ nft }: Props) => { - const router = useRouter(); - const { isAuthenticated } = useUser(); - - /** - * Redirect on log out - */ - useEffect(() => { - const isUnauthenticated = !isAuthenticated; - if (isUnauthenticated) { - router.pop(); - } - }, [isAuthenticated]); + const { user } = useUser(); + const { userAddress: address } = useCurrentUserAddress(); + const { listNFT, state } = useListNFT(); + + const hasMultipleOwners = nft?.multiple_owners_list + ? nft?.multiple_owners_list.length > 1 + : false; + + const isActiveAddressAnOwner = Boolean( + findAddressInOwnerList( + address, + user?.data.profile.wallet_addresses_v2, + nft?.multiple_owners_list + ) + ); + + if (state.status === "listingSuccess") { + return ( + + 🎉 + + + Your NFT has been listed on Showtime! + + + + + ); + } + + if (state.status === "transactionInitiated") { + return ( + + + + + Your NFT is being listed on Showtime. Feel free to navigate away + from this screen. + + + + + ); + } return ( - - - - - - - + + + + + + + + {nft?.token_name} + + + + {nft?.token_created ? ( + + {`Minted ${formatDistanceToNowStrict( + new Date(nft?.token_created), + { + addSuffix: true, + } + )}`} + + ) : null} + + + + + {isActiveAddressAnOwner ? ( + + ) : ( + + )} + + ); }; diff --git a/packages/app/components/list/listing-card.tsx b/packages/app/components/list/listing-card.tsx deleted file mode 100644 index 14016b1b43..0000000000 --- a/packages/app/components/list/listing-card.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { formatDistanceToNowStrict } from "date-fns"; - -import { PolygonScanButton } from "app/components/polygon-scan-button"; -import { useCurrentUserAddress } from "app/hooks/use-current-user-address"; -import { useListNFT } from "app/hooks/use-list-nft"; -import { useUser } from "app/hooks/use-user"; -import type { NFT } from "app/types"; -import { findAddressInOwnerList } from "app/utilities"; - -import { Media, Spinner, Text, View } from "design-system"; -import { Owner } from "design-system/card"; -import { Collection } from "design-system/card/rows/collection"; -import { PolygonScan } from "design-system/icon"; -import { tw } from "design-system/tailwind"; - -import { ListingForm } from "./listing-form"; -import { ListingUnavailable } from "./listing-unavailable"; - -type Props = { - nft?: NFT; -}; - -const ListingCard = ({ nft }: Props) => { - const { user } = useUser(); - const { userAddress: address } = useCurrentUserAddress(); - const { listNFT, state } = useListNFT(); - - const hasMultipleOwners = nft?.multiple_owners_list - ? nft?.multiple_owners_list.length > 1 - : false; - - const isActiveAddressAnOwner = Boolean( - findAddressInOwnerList( - address, - user?.data.profile.wallet_addresses_v2, - nft?.multiple_owners_list - ) - ); - - if (state.status === "listingSuccess") { - return ( - - 🎉 - - - Your NFT has been listed on Showtime! - - - - - ); - } - - if (state.status === "transactionInitiated") { - return ( - - - - - Your NFT is being listed on Showtime. Feel free to navigate away - from this screen. - - - - - ); - } - - return ( - - - - - - - - {nft?.token_name} - - - - {nft?.token_created ? ( - - {`Minted ${formatDistanceToNowStrict( - new Date(nft?.token_created), - { - addSuffix: true, - } - )}`} - - ) : null} - - - - - {isActiveAddressAnOwner ? ( - - ) : ( - - )} - - - ); -}; - -export { ListingCard }; diff --git a/packages/app/components/list/listing-modal.tsx b/packages/app/components/list/listing-modal.tsx deleted file mode 100644 index 70238a9893..0000000000 --- a/packages/app/components/list/listing-modal.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { ReactNode, useMemo } from "react"; -import { Platform } from "react-native"; - -import { useRouter } from "app/navigation/use-router"; - -import { View } from "design-system"; -import { Modal, ModalSheet } from "design-system"; - -type Props = { - children: ReactNode; -}; - -const NativeModal = Platform.OS === "android" ? ModalSheet : Modal; - -const ListingModal = (props: Props) => { - const children = props.children; - const snapPoints = useMemo(() => ["90%"], []); - const router = useRouter(); - return ( - - {children} - - ); -}; - -export { ListingModal }; diff --git a/packages/app/components/transfer.tsx b/packages/app/components/transfer.tsx index fc9abd8362..37baddeee9 100644 --- a/packages/app/components/transfer.tsx +++ b/packages/app/components/transfer.tsx @@ -174,12 +174,13 @@ function Transfer({ nft }: { nft?: NFT }) { width={14} /> - {`Minted ${formatDistanceToNowStrict( - new Date(nft?.token_created), - { - addSuffix: true, - } - )}`} + {nft?.token_created && + `Minted ${formatDistanceToNowStrict( + new Date(nft?.token_created), + { + addSuffix: true, + } + )}`} diff --git a/packages/app/components/unlist/index.tsx b/packages/app/components/unlist/index.tsx index 90630bd56c..8ded998a34 100644 --- a/packages/app/components/unlist/index.tsx +++ b/packages/app/components/unlist/index.tsx @@ -1,35 +1,122 @@ -import { Platform, ScrollView } from "react-native"; - -import { - BottomSheetModalProvider, - BottomSheetScrollView, -} from "@gorhom/bottom-sheet"; +import { formatDistanceToNowStrict } from "date-fns"; +import { PolygonScanButton } from "app/components/polygon-scan-button"; +import { useCurrentUserAddress } from "app/hooks/use-current-user-address"; +import { useUnlistNFT } from "app/hooks/use-unlist-nft"; +import { useUser } from "app/hooks/use-user"; import type { NFT } from "app/types"; +import { findAddressInOwnerList } from "app/utilities"; + +import { Media, Spinner, Text, View } from "design-system"; +import { Owner } from "design-system/card"; +import { Collection } from "design-system/card/rows/collection"; +import { PolygonScan } from "design-system/icon"; +import { tw } from "design-system/tailwind"; -import { UnlistingCard } from "./unlisting-card"; -import { UnlistingModal } from "./unlisting-modal"; +import { UnlistingSubmit } from "./unlisting-submit"; +import { UnlistingTitle } from "./unlisting-title"; +import { UnlistingUnavailable } from "./unlisting-unavailable"; type Props = { nft?: NFT; }; -const UnlistingScrollView = - Platform.OS === "android" ? BottomSheetScrollView : ScrollView; - const Unlist = ({ nft }: Props) => { + const { user } = useUser(); + const { userAddress: address } = useCurrentUserAddress(); + + const { state, unlistNFT } = useUnlistNFT(); + + const listingId = nft?.listing?.sale_identifier; + const hasMultipleOwners = nft?.multiple_owners_list + ? nft?.multiple_owners_list.length > 1 + : false; + + const isActiveAddressAnOwner = Boolean( + findAddressInOwnerList( + address, + user?.data.profile.wallet_addresses_v2, + nft?.multiple_owners_list + ) + ); + + if (state.status === "unlistingSuccess") { + return ( + + 🎉 + + + Your NFT has been listed from Showtime + + + + + ); + } + + if (state.status === "transactionInitiated") { + return ( + + + + + Your NFT is being unlisted on Showtime. Feel free to navigate away + from this screen. + + + + + ); + } + return ( - - - - - - - + + + + + + + + + {nft?.token_name} + + + + {nft?.token_created ? ( + + {`Minted ${formatDistanceToNowStrict( + new Date(nft?.token_created), + { + addSuffix: true, + } + )}`} + + ) : null} + + + + + {isActiveAddressAnOwner ? ( + + ) : ( + + )} + + ); }; diff --git a/packages/app/components/unlist/unlisting-card.tsx b/packages/app/components/unlist/unlisting-card.tsx deleted file mode 100644 index 32e325aba4..0000000000 --- a/packages/app/components/unlist/unlisting-card.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import { formatDistanceToNowStrict } from "date-fns"; - -import { PolygonScanButton } from "app/components/polygon-scan-button"; -import { useCurrentUserAddress } from "app/hooks/use-current-user-address"; -import { useUnlistNFT } from "app/hooks/use-unlist-nft"; -import { useUser } from "app/hooks/use-user"; -import type { NFT } from "app/types"; -import { findAddressInOwnerList } from "app/utilities"; - -import { Media, Spinner, Text, View } from "design-system"; -import { Owner } from "design-system/card"; -import { Collection } from "design-system/card/rows/collection"; -import { PolygonScan } from "design-system/icon"; -import { tw } from "design-system/tailwind"; - -import { UnlistingSubmit } from "./unlisting-submit"; -import { UnlistingTitle } from "./unlisting-title"; -import { UnlistingUnavailable } from "./unlisting-unavailable"; - -type Props = { - nft?: NFT; -}; - -const UnlistingCard = ({ nft }: Props) => { - const { user } = useUser(); - const { userAddress: address } = useCurrentUserAddress(); - - const { state, unlistNFT } = useUnlistNFT(); - - const listingId = nft?.listing?.sale_identifier; - const hasMultipleOwners = nft?.multiple_owners_list - ? nft?.multiple_owners_list.length > 1 - : false; - - const isActiveAddressAnOwner = Boolean( - findAddressInOwnerList( - address, - user?.data.profile.wallet_addresses_v2, - nft?.multiple_owners_list - ) - ); - - if (state.status === "unlistingSuccess") { - return ( - - 🎉 - - - Your NFT has been listed from Showtime - - - - - ); - } - - if (state.status === "transactionInitiated") { - return ( - - - - - Your NFT is being unlisted on Showtime. Feel free to navigate away - from this screen. - - - - - ); - } - - return ( - - - - - - - - - {nft?.token_name} - - - - {nft?.token_created ? ( - - {`Minted ${formatDistanceToNowStrict( - new Date(nft?.token_created), - { - addSuffix: true, - } - )}`} - - ) : null} - - - - - {isActiveAddressAnOwner ? ( - - ) : ( - - )} - - - ); -}; - -export { UnlistingCard }; diff --git a/packages/app/components/unlist/unlisting-modal.tsx b/packages/app/components/unlist/unlisting-modal.tsx deleted file mode 100644 index 3e9f1d7d40..0000000000 --- a/packages/app/components/unlist/unlisting-modal.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { ReactNode, useMemo } from "react"; -import { Platform } from "react-native"; - -import { useRouter } from "app/navigation/use-router"; - -import { View } from "design-system"; -import { Modal, ModalSheet } from "design-system"; - -type Props = { - children: ReactNode; -}; - -const NativeModal = Platform.OS === "android" ? ModalSheet : Modal; - -const UnlistingModal = (props: Props) => { - const children = props.children; - const snapPoints = useMemo(() => ["90%"], []); - const router = useRouter(); - return ( - - {children} - - ); -}; - -export { UnlistingModal }; diff --git a/packages/app/hooks/use-modal.ts b/packages/app/hooks/use-modal.ts deleted file mode 100644 index 3038118b3c..0000000000 --- a/packages/app/hooks/use-modal.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { useCallback, useRef } from "react"; -import { Platform } from "react-native"; - -import { useIsFocused } from "app/lib/react-navigation/native"; -import { useSafeAreaInsets } from "app/lib/safe-area"; -import { useRouter } from "app/navigation/use-router"; - -import { Modal, ModalSheet } from "design-system"; - -const snapPoints = ["90%"]; - -/** - * extracted these number from react-navigation - */ -// @ts-ignore -export const modalPresentationHeight = Platform.isPad - ? 6 - : Platform.OS === "ios" - ? 12 - : 0; - -// TODO: remove this and replace with modalScreen HOC -export const useModal = () => { - const wasClosedByUserAction = useRef(undefined); - const isModalFocused = useIsFocused(); - const router = useRouter(); - const { top: topSafeArea } = useSafeAreaInsets(); - - const handleClose = useCallback(() => { - wasClosedByUserAction.current = true; - router.pop(); - }, [router]); - - const handleOnClose = useCallback(() => { - if (!isModalFocused) { - return; - } - - if (!wasClosedByUserAction.current) { - wasClosedByUserAction.current = true; - router.pop(); - } - }, [router, isModalFocused]); - - const ModalComponent = Platform.OS === "android" ? ModalSheet : Modal; - - return [ - ModalComponent, - { - snapPoints, - height: "h-[90vh]", - close: handleClose, - onClose: handleOnClose, - keyboardVerticalOffset: topSafeArea + modalPresentationHeight, - bodyTW: "bg-white dark:bg-black", - bodyContentTW: "p-0", - scrollable: false, - visible: isModalFocused, - }, - ]; -}; diff --git a/packages/app/navigation/with-modal-screen.tsx b/packages/app/navigation/with-modal-screen.tsx deleted file mode 100644 index 74a8da1e9b..0000000000 --- a/packages/app/navigation/with-modal-screen.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { FC } from "react"; -import { Platform } from "react-native"; - -import { useRouter } from "./use-router"; - -function withModalScreen

( - Screen: FC

, - matchingPathname: string, - matchingQueryParam: string -) { - return function (props: P) { - const { pathname, query } = useRouter(); - - const shouldShowModal = - pathname === matchingPathname || Boolean(query[matchingQueryParam]); - - if (Platform.OS === "web" && !shouldShowModal) { - return null; - } - - return ; - }; -} - -export { withModalScreen }; diff --git a/packages/app/screens/activities.tsx b/packages/app/screens/activities.tsx index 72fed8a97e..5464041b5a 100644 --- a/packages/app/screens/activities.tsx +++ b/packages/app/screens/activities.tsx @@ -2,10 +2,10 @@ import { Suspense } from "react"; import { ErrorBoundary } from "app/components/error-boundary"; import { Activities } from "app/components/nft-activity"; -import { useModal } from "app/hooks/use-modal"; import { useNFTDetailByTokenId } from "app/hooks/use-nft-detail-by-token-id"; import { createParam } from "app/navigation/use-param"; -import { withModalScreen } from "app/navigation/with-modal-screen"; + +import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; type Query = { tokenId: string; @@ -16,7 +16,6 @@ type Query = { const { useParam } = createParam(); export function ActivitiesModal() { - const [ModalComponent, modalProps] = useModal(); const [tokenId] = useParam("tokenId"); const [contractAddress] = useParam("contractAddress"); const [chainName] = useParam("chainName"); @@ -27,18 +26,17 @@ export function ActivitiesModal() { }); return ( - - - null}> - - - - + + null}> + + + ); } export const ActivitiesScreen = withModalScreen( ActivitiesModal, + "Activities", "/nft/[chainName]/[contractAddress]/[tokenId]/activities", "activitiesModal" ); diff --git a/packages/app/screens/comments.tsx b/packages/app/screens/comments.tsx index 5baf906b7b..01ddeb1280 100644 --- a/packages/app/screens/comments.tsx +++ b/packages/app/screens/comments.tsx @@ -4,9 +4,10 @@ import { Comments } from "app/components/comments"; import { CommentsStatus } from "app/components/comments/comments-status"; import { ErrorBoundary } from "app/components/error-boundary"; import { useNFTDetailByTokenId } from "app/hooks/use-nft-detail-by-token-id"; -import { withModalScreen } from "app/navigation/modal-screen/with-modal-screen"; import { createParam } from "app/navigation/use-param"; +import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; + type Query = { tokenId: string; contractAddress: string; diff --git a/packages/app/screens/create.tsx b/packages/app/screens/create.tsx index 6b57b8baed..0f36904824 100644 --- a/packages/app/screens/create.tsx +++ b/packages/app/screens/create.tsx @@ -8,11 +8,11 @@ import { useNavigation } from "app/lib/react-navigation/native"; import { useHideHeader } from "app/navigation/use-navigation-elements"; import { createParam } from "app/navigation/use-param"; import { useRouter } from "app/navigation/use-router"; -import { withModalScreen } from "app/navigation/with-modal-screen"; import { Button, Modal, ModalSheet, Spinner, Text, View } from "design-system"; import { useAlert } from "design-system/alert"; import { Hidden } from "design-system/hidden"; +import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; type Query = { form: string; @@ -86,24 +86,13 @@ const CreateModal = () => { return ( <> - - <> - - - + + + - - - - - + + + ); }; @@ -146,6 +135,7 @@ const CreateMD = () => { export const CreateScreen = withModalScreen( CreateModal, + "Create", "/create", "createModal" ); diff --git a/packages/app/screens/delete.tsx b/packages/app/screens/delete.tsx index 829ac01834..03651e6143 100644 --- a/packages/app/screens/delete.tsx +++ b/packages/app/screens/delete.tsx @@ -1,14 +1,9 @@ -import { useMemo } from "react"; -import { Platform } from "react-native"; - import { Delete } from "app/components/delete"; import { useNFTDetailByTokenId } from "app/hooks/use-nft-detail-by-token-id"; import { useHideHeader } from "app/navigation/use-navigation-elements"; import { createParam } from "app/navigation/use-param"; -import { useRouter } from "app/navigation/use-router"; -import { withModalScreen } from "app/navigation/with-modal-screen"; -import { Modal, ModalSheet } from "design-system"; +import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; type Query = { tokenId: string; @@ -20,7 +15,6 @@ const { useParam } = createParam(); const DeleteModal = () => { useHideHeader(); - const router = useRouter(); const [tokenId] = useParam("tokenId"); const [contractAddress] = useParam("contractAddress"); const [chainName] = useParam("chainName"); @@ -30,25 +24,12 @@ const DeleteModal = () => { contractAddress: contractAddress as string, }); - const snapPoints = useMemo(() => ["90%"], []); - - const ModalComponent = Platform.OS === "android" ? ModalSheet : Modal; - - return ( - - - - ); + return ; }; export const DeleteScreen = withModalScreen( DeleteModal, + "Delete", "/nft/[chainName]/[contractAddress]/[tokenId]/delete", "deleteModal" ); diff --git a/packages/app/screens/details.tsx b/packages/app/screens/details.tsx index c64172ab5a..6190db7987 100644 --- a/packages/app/screens/details.tsx +++ b/packages/app/screens/details.tsx @@ -1,14 +1,9 @@ -import { useMemo } from "react"; -import { Platform } from "react-native"; - import { Details } from "app/components/details"; import { useNFTDetailByTokenId } from "app/hooks/use-nft-detail-by-token-id"; import { useHideHeader } from "app/navigation/use-navigation-elements"; import { createParam } from "app/navigation/use-param"; -import { useRouter } from "app/navigation/use-router"; -import { withModalScreen } from "app/navigation/with-modal-screen"; -import { Modal, ModalSheet } from "design-system"; +import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; type Query = { tokenId: string; @@ -20,9 +15,6 @@ const { useParam } = createParam(); const DetailsModal = () => { useHideHeader(); - - //#region hooks - const router = useRouter(); const [tokenId] = useParam("tokenId"); const [contractAddress] = useParam("contractAddress"); const [chainName] = useParam("chainName"); @@ -31,29 +23,13 @@ const DetailsModal = () => { tokenId: tokenId as string, contractAddress: contractAddress as string, }); - //#endregion - - //#region variables - const snapPoints = useMemo(() => ["90%"], []); - const ModalComponent = Platform.OS === "android" ? ModalSheet : Modal; - //#endregion - return ( - -

- - ); + return
; }; export const DetailsScreen = withModalScreen( DetailsModal, + "Details", "/nft/[chainName]/[contractAddress]/[tokenId]/details", "detailsModal" ); diff --git a/packages/app/screens/list.tsx b/packages/app/screens/list.tsx index 4e66960cd6..d2520e7189 100644 --- a/packages/app/screens/list.tsx +++ b/packages/app/screens/list.tsx @@ -3,7 +3,8 @@ import { withColorScheme } from "app/components/memo-with-theme"; import { useNFTDetailByTokenId } from "app/hooks/use-nft-detail-by-token-id"; import { useHideHeader } from "app/navigation/use-navigation-elements"; import { createParam } from "app/navigation/use-param"; -import { withModalScreen } from "app/navigation/with-modal-screen"; + +import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; type Query = { tokenId: string; @@ -29,6 +30,7 @@ const ListModal = withColorScheme(() => { export const ListScreen = withModalScreen( ListModal, + "List", "/nft/[chainName]/[contractAddress]/[tokenId]/list", "listModal" ); diff --git a/packages/app/screens/login.tsx b/packages/app/screens/login.tsx index 18f5f688ac..705995feb3 100644 --- a/packages/app/screens/login.tsx +++ b/packages/app/screens/login.tsx @@ -1,23 +1,10 @@ import { useCallback } from "react"; -import { Platform } from "react-native"; import { Login } from "app/components/login"; -import { useSafeAreaInsets } from "app/lib/safe-area"; import { createParam } from "app/navigation/use-param"; import { useRouter } from "app/navigation/use-router"; -import { withModalScreen } from "app/navigation/with-modal-screen"; -import { Modal } from "design-system"; - -/** - * extracted these number from react-navigation - */ -// @ts-ignore -const modalPresentationHeight = Platform.isPad - ? 6 - : Platform.OS === "ios" - ? 12 - : 0; +import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; type Query = { redirect_url: string; @@ -29,7 +16,6 @@ function LoginModal() { //#region hooks const [redirect_url] = useParam("redirect_url"); const router = useRouter(); - const { top: topSafeArea } = useSafeAreaInsets(); //#endregion //#region callbacks @@ -46,17 +32,13 @@ function LoginModal() { }, [redirect_url, router]); //#endregion - return ( - router.push("/") : router.pop} - height="" - keyboardVerticalOffset={topSafeArea + modalPresentationHeight} - bodyTW="bg-white dark:bg-black" - > - - - ); + // TODO: close={router.asPath === "/login" ? () => router.push("/") : router.pop} + return ; } -export const LoginScreen = withModalScreen(LoginModal, "/login", "loginModal"); +export const LoginScreen = withModalScreen( + LoginModal, + "Sign In", + "/login", + "loginModal" +); diff --git a/packages/app/screens/transfer.tsx b/packages/app/screens/transfer.tsx index f82f2d9b6d..a7db2492a2 100644 --- a/packages/app/screens/transfer.tsx +++ b/packages/app/screens/transfer.tsx @@ -1,14 +1,9 @@ -import { useMemo } from "react"; -import { KeyboardAvoidingView, Platform } from "react-native"; - import { Transfer } from "app/components/transfer"; import { useNFTDetailByTokenId } from "app/hooks/use-nft-detail-by-token-id"; import { useHideHeader } from "app/navigation/use-navigation-elements"; import { createParam } from "app/navigation/use-param"; -import { useRouter } from "app/navigation/use-router"; -import { withModalScreen } from "app/navigation/with-modal-screen"; -import { Modal, ModalSheet } from "design-system"; +import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; type Query = { tokenId: string; @@ -20,9 +15,6 @@ const { useParam } = createParam(); const TransferModal = () => { useHideHeader(); - - //#region hooks - const router = useRouter(); const [tokenId] = useParam("tokenId"); const [contractAddress] = useParam("contractAddress"); const [chainName] = useParam("chainName"); @@ -31,35 +23,13 @@ const TransferModal = () => { tokenId: tokenId as string, contractAddress: contractAddress as string, }); - //#endregion - - //#region variables - const snapPoints = useMemo(() => ["90%"], []); - const ModalComponent = Platform.OS === "android" ? ModalSheet : Modal; - //#endregion - return ( - - - - - - ); + return ; }; export const TransferScreen = withModalScreen( TransferModal, + "Transfer", "/nft/[chainName]/[contractAddress]/[tokenId]/transfer", "transferModal" ); diff --git a/packages/app/screens/unlist.tsx b/packages/app/screens/unlist.tsx index 73182b05ed..059249b22c 100644 --- a/packages/app/screens/unlist.tsx +++ b/packages/app/screens/unlist.tsx @@ -3,7 +3,8 @@ import { Unlist } from "app/components/unlist"; import { useNFTDetailByTokenId } from "app/hooks/use-nft-detail-by-token-id"; import { useHideHeader } from "app/navigation/use-navigation-elements"; import { createParam } from "app/navigation/use-param"; -import { withModalScreen } from "app/navigation/with-modal-screen"; + +import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; type Query = { tokenId: string; @@ -29,6 +30,7 @@ const UnlistModal = withColorScheme(() => { export const UnlistScreen = withModalScreen( UnlistModal, + "Unlist", "/nft/[chainName]/[contractAddress]/[tokenId]/unlist", "unlistModal" ); diff --git a/packages/app/navigation/modal-screen/use-back-press-handler.android.tsx b/packages/design-system/modal-screen/use-back-press-handler.android.tsx similarity index 83% rename from packages/app/navigation/modal-screen/use-back-press-handler.android.tsx rename to packages/design-system/modal-screen/use-back-press-handler.android.tsx index 52a93e65b6..1e22bf6ae1 100644 --- a/packages/app/navigation/modal-screen/use-back-press-handler.android.tsx +++ b/packages/design-system/modal-screen/use-back-press-handler.android.tsx @@ -1,5 +1,5 @@ import { RefObject, useCallback } from "react"; -import { BackHandler, Platform } from "react-native"; +import { BackHandler } from "react-native"; import { useFocusEffect } from "@react-navigation/native"; @@ -10,7 +10,6 @@ export const useBackPressHandler = (ref: RefObject) => { useCallback(() => { const onBackPress = () => { ref.current?.close(); - console.log("withModalScreen", "onBackPress"); return true; }; diff --git a/packages/app/navigation/modal-screen/use-back-press-handler.tsx b/packages/design-system/modal-screen/use-back-press-handler.tsx similarity index 100% rename from packages/app/navigation/modal-screen/use-back-press-handler.tsx rename to packages/design-system/modal-screen/use-back-press-handler.tsx diff --git a/packages/app/navigation/modal-screen/with-modal-screen.tsx b/packages/design-system/modal-screen/with-modal-screen.tsx similarity index 89% rename from packages/app/navigation/modal-screen/with-modal-screen.tsx rename to packages/design-system/modal-screen/with-modal-screen.tsx index 85c83d223d..fc5e6d8f6a 100644 --- a/packages/app/navigation/modal-screen/with-modal-screen.tsx +++ b/packages/design-system/modal-screen/with-modal-screen.tsx @@ -1,9 +1,10 @@ -import React, { FC, useCallback, useRef } from "react"; +import { FC, useCallback, useRef } from "react"; + +import { useRouter } from "app/navigation/use-router"; import { ModalMethods } from "design-system/modal-new"; import { ModalScreen } from "design-system/modal-new/modal.screen"; -import { useRouter } from "../use-router"; import { useBackPressHandler } from "./use-back-press-handler"; const snapPoints = ["90%", "100%"]; diff --git a/packages/app/navigation/modal-screen/with-modal-screen.web.tsx b/packages/design-system/modal-screen/with-modal-screen.web.tsx similarity index 89% rename from packages/app/navigation/modal-screen/with-modal-screen.web.tsx rename to packages/design-system/modal-screen/with-modal-screen.web.tsx index b20ee2757b..dbf02faabd 100644 --- a/packages/app/navigation/modal-screen/with-modal-screen.web.tsx +++ b/packages/design-system/modal-screen/with-modal-screen.web.tsx @@ -1,10 +1,10 @@ -import React, { FC, useCallback, useRef } from "react"; +import { FC, useCallback, useRef } from "react"; + +import { useRouter } from "app/navigation/use-router"; import { ModalMethods } from "design-system/modal-new"; import { ModalScreen } from "design-system/modal-new/modal.screen"; -import { useRouter } from "../use-router"; - function withModalScreen

( Screen: FC

, title: string, From e7133153cd7d2790d2b1c9153e3b87146b21f301 Mon Sep 17 00:00:00 2001 From: Axel Delafosse Date: Wed, 27 Apr 2022 13:18:40 +0200 Subject: [PATCH 2/9] clean modal implementations --- .../.storybook/storybook.requires.js | 4 +- packages/app/components/comments/index.tsx | 2 +- .../navigation/with-modal-sheet-screen.tsx | 36 ----- packages/design-system/index.tsx | 58 +++----- packages/design-system/modal-new/constants.ts | 2 - packages/design-system/modal-new/index.tsx | 65 -------- .../design-system/modal-new/modal.stories.tsx | 95 ------------ packages/design-system/modal-new/types.ts | 102 ------------- .../use-back-press-handler.android.tsx | 2 +- .../modal-screen/use-back-press-handler.tsx | 2 +- .../modal-screen/with-modal-screen.tsx | 4 +- .../modal-screen/with-modal-screen.web.tsx | 4 +- packages/design-system/modal-sheet/index.tsx | 57 ------- .../modal-sheet/modal-sheet.stories.tsx | 37 ----- packages/design-system/modal/backdrop.tsx | 15 -- packages/design-system/modal/body.tsx | 36 ----- packages/design-system/modal/body.web.tsx | 23 --- packages/design-system/modal/constants.ts | 42 +----- packages/design-system/modal/container.tsx | 35 ----- packages/design-system/modal/footer.tsx | 0 packages/design-system/modal/header.tsx | 47 ------ packages/design-system/modal/index.tsx | 139 ++++++++---------- .../{modal-new => modal}/modal.backdrop.tsx | 0 .../modal.backdrop.web.tsx | 0 .../{modal-new => modal}/modal.container.tsx | 0 .../modal.container.web.tsx | 0 .../{modal-new => modal}/modal.footer.tsx | 0 .../{modal-new => modal}/modal.footer.web.tsx | 0 .../{modal-new => modal}/modal.header-bar.tsx | 0 .../{modal-new => modal}/modal.header.tsx | 0 .../{modal-new => modal}/modal.screen.ios.tsx | 0 .../{modal-new => modal}/modal.screen.tsx | 0 .../design-system/modal/modal.stories.tsx | 118 +++++++-------- packages/design-system/modal/types.ts | 115 +++++++++------ .../useKeyboardOffset.android.ts | 0 .../{modal-new => modal}/useKeyboardOffset.ts | 0 36 files changed, 217 insertions(+), 823 deletions(-) delete mode 100644 packages/app/navigation/with-modal-sheet-screen.tsx delete mode 100644 packages/design-system/modal-new/constants.ts delete mode 100644 packages/design-system/modal-new/index.tsx delete mode 100644 packages/design-system/modal-new/modal.stories.tsx delete mode 100644 packages/design-system/modal-new/types.ts delete mode 100644 packages/design-system/modal-sheet/index.tsx delete mode 100644 packages/design-system/modal-sheet/modal-sheet.stories.tsx delete mode 100644 packages/design-system/modal/backdrop.tsx delete mode 100644 packages/design-system/modal/body.tsx delete mode 100644 packages/design-system/modal/body.web.tsx delete mode 100644 packages/design-system/modal/container.tsx delete mode 100644 packages/design-system/modal/footer.tsx delete mode 100644 packages/design-system/modal/header.tsx rename packages/design-system/{modal-new => modal}/modal.backdrop.tsx (100%) rename packages/design-system/{modal-new => modal}/modal.backdrop.web.tsx (100%) rename packages/design-system/{modal-new => modal}/modal.container.tsx (100%) rename packages/design-system/{modal-new => modal}/modal.container.web.tsx (100%) rename packages/design-system/{modal-new => modal}/modal.footer.tsx (100%) rename packages/design-system/{modal-new => modal}/modal.footer.web.tsx (100%) rename packages/design-system/{modal-new => modal}/modal.header-bar.tsx (100%) rename packages/design-system/{modal-new => modal}/modal.header.tsx (100%) rename packages/design-system/{modal-new => modal}/modal.screen.ios.tsx (100%) rename packages/design-system/{modal-new => modal}/modal.screen.tsx (100%) rename packages/design-system/{modal-new => modal}/useKeyboardOffset.android.ts (100%) rename packages/design-system/{modal-new => modal}/useKeyboardOffset.ts (100%) diff --git a/apps/storybook-react-native/.storybook/storybook.requires.js b/apps/storybook-react-native/.storybook/storybook.requires.js index 43488a0f67..55656bf980 100644 --- a/apps/storybook-react-native/.storybook/storybook.requires.js +++ b/apps/storybook-react-native/.storybook/storybook.requires.js @@ -1,9 +1,8 @@ /* do not change this file, it is auto generated by storybook. */ import { - configure, addDecorator, addParameters, - addArgsEnhancer, + configure, } from "@storybook/react-native"; import { decorators, parameters } from "./preview"; @@ -41,7 +40,6 @@ const getStories = () => { require("../../../packages/design-system/alert/alert.stories.tsx"), require("../../../packages/design-system/toast/toast.stories.tsx"), require("../../../packages/design-system/verification-badge/badge.stories.tsx"), - require("../../../packages/design-system/modal-new/modal.stories"), require("../../../packages/design-system/snackbar/snackbar.stories.tsx"), ]; }; diff --git a/packages/app/components/comments/index.tsx b/packages/app/components/comments/index.tsx index 48752a8ab5..c1be0f3181 100644 --- a/packages/app/components/comments/index.tsx +++ b/packages/app/components/comments/index.tsx @@ -15,7 +15,7 @@ import { useUser } from "app/hooks/use-user"; import type { NFT } from "app/types"; import { useAlert } from "design-system/alert"; -import { ModalFooter } from "design-system/modal-new"; +import { ModalFooter } from "design-system/modal"; import { CommentInputBox, CommentInputBoxMethods } from "./comment-input-box"; import { CommentsContainer } from "./comments-container"; diff --git a/packages/app/navigation/with-modal-sheet-screen.tsx b/packages/app/navigation/with-modal-sheet-screen.tsx deleted file mode 100644 index 780060ef11..0000000000 --- a/packages/app/navigation/with-modal-sheet-screen.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { FC, useCallback, useState } from "react"; - -import { BottomSheetModalProvider } from "@gorhom/bottom-sheet"; - -import { ModalSheet } from "design-system/modal-sheet"; - -import { useRouter } from "./use-router"; - -function withModalSheetScreen

(Screen: FC

, title?: string) { - return function (props: P) { - const [visible, setVisible] = useState(true); - - const { pop } = useRouter(); - - const close = useCallback(() => setVisible(false), []); - const onClose = useCallback(() => { - pop(); - }, [pop]); - - // TODO: extract title from navigation descriptor - return ( - - - - - - ); - }; -} - -export { withModalSheetScreen }; diff --git a/packages/design-system/index.tsx b/packages/design-system/index.tsx index b5fdd9ec90..cd04f1d856 100644 --- a/packages/design-system/index.tsx +++ b/packages/design-system/index.tsx @@ -1,47 +1,23 @@ -export { View } from "design-system/view"; - -export { ScrollView } from "design-system/scroll-view"; - -export { Text } from "design-system/text"; - -export { TextInput } from "design-system/text-input"; - -export { Gradient } from "design-system/gradient"; - -export { Pressable } from "design-system/pressable-scale"; - -export { Button, ButtonLabel } from "design-system/button"; - -export { Image } from "design-system/image"; - -export { Modal } from "design-system/modal"; - -export { ModalSheet } from "design-system/modal-sheet"; - +export { Accordion } from "design-system/accordion"; export { ActivityIndicator } from "design-system/activity-indicator"; - -export { Skeleton } from "design-system/skeleton"; - +export { Button, ButtonLabel } from "design-system/button"; export { Checkbox } from "design-system/checkbox"; - -export { Tabs, TabItem, SelectedTabIndicator } from "design-system/tabs"; - -export { Spinner } from "design-system/spinner"; - +export { CountryCodePicker } from "design-system/country-code-picker"; export { CreatorPreview } from "design-system/creator-preview"; - -export { SegmentedControl } from "design-system/segmented-control"; - -export { Select } from "design-system/select"; - -export { Media } from "design-system/media"; - export { Fieldset } from "design-system/fieldset"; - -export { Accordion } from "design-system/accordion"; - -export { CountryCodePicker } from "design-system/country-code-picker"; - +export { Gradient } from "design-system/gradient"; +export { Image } from "design-system/image"; export { LikeButton } from "design-system/like-button"; - +export { Media } from "design-system/media"; +export { Modal } from "design-system/modal"; +export { Pressable } from "design-system/pressable-scale"; +export { ScrollView } from "design-system/scroll-view"; +export { SegmentedControl } from "design-system/segmented-control"; +export { Select } from "design-system/select"; +export { Skeleton } from "design-system/skeleton"; +export { Spinner } from "design-system/spinner"; +export { SelectedTabIndicator, TabItem, Tabs } from "design-system/tabs"; +export { Text } from "design-system/text"; +export { TextInput } from "design-system/text-input"; export { VerificationBadge } from "design-system/verification-badge"; +export { View } from "design-system/view"; diff --git a/packages/design-system/modal-new/constants.ts b/packages/design-system/modal-new/constants.ts deleted file mode 100644 index e4b4daa045..0000000000 --- a/packages/design-system/modal-new/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const MOBILE_SNAP_POINTS = ["50%"]; -export const WEB_HEIGHT = "max-h-280px"; diff --git a/packages/design-system/modal-new/index.tsx b/packages/design-system/modal-new/index.tsx deleted file mode 100644 index a3f788e8ff..0000000000 --- a/packages/design-system/modal-new/index.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { forwardRef, memo, useCallback, useRef } from "react"; - -import { MOBILE_SNAP_POINTS, WEB_HEIGHT } from "./constants"; -import { ModalContainer as BaseModalContainer } from "./modal.container"; -import type { ModalProps, ModalMethods } from "./types"; - -export { ModalMethods }; - -const ModalComponent = forwardRef( - function ModalComponent( - { - title, - isScreen = false, - web_height = WEB_HEIGHT, - mobile_snapPoints = MOBILE_SNAP_POINTS, - modalContainer: ModalContainer = BaseModalContainer, - children, - onClose, - }, - ref - ) { - const didFireClose = useRef(false); - - //#region methods - const handleOnClose = useCallback(() => { - if (didFireClose.current) { - return; - } - didFireClose.current = true; - onClose?.(); - }, [onClose]); - - const handleClose = useCallback(() => { - if (!isScreen) { - handleOnClose(); - //@ts-ignore - } else if (isScreen && ref && ref.current) { - //@ts-ignore - ref.current.close(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isScreen, handleOnClose]); - //#endregion - - //#region render - return ( - - {children} - - ); - //#endregion - } -); - -export const Modal = memo(ModalComponent); - -export { ModalFooter } from "./modal.footer"; diff --git a/packages/design-system/modal-new/modal.stories.tsx b/packages/design-system/modal-new/modal.stories.tsx deleted file mode 100644 index 6d54ab8414..0000000000 --- a/packages/design-system/modal-new/modal.stories.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { useState } from "react"; - -import { BottomSheetScrollView } from "@gorhom/bottom-sheet"; -import { Meta } from "@storybook/react"; - -import { Button } from "design-system/button"; -import { Close } from "design-system/icon"; -import { Text } from "design-system/text"; - -import { View } from "../view"; -import { Modal } from "./index"; -import { ModalHeader } from "./modal.header"; - -export default { - component: ModalHeader, - title: "Components/NewModal", -} as Meta; - -const Container = (props: any) => { - return {props.children}; -}; - -export const HeaderDefault: React.VFC<{}> = () => { - return ( - - - - ); -}; - -export const HeaderWithEndContent: React.VFC<{}> = () => { - return ( - - ( - - )} - /> - - ); -}; - -export const Default: React.VFC<{}> = () => { - const [visible, setVisible] = useState(false); - - const onClose = () => { - setVisible(false); - }; - return ( - - - {visible && ( - - - - )} - - ); -}; - -export const WithScrollable: React.VFC<{}> = () => { - const [visible, setVisible] = useState(false); - - const onClose = () => { - console.log("onClose"); - setVisible(false); - }; - return ( - - - {visible && ( - - - {Array(50) - .fill(0) - .map((_, index) => ( - {`#${index} item`} - ))} - - - )} - - ); -}; diff --git a/packages/design-system/modal-new/types.ts b/packages/design-system/modal-new/types.ts deleted file mode 100644 index 0a3f764972..0000000000 --- a/packages/design-system/modal-new/types.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type { FC, ReactNode } from "react"; - -import type { - BottomSheetProps, - BottomSheetFooterProps, -} from "@gorhom/bottom-sheet"; - -import type { TW } from "../tailwind/types"; - -export interface ModalMethods { - close: () => void; -} - -export interface ModalProps { - /** - * Defines the modal title. - * @default "" - */ - title?: string; - /** - * Defines if the modal is presenting as - * a screen. - * @default false - */ - isScreen?: boolean; - /** - * **MOBILE ONLY**: Defines the points for the bottom sheet - * to snap to. It accepts array of number, string or mix. - * @default ["50%"] - */ - mobile_snapPoints?: BottomSheetProps["snapPoints"]; - - /** - * **WEB ONLY**: Defines the modal container height. - * It could be static value or responsive. - * @default "max-h-280px" - */ - web_height?: string; - - /** - * Defines the modal container - * tailwind style. - * @default undefined - */ - tw?: string; - - //#region components - modalContainer?: FC; - /** - * Defines the modal content. - * @default undefined - */ - children?: ReactNode; - //#endregion - - //#region callbacks - /** - * Defines the action to close - * the modal view/screen. - * @default undefined - */ - onClose?: () => void; - //#endregion -} - -export interface ModalHeaderProps - extends Pick { - /** - * Defines the component to be placed - * at the end of the header. - * @default undefined - */ - endContentComponent?: FC; - /** - * Defines the header tailwind style. - * @default undefined - */ - tw?: TW; -} - -export interface ModalContainerProps - extends Pick< - ModalProps, - | "title" - | "isScreen" - | "onClose" - | "children" - | "mobile_snapPoints" - | "web_height" - > { - close: () => void; -} - -export interface ModalScreenProps extends ModalProps { - close: () => void; -} - -export interface ModalFooterProps { - children: JSX.Element; -} - -export interface ModalBackdropProps extends Pick {} diff --git a/packages/design-system/modal-screen/use-back-press-handler.android.tsx b/packages/design-system/modal-screen/use-back-press-handler.android.tsx index 1e22bf6ae1..32ec602638 100644 --- a/packages/design-system/modal-screen/use-back-press-handler.android.tsx +++ b/packages/design-system/modal-screen/use-back-press-handler.android.tsx @@ -3,7 +3,7 @@ import { BackHandler } from "react-native"; import { useFocusEffect } from "@react-navigation/native"; -import type { ModalMethods } from "design-system/modal-new"; +import type { ModalMethods } from "design-system/modal"; export const useBackPressHandler = (ref: RefObject) => { return useFocusEffect( diff --git a/packages/design-system/modal-screen/use-back-press-handler.tsx b/packages/design-system/modal-screen/use-back-press-handler.tsx index dd2901ea3c..ffce1cebdb 100644 --- a/packages/design-system/modal-screen/use-back-press-handler.tsx +++ b/packages/design-system/modal-screen/use-back-press-handler.tsx @@ -1,5 +1,5 @@ import { RefObject } from "react"; -import type { ModalMethods } from "design-system/modal-new"; +import type { ModalMethods } from "design-system/modal"; export const useBackPressHandler = (ref: RefObject) => {}; diff --git a/packages/design-system/modal-screen/with-modal-screen.tsx b/packages/design-system/modal-screen/with-modal-screen.tsx index fc5e6d8f6a..0a03e6a3c4 100644 --- a/packages/design-system/modal-screen/with-modal-screen.tsx +++ b/packages/design-system/modal-screen/with-modal-screen.tsx @@ -2,8 +2,8 @@ import { FC, useCallback, useRef } from "react"; import { useRouter } from "app/navigation/use-router"; -import { ModalMethods } from "design-system/modal-new"; -import { ModalScreen } from "design-system/modal-new/modal.screen"; +import { ModalMethods } from "design-system/modal"; +import { ModalScreen } from "design-system/modal/modal.screen"; import { useBackPressHandler } from "./use-back-press-handler"; diff --git a/packages/design-system/modal-screen/with-modal-screen.web.tsx b/packages/design-system/modal-screen/with-modal-screen.web.tsx index dbf02faabd..a257ef95ea 100644 --- a/packages/design-system/modal-screen/with-modal-screen.web.tsx +++ b/packages/design-system/modal-screen/with-modal-screen.web.tsx @@ -2,8 +2,8 @@ import { FC, useCallback, useRef } from "react"; import { useRouter } from "app/navigation/use-router"; -import { ModalMethods } from "design-system/modal-new"; -import { ModalScreen } from "design-system/modal-new/modal.screen"; +import { ModalMethods } from "design-system/modal"; +import { ModalScreen } from "design-system/modal/modal.screen"; function withModalScreen

( Screen: FC

, diff --git a/packages/design-system/modal-sheet/index.tsx b/packages/design-system/modal-sheet/index.tsx deleted file mode 100644 index 60da457a48..0000000000 --- a/packages/design-system/modal-sheet/index.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { useCallback } from "react"; -import { useWindowDimensions } from "react-native"; - -import { BottomSheet } from "../bottom-sheet"; -import { Modal } from "../modal"; -import { Header } from "../modal/header"; -import { TW } from "../tailwind/types"; - -type Props = { - children: React.ReactElement; - title?: string; - visible?: boolean; - close?: () => void; - onClose?: () => void; - snapPoints?: string[]; - bodyContentTW?: TW; -}; - -export function ModalSheet({ visible = true, bodyContentTW, ...props }: Props) { - const { width } = useWindowDimensions(); - - const renderHandleComponent = useCallback( - (handleProps) => ( -

- ), - [props.title, props.close] - ); - - if (width >= 768) { - return visible ? ( - { - // TODO: extract `onClose` to a proper unmount transition completion event. - props.close?.(); - props.onClose?.(); - }} - > - {props.children} - - ) : null; - } - - return ( - - {props.children} - - ); -} diff --git a/packages/design-system/modal-sheet/modal-sheet.stories.tsx b/packages/design-system/modal-sheet/modal-sheet.stories.tsx deleted file mode 100644 index f55a06207b..0000000000 --- a/packages/design-system/modal-sheet/modal-sheet.stories.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { useState } from "react"; - -import { Meta } from "@storybook/react"; - -import { Button } from "../button"; -import { Text } from "../text"; -import { View } from "../view"; -import { ModalSheet } from "./index"; - -export default { - component: ModalSheet, - title: "Components/ModalSheet", -} as Meta; - -const Container = (props: any) => { - return {props.children}; -}; - -export const Basic: React.VFC<{}> = () => { - const [visible, setVisible] = useState(false); - return ( - - - setVisible(false)} - > - - Hello world - - - - ); -}; diff --git a/packages/design-system/modal/backdrop.tsx b/packages/design-system/modal/backdrop.tsx deleted file mode 100644 index fb6f5611dd..0000000000 --- a/packages/design-system/modal/backdrop.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { View } from "../view"; -import type { ModalProps } from "./types"; - -interface ModalBackdropProps extends Pick {} - -export function ModalBackdrop({ close }: ModalBackdropProps) { - return ( - - ); -} diff --git a/packages/design-system/modal/body.tsx b/packages/design-system/modal/body.tsx deleted file mode 100644 index aea941b63c..0000000000 --- a/packages/design-system/modal/body.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { useRef } from "react"; -import { ScrollView } from "react-native"; - -import { tw as tailwind } from "../tailwind"; -import type { TW } from "../tailwind/types"; -import { View } from "../view"; -import { BODY_CONTAINER_TW, BODY_TW } from "./constants"; -import type { ModalProps } from "./types"; - -interface ModalBodyProps extends Pick { - tw?: TW; - contentTW?: TW; -} - -export function ModalBody({ - tw, - contentTW, - scrollable, - children, -}: ModalBodyProps) { - const containerStyle = scrollable - ? tailwind.style(BODY_CONTAINER_TW, tw) - : tailwind.style("flex-1", BODY_CONTAINER_TW, BODY_TW, tw, contentTW); - const contentContainerStyle = tailwind.style(BODY_TW, contentTW); - - const BodyWrapper = scrollable ? ScrollView : View; - return ( - - {children} - - ); -} diff --git a/packages/design-system/modal/body.web.tsx b/packages/design-system/modal/body.web.tsx deleted file mode 100644 index c4daecc59a..0000000000 --- a/packages/design-system/modal/body.web.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; - -import { SxProp } from "dripsy"; - -import { View } from "../view"; -import { BODY_CONTAINER_TW, BODY_TW } from "./constants"; -import type { ModalProps } from "./types"; - -interface ModalBodyProps extends Pick { - tw?: string; -} - -export function ModalBody({ tw = "", children }: ModalBodyProps) { - return ( - - {children} - - ); -} - -const stylesX = { - container: { overflowY: "scroll" } as SxProp, -}; diff --git a/packages/design-system/modal/constants.ts b/packages/design-system/modal/constants.ts index 4fa4f0d33a..e4b4daa045 100644 --- a/packages/design-system/modal/constants.ts +++ b/packages/design-system/modal/constants.ts @@ -1,40 +1,2 @@ -import { Platform } from "react-native"; - -const DEFAULT_WIDTH = Platform.select({ - web: "w-10/12 max-w-480px md:w-420px lg:w-420px xl:w-480px", - default: "w-12/12 max-w-480px md:w-480px lg:w-480px", -}); -const DEFAULT_HEIGHT = "max-h-280px"; - -// tailwind classes -const CONTAINER_TW_BASE = - "items-center absolute ios:absolute android:absolute top-0 right-0 bottom-0 left-0"; -const CONTAINER_TW = Platform.select({ - web: `${CONTAINER_TW_BASE} justify-center`, - android: `${CONTAINER_TW_BASE} justify-end`, - ios: CONTAINER_TW_BASE, -}); - -const MODAL_TW_BASE = - "flex overflow-hidden bg-white dark:bg-black shadow-lg shadow-black dark:shadow-white"; -const MODAL_TW = Platform.select({ - web: `${MODAL_TW_BASE} rounded-[32px]`, - ios: `flex-1 ${MODAL_TW_BASE}`, - android: `${MODAL_TW_BASE} rounded-t-[32px]`, -}); - -const BODY_CONTAINER_TW_BASE = "bg-gray-100 dark:bg-gray-900"; -const BODY_CONTAINER_TW = Platform.select({ - web: `flex-1 ${BODY_CONTAINER_TW_BASE}`, - default: BODY_CONTAINER_TW_BASE, -}); -const BODY_TW = "p-[16px]"; - -export { - DEFAULT_HEIGHT, - DEFAULT_WIDTH, - CONTAINER_TW, - MODAL_TW, - BODY_CONTAINER_TW, - BODY_TW, -}; +export const MOBILE_SNAP_POINTS = ["50%"]; +export const WEB_HEIGHT = "max-h-280px"; diff --git a/packages/design-system/modal/container.tsx b/packages/design-system/modal/container.tsx deleted file mode 100644 index 1174b026b2..0000000000 --- a/packages/design-system/modal/container.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Platform, StyleSheet, Modal as RNModal } from "react-native"; - -import { GestureHandlerRootView } from "react-native-gesture-handler"; - -import { CONTAINER_TW } from "./constants"; -import type { ModalWrapperProps } from "./types"; - -interface ModalContainer { - onDismiss?: () => void; - children: React.ReactNode; -} - -export const createModalContainer = ( - ModalWrapper?: React.FC | null -) => - Platform.select({ - ios: ({ children }: ModalContainer) => children, - android: ({ children, onDismiss }: ModalContainer) => - ModalWrapper ? ( - {children} - ) : ModalWrapper === null ? ( - children - ) : ( - - - {children} - - - ), - default: ({ children, onDismiss }) => ( - - {children} - - ), - }) as React.FC; diff --git a/packages/design-system/modal/footer.tsx b/packages/design-system/modal/footer.tsx deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/design-system/modal/header.tsx b/packages/design-system/modal/header.tsx deleted file mode 100644 index 6c521a0c0b..0000000000 --- a/packages/design-system/modal/header.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { Platform } from "react-native"; - -import { Button } from "design-system/button"; -import { Close, MoreHorizontal } from "design-system/icon"; -import { Pressable } from "design-system/pressable-scale"; -import { tw } from "design-system/tailwind"; -import { Text } from "design-system/text"; -import { View } from "design-system/view"; - -type Props = { - title?: string; - close?: () => void; -}; - -export function Header({ title, close }: Props) { - return ( - <> - - {Platform.OS !== "web" && ( - - )} - - - - - - - {title} - - - {/* - - */} - - - ); -} diff --git a/packages/design-system/modal/index.tsx b/packages/design-system/modal/index.tsx index 7d3189ab3a..963b400423 100644 --- a/packages/design-system/modal/index.tsx +++ b/packages/design-system/modal/index.tsx @@ -1,87 +1,64 @@ -import React, { useMemo } from "react"; -import { KeyboardAvoidingView, Platform, StyleSheet } from "react-native"; +import { forwardRef, memo, useCallback, useRef } from "react"; -import { useSafeAreaInsets } from "app/lib/safe-area"; +import { MOBILE_SNAP_POINTS, WEB_HEIGHT } from "./constants"; +import { ModalContainer as BaseModalContainer } from "./modal.container"; +import type { ModalMethods, ModalProps } from "./types"; -import { View } from "design-system/view"; +export { ModalFooter } from "./modal.footer"; +export { ModalMethods }; -import { ModalBackdrop } from "./backdrop"; -import { ModalBody } from "./body"; -import { - DEFAULT_HEIGHT, - DEFAULT_WIDTH, - CONTAINER_TW, - MODAL_TW, -} from "./constants"; -import { createModalContainer } from "./container"; -import { Header } from "./header"; -import type { ModalProps } from "./types"; +const ModalComponent = forwardRef( + function ModalComponent( + { + title, + isScreen = false, + web_height = WEB_HEIGHT, + mobile_snapPoints = MOBILE_SNAP_POINTS, + modalContainer: ModalContainer = BaseModalContainer, + children, + onClose, + }, + ref + ) { + const didFireClose = useRef(false); -const ModalKeyboardAvoidingView: React.FC<{ - keyboardVerticalOffset: number; - style: any; -}> = Platform.select({ - web: ({ children }) => children as any, - default: ({ keyboardVerticalOffset, style, children }) => ( - - {children} - - ), -}); + //#region methods + const handleOnClose = useCallback(() => { + if (didFireClose.current) { + return; + } + didFireClose.current = true; + onClose?.(); + }, [onClose]); -export function Modal({ - title, - width = DEFAULT_WIDTH, - height = DEFAULT_HEIGHT, - bodyTW, - bodyContentTW, - keyboardVerticalOffset = 0, - scrollable = true, - close, - onDismiss, - modalWrapper, - children, -}: ModalProps) { - const { bottom: safeAreaBottom } = useSafeAreaInsets(); + const handleClose = useCallback(() => { + if (!isScreen) { + handleOnClose(); + //@ts-ignore + } else if (isScreen && ref && ref.current) { + //@ts-ignore + ref.current.close(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isScreen, handleOnClose]); + //#endregion - const ModalContainer = useMemo( - () => createModalContainer(modalWrapper), - [modalWrapper] - ); - return ( - - - - - -
- - {children} - - - - - - ); -} + //#region render + return ( + + {children} + + ); + //#endregion + } +); + +export const Modal = memo(ModalComponent); diff --git a/packages/design-system/modal-new/modal.backdrop.tsx b/packages/design-system/modal/modal.backdrop.tsx similarity index 100% rename from packages/design-system/modal-new/modal.backdrop.tsx rename to packages/design-system/modal/modal.backdrop.tsx diff --git a/packages/design-system/modal-new/modal.backdrop.web.tsx b/packages/design-system/modal/modal.backdrop.web.tsx similarity index 100% rename from packages/design-system/modal-new/modal.backdrop.web.tsx rename to packages/design-system/modal/modal.backdrop.web.tsx diff --git a/packages/design-system/modal-new/modal.container.tsx b/packages/design-system/modal/modal.container.tsx similarity index 100% rename from packages/design-system/modal-new/modal.container.tsx rename to packages/design-system/modal/modal.container.tsx diff --git a/packages/design-system/modal-new/modal.container.web.tsx b/packages/design-system/modal/modal.container.web.tsx similarity index 100% rename from packages/design-system/modal-new/modal.container.web.tsx rename to packages/design-system/modal/modal.container.web.tsx diff --git a/packages/design-system/modal-new/modal.footer.tsx b/packages/design-system/modal/modal.footer.tsx similarity index 100% rename from packages/design-system/modal-new/modal.footer.tsx rename to packages/design-system/modal/modal.footer.tsx diff --git a/packages/design-system/modal-new/modal.footer.web.tsx b/packages/design-system/modal/modal.footer.web.tsx similarity index 100% rename from packages/design-system/modal-new/modal.footer.web.tsx rename to packages/design-system/modal/modal.footer.web.tsx diff --git a/packages/design-system/modal-new/modal.header-bar.tsx b/packages/design-system/modal/modal.header-bar.tsx similarity index 100% rename from packages/design-system/modal-new/modal.header-bar.tsx rename to packages/design-system/modal/modal.header-bar.tsx diff --git a/packages/design-system/modal-new/modal.header.tsx b/packages/design-system/modal/modal.header.tsx similarity index 100% rename from packages/design-system/modal-new/modal.header.tsx rename to packages/design-system/modal/modal.header.tsx diff --git a/packages/design-system/modal-new/modal.screen.ios.tsx b/packages/design-system/modal/modal.screen.ios.tsx similarity index 100% rename from packages/design-system/modal-new/modal.screen.ios.tsx rename to packages/design-system/modal/modal.screen.ios.tsx diff --git a/packages/design-system/modal-new/modal.screen.tsx b/packages/design-system/modal/modal.screen.tsx similarity index 100% rename from packages/design-system/modal-new/modal.screen.tsx rename to packages/design-system/modal/modal.screen.tsx diff --git a/packages/design-system/modal/modal.stories.tsx b/packages/design-system/modal/modal.stories.tsx index 32f7018dd5..6d54ab8414 100644 --- a/packages/design-system/modal/modal.stories.tsx +++ b/packages/design-system/modal/modal.stories.tsx @@ -1,91 +1,93 @@ import { useState } from "react"; +import { BottomSheetScrollView } from "@gorhom/bottom-sheet"; import { Meta } from "@storybook/react"; -import { Button } from "../button"; -import { Text } from "../text"; +import { Button } from "design-system/button"; +import { Close } from "design-system/icon"; +import { Text } from "design-system/text"; + import { View } from "../view"; import { Modal } from "./index"; +import { ModalHeader } from "./modal.header"; export default { - component: Modal, - title: "Components/Modal", + component: ModalHeader, + title: "Components/NewModal", } as Meta; const Container = (props: any) => { - return {props.children}; + return {props.children}; +}; + +export const HeaderDefault: React.VFC<{}> = () => { + return ( + + + + ); +}; + +export const HeaderWithEndContent: React.VFC<{}> = () => { + return ( + + ( + + )} + /> + + ); }; -export const Basic: React.VFC<{}> = () => { +export const Default: React.VFC<{}> = () => { const [visible, setVisible] = useState(false); + + const onClose = () => { + setVisible(false); + }; return ( {visible && ( - setVisible(false)}> - - - Lorem Ipsum is simply dummy text of the printing and typesetting - industry. Lorem Ipsum has been the industry's standard dummy text - ever since the 1500s, when an unknown printer took a galley of - type and scrambled it to make a type specimen book. It has - survived not only five centuries, but also the leap into - electronic typesetting, remaining essentially unchanged. It was - popularised in the 1960s with the release of Letraset sheets - containing Lorem Ipsum passages, and more recently with desktop - publishing software like Aldus PageMaker including versions of - Lorem Ipsum. Lorem Ipsum is simply dummy text of the printing and - typesetting industry. Lorem Ipsum has been the industry's standard - dummy text ever since the 1500s, when an unknown printer took a - galley of type and scrambled it to make a type specimen book. It - has survived not only five centuries, but also the leap into - electronic typesetting, remaining essentially unchanged. It was - popularised in the 1960s with the release of Letraset sheets - containing Lorem Ipsum passages, and more recently with desktop - publishing software like Aldus PageMaker including versions of - Lorem Ipsum. - - + + )} ); }; -export const AutoHeight: React.VFC<{}> = () => { +export const WithScrollable: React.VFC<{}> = () => { const [visible, setVisible] = useState(false); + + const onClose = () => { + console.log("onClose"); + setVisible(false); + }; return ( - + {visible && ( - setVisible(false)} height=""> - - - Lorem Ipsum is simply dummy text of the printing and typesetting - industry. Lorem Ipsum has been the industry's standard dummy text - ever since the 1500s, when an unknown printer took a galley of - type and scrambled it to make a type specimen book. It has - survived not only five centuries, but also the leap into - electronic typesetting, remaining essentially unchanged. It was - popularised in the 1960s with the release of Letraset sheets - containing Lorem Ipsum passages, and more recently with desktop - publishing software like Aldus PageMaker including versions of - Lorem Ipsum. Lorem Ipsum is simply dummy text of the printing and - typesetting industry. Lorem Ipsum has been the industry's standard - dummy text ever since the 1500s, when an unknown printer took a - galley of type and scrambled it to make a type specimen book. It - has survived not only five centuries, but also the leap into - electronic typesetting, remaining essentially unchanged. It was - popularised in the 1960s with the release of Letraset sheets - containing Lorem Ipsum passages, and more recently with desktop - publishing software like Aldus PageMaker including versions of - Lorem Ipsum. - - + + + {Array(50) + .fill(0) + .map((_, index) => ( + {`#${index} item`} + ))} + )} diff --git a/packages/design-system/modal/types.ts b/packages/design-system/modal/types.ts index 6dab0507d4..0a3f764972 100644 --- a/packages/design-system/modal/types.ts +++ b/packages/design-system/modal/types.ts @@ -1,73 +1,102 @@ -import type React from "react"; +import type { FC, ReactNode } from "react"; + +import type { + BottomSheetProps, + BottomSheetFooterProps, +} from "@gorhom/bottom-sheet"; import type { TW } from "../tailwind/types"; -export interface ModalWrapperProps { - tw?: TW; +export interface ModalMethods { + close: () => void; } export interface ModalProps { - /** - * Defines the modal content. - */ - children: React.ReactNode; - /** - * Defines the modal wrapper. - */ - modalWrapper?: React.FC | null; /** * Defines the modal title. - * - * @default undefined + * @default "" */ title?: string; /** - * Defines the height style, set it empty to let - * the modal be auto height. - * - * @default "max-h-280px" + * Defines if the modal is presenting as + * a screen. + * @default false */ - height?: string; + isScreen?: boolean; /** - * Defines the width style. - * - * @default "w-10/12 max-w-480px md:w-480px lg:w-480px" + * **MOBILE ONLY**: Defines the points for the bottom sheet + * to snap to. It accepts array of number, string or mix. + * @default ["50%"] */ - width?: string; + mobile_snapPoints?: BottomSheetProps["snapPoints"]; + /** - * Defines the body tailwind style. - * - * @default undefined + * **WEB ONLY**: Defines the modal container height. + * It could be static value or responsive. + * @default "max-h-280px" */ - bodyTW?: TW; + web_height?: string; + /** - * Defines the body ScrollView content tailwind style. - * + * Defines the modal container + * tailwind style. * @default undefined */ - bodyContentTW?: TW; + tw?: string; + + //#region components + modalContainer?: FC; /** - * Defines the keyboard vertical offset, usually - * the header height. - * - * @default 0 + * Defines the modal content. + * @default undefined */ - keyboardVerticalOffset?: number; + children?: ReactNode; + //#endregion + + //#region callbacks /** - * Defines if the modal body is scrollable or not. + * Defines the action to close + * the modal view/screen. + * @default undefined */ - scrollable?: boolean; + onClose?: () => void; + //#endregion +} + +export interface ModalHeaderProps + extends Pick { /** - * Defines the action to be fried to close - * the modal. - * + * Defines the component to be placed + * at the end of the header. * @default undefined */ - close?: () => void; + endContentComponent?: FC; /** - * Defines the callback when the modal dismiss. - * + * Defines the header tailwind style. * @default undefined */ - onDismiss?: () => void; + tw?: TW; } + +export interface ModalContainerProps + extends Pick< + ModalProps, + | "title" + | "isScreen" + | "onClose" + | "children" + | "mobile_snapPoints" + | "web_height" + > { + close: () => void; +} + +export interface ModalScreenProps extends ModalProps { + close: () => void; +} + +export interface ModalFooterProps { + children: JSX.Element; +} + +export interface ModalBackdropProps extends Pick {} diff --git a/packages/design-system/modal-new/useKeyboardOffset.android.ts b/packages/design-system/modal/useKeyboardOffset.android.ts similarity index 100% rename from packages/design-system/modal-new/useKeyboardOffset.android.ts rename to packages/design-system/modal/useKeyboardOffset.android.ts diff --git a/packages/design-system/modal-new/useKeyboardOffset.ts b/packages/design-system/modal/useKeyboardOffset.ts similarity index 100% rename from packages/design-system/modal-new/useKeyboardOffset.ts rename to packages/design-system/modal/useKeyboardOffset.ts From df99490324b304499d3e1b96365ee6d1c994ff49 Mon Sep 17 00:00:00 2001 From: Axel Delafosse Date: Wed, 27 Apr 2022 13:19:02 +0200 Subject: [PATCH 3/9] remove background color for web modals --- packages/design-system/modal/modal.container.web.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/design-system/modal/modal.container.web.tsx b/packages/design-system/modal/modal.container.web.tsx index 9ef6a0954a..af33eed8f9 100644 --- a/packages/design-system/modal/modal.container.web.tsx +++ b/packages/design-system/modal/modal.container.web.tsx @@ -11,7 +11,6 @@ const CONTAINER_TW = [ "top-0 right-0 bottom-0 left-0", "flex items-center justify-end sm:justify-center", "z-[999]", - "bg-red-900", ]; const MODAL_CONTAINER_TW = [ From 0a4c83c99e94dded2b169559704719ac3e4bbc88 Mon Sep 17 00:00:00 2001 From: Axel Delafosse Date: Wed, 27 Apr 2022 13:39:45 +0200 Subject: [PATCH 4/9] bring back modal sheet --- packages/app/screens/create.tsx | 18 +----- packages/design-system/index.tsx | 1 + packages/design-system/modal-sheet/index.tsx | 57 +++++++++++++++++++ .../modal-sheet/modal-sheet.stories.tsx | 37 ++++++++++++ 4 files changed, 97 insertions(+), 16 deletions(-) create mode 100644 packages/design-system/modal-sheet/index.tsx create mode 100644 packages/design-system/modal-sheet/modal-sheet.stories.tsx diff --git a/packages/app/screens/create.tsx b/packages/app/screens/create.tsx index 0f36904824..1c3c9fd0c0 100644 --- a/packages/app/screens/create.tsx +++ b/packages/app/screens/create.tsx @@ -1,15 +1,14 @@ -import { useContext, useEffect, useMemo } from "react"; +import { useContext, useEffect } from "react"; import { Linking, Platform } from "react-native"; import { Create } from "app/components/create"; import { MintContext } from "app/context/mint-context"; -import { mixpanel } from "app/lib/mixpanel"; import { useNavigation } from "app/lib/react-navigation/native"; import { useHideHeader } from "app/navigation/use-navigation-elements"; import { createParam } from "app/navigation/use-param"; import { useRouter } from "app/navigation/use-router"; -import { Button, Modal, ModalSheet, Spinner, Text, View } from "design-system"; +import { Button, Spinner, Text, View } from "design-system"; import { useAlert } from "design-system/alert"; import { Hidden } from "design-system/hidden"; import { withModalScreen } from "design-system/modal-screen/with-modal-screen"; @@ -29,20 +28,7 @@ const CreateModal = () => { const { state, dispatch } = useContext(MintContext); //#endregion - //#region variables - const snapPoints = useMemo(() => ["90%"], []); - const ModalComponent = Platform.OS === "android" ? ModalSheet : Modal; - //#endregion - //#region effects - useEffect(() => { - mixpanel.track("Create page view"); - - // return () => { - // dispatch({ type: "reset" }); - // }; - }, []); - useEffect(() => { const unsubscribe = navigation.addListener("beforeRemove", (e) => { if ( diff --git a/packages/design-system/index.tsx b/packages/design-system/index.tsx index cd04f1d856..e2fb67e71f 100644 --- a/packages/design-system/index.tsx +++ b/packages/design-system/index.tsx @@ -10,6 +10,7 @@ export { Image } from "design-system/image"; export { LikeButton } from "design-system/like-button"; export { Media } from "design-system/media"; export { Modal } from "design-system/modal"; +export { ModalSheet } from "design-system/modal-sheet"; export { Pressable } from "design-system/pressable-scale"; export { ScrollView } from "design-system/scroll-view"; export { SegmentedControl } from "design-system/segmented-control"; diff --git a/packages/design-system/modal-sheet/index.tsx b/packages/design-system/modal-sheet/index.tsx new file mode 100644 index 0000000000..427cf326b2 --- /dev/null +++ b/packages/design-system/modal-sheet/index.tsx @@ -0,0 +1,57 @@ +import { useCallback } from "react"; +import { useWindowDimensions } from "react-native"; + +import { BottomSheet } from "../bottom-sheet"; +import { Modal } from "../modal"; +import { ModalHeader } from "../modal/modal.header"; +import { TW } from "../tailwind/types"; + +type Props = { + children: React.ReactElement; + title?: string; + visible?: boolean; + close?: () => void; + onClose?: () => void; + snapPoints?: string[]; + bodyContentTW?: TW; +}; + +export function ModalSheet({ visible = true, bodyContentTW, ...props }: Props) { + const { width } = useWindowDimensions(); + + const renderHandleComponent = useCallback( + (handleProps) => ( + + ), + [props.title, props.close] + ); + + if (width >= 768) { + return visible ? ( + { + // TODO: extract `onClose` to a proper unmount transition completion event. + props.close?.(); + props.onClose?.(); + }} + > + {props.children} + + ) : null; + } + + return ( + + {props.children} + + ); +} diff --git a/packages/design-system/modal-sheet/modal-sheet.stories.tsx b/packages/design-system/modal-sheet/modal-sheet.stories.tsx new file mode 100644 index 0000000000..f55a06207b --- /dev/null +++ b/packages/design-system/modal-sheet/modal-sheet.stories.tsx @@ -0,0 +1,37 @@ +import { useState } from "react"; + +import { Meta } from "@storybook/react"; + +import { Button } from "../button"; +import { Text } from "../text"; +import { View } from "../view"; +import { ModalSheet } from "./index"; + +export default { + component: ModalSheet, + title: "Components/ModalSheet", +} as Meta; + +const Container = (props: any) => { + return {props.children}; +}; + +export const Basic: React.VFC<{}> = () => { + const [visible, setVisible] = useState(false); + return ( + + + setVisible(false)} + > + + Hello world + + + + ); +}; From 82c508a04855a76c80fc110eaf8e87eca8a3f0b5 Mon Sep 17 00:00:00 2001 From: Axel Delafosse Date: Wed, 27 Apr 2022 13:56:13 +0200 Subject: [PATCH 5/9] handle login modal close --- packages/app/screens/login.tsx | 1 - .../modal-screen/with-modal-screen.tsx | 8 ++++---- .../modal-screen/with-modal-screen.web.tsx | 14 +++++++++----- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/app/screens/login.tsx b/packages/app/screens/login.tsx index 705995feb3..ffe5b915e1 100644 --- a/packages/app/screens/login.tsx +++ b/packages/app/screens/login.tsx @@ -32,7 +32,6 @@ function LoginModal() { }, [redirect_url, router]); //#endregion - // TODO: close={router.asPath === "/login" ? () => router.push("/") : router.pop} return ; } diff --git a/packages/design-system/modal-screen/with-modal-screen.tsx b/packages/design-system/modal-screen/with-modal-screen.tsx index 0a03e6a3c4..d8859205dd 100644 --- a/packages/design-system/modal-screen/with-modal-screen.tsx +++ b/packages/design-system/modal-screen/with-modal-screen.tsx @@ -19,13 +19,13 @@ function withModalScreen

( ) { return function (props: P) { const modalRef = useRef(null); - const { pop } = useRouter(); + useBackPressHandler(modalRef); + const router = useRouter(); const onClose = useCallback(() => { - pop(); - }, [pop]); + router.pop(); + }, [router]); - useBackPressHandler(modalRef); return ( ( ) { return function (props: P) { const modalRef = useRef(null); - const { pathname, query, pop } = useRouter(); + const router = useRouter(); const onClose = useCallback(() => { - pop(); - }, [pop]); + if (router.asPath === "/login") { + router.push("/"); + } else { + router.pop(); + } + }, [router]); const shouldShowModal = - pathname === matchingPathname || - Boolean(query[matchingQueryParam as any]); + router.pathname === matchingPathname || + Boolean(router.query[matchingQueryParam as any]); if (!shouldShowModal) { return null; From b74b99f1e138c4e4d8c25dc798c9c808f9bcfdc1 Mon Sep 17 00:00:00 2001 From: Axel Delafosse Date: Wed, 27 Apr 2022 14:56:08 +0200 Subject: [PATCH 6/9] fix design login modal on web --- packages/app/components/login/index.web.tsx | 26 +++++++++++---------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/app/components/login/index.web.tsx b/packages/app/components/login/index.web.tsx index 100185a866..3854d163ec 100644 --- a/packages/app/components/login/index.web.tsx +++ b/packages/app/components/login/index.web.tsx @@ -2,7 +2,7 @@ import { useCallback, useMemo } from "react"; import { yup } from "app/lib/yup"; -import { View, Text, Button, ButtonLabel } from "design-system"; +import { Button, ButtonLabel, Text, View } from "design-system"; import { LoginContainer } from "./login-container"; import { LoginHeader } from "./login-header"; @@ -76,7 +76,7 @@ export function Login({ onLogin }: LoginProps) { ) : ( <> - + - - + + — or — - + + + )} From 493c988348c34f08c12637846b834e02785f95b7 Mon Sep 17 00:00:00 2001 From: Axel Delafosse Date: Wed, 27 Apr 2022 15:09:20 +0200 Subject: [PATCH 7/9] improve modal sheet --- packages/app/components/following-user-list.tsx | 1 + packages/app/components/notifications.tsx | 6 +++--- packages/app/components/profile/profile-top.tsx | 2 +- packages/app/components/user-list.tsx | 6 +++--- packages/design-system/modal-sheet/index.tsx | 2 +- packages/design-system/modal/constants.ts | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/app/components/following-user-list.tsx b/packages/app/components/following-user-list.tsx index 31ce04a694..54230f7d52 100644 --- a/packages/app/components/following-user-list.tsx +++ b/packages/app/components/following-user-list.tsx @@ -18,6 +18,7 @@ export const FollowingList = (props: { hideSheet: () => void; }) => { const { data, loading } = useFollowingList(props.profileId); + return ( ); diff --git a/packages/app/components/notifications.tsx b/packages/app/components/notifications.tsx index 6a22636830..cd0da91838 100644 --- a/packages/app/components/notifications.tsx +++ b/packages/app/components/notifications.tsx @@ -14,16 +14,16 @@ import { axios } from "app/lib/axios"; import { CHAIN_IDENTIFIERS } from "app/lib/constants"; import { useBottomTabBarHeight } from "app/lib/react-navigation/bottom-tabs"; import { useScrollToTop } from "app/lib/react-navigation/native"; -import { TextLink, Link } from "app/navigation/link"; +import { Link, TextLink } from "app/navigation/link"; import { formatAddressShort } from "app/utilities"; import { ModalSheet, Skeleton, Text, View } from "design-system"; import { Avatar } from "design-system/avatar"; import { HeartFilled, + MarketFilled, MessageFilled, PlusFilled, - MarketFilled, } from "design-system/icon"; import { colors } from "design-system/tailwind/colors"; @@ -99,7 +99,7 @@ export const Notifications = () => { /> 0} close={() => setUsers([])} diff --git a/packages/app/components/profile/profile-top.tsx b/packages/app/components/profile/profile-top.tsx index 23b8c874f7..8c40b4e425 100644 --- a/packages/app/components/profile/profile-top.tsx +++ b/packages/app/components/profile/profile-top.tsx @@ -298,7 +298,7 @@ export const ProfileTop = ({ - No Results found + No results found ); } @@ -110,7 +110,7 @@ const FollowingListUser = memo( }: { item: FollowerUser; isFollowingUser: boolean } & FollowingListProp) => { return ( { + onClose={() => { // TODO: extract `onClose` to a proper unmount transition completion event. props.close?.(); props.onClose?.(); diff --git a/packages/design-system/modal/constants.ts b/packages/design-system/modal/constants.ts index e4b4daa045..95a145e087 100644 --- a/packages/design-system/modal/constants.ts +++ b/packages/design-system/modal/constants.ts @@ -1,2 +1,2 @@ -export const MOBILE_SNAP_POINTS = ["50%"]; +export const MOBILE_SNAP_POINTS = ["90%", "100%"]; export const WEB_HEIGHT = "max-h-280px"; From 41fdc30bd53c0fd3403887e08e902b823cf3602c Mon Sep 17 00:00:00 2001 From: Axel Delafosse Date: Wed, 27 Apr 2022 15:15:20 +0200 Subject: [PATCH 8/9] set default bottom sheet snap points --- packages/design-system/bottom-sheet/index.tsx | 14 +++++++------- packages/design-system/modal/types.ts | 7 ++----- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/design-system/bottom-sheet/index.tsx b/packages/design-system/bottom-sheet/index.tsx index 91646176fd..96a70f182b 100644 --- a/packages/design-system/bottom-sheet/index.tsx +++ b/packages/design-system/bottom-sheet/index.tsx @@ -1,17 +1,17 @@ import { - useRef, - useMemo, - useCallback, - useEffect, ComponentProps, - MutableRefObject, ComponentType, + MutableRefObject, + useCallback, + useEffect, + useMemo, + useRef, } from "react"; import { - BottomSheetModal, BottomSheetBackdrop, BottomSheetHandleProps, + BottomSheetModal, BottomSheetTextInput as BottomSheetInput, } from "@gorhom/bottom-sheet"; @@ -50,7 +50,7 @@ export const BottomSheet = (props: BottomSheetProps) => { } }, [visible]); - const defaultSnapPoints = useMemo(() => ["50%", "75%"], []); + const defaultSnapPoints = useMemo(() => ["90%", "100%"], []); const renderBackdrop = useCallback( (props) => ( diff --git a/packages/design-system/modal/types.ts b/packages/design-system/modal/types.ts index 0a3f764972..ad10f87fb9 100644 --- a/packages/design-system/modal/types.ts +++ b/packages/design-system/modal/types.ts @@ -1,9 +1,6 @@ import type { FC, ReactNode } from "react"; -import type { - BottomSheetProps, - BottomSheetFooterProps, -} from "@gorhom/bottom-sheet"; +import type { BottomSheetProps } from "@gorhom/bottom-sheet"; import type { TW } from "../tailwind/types"; @@ -26,7 +23,7 @@ export interface ModalProps { /** * **MOBILE ONLY**: Defines the points for the bottom sheet * to snap to. It accepts array of number, string or mix. - * @default ["50%"] + * @default ["90%", "100%"] */ mobile_snapPoints?: BottomSheetProps["snapPoints"]; From 294e60d85741120f7b34698455c3fc967df14c3a Mon Sep 17 00:00:00 2001 From: Axel Delafosse Date: Wed, 27 Apr 2022 15:15:30 +0200 Subject: [PATCH 9/9] remove max height for login modal --- packages/design-system/modal/modal.container.web.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/design-system/modal/modal.container.web.tsx b/packages/design-system/modal/modal.container.web.tsx index af33eed8f9..5d6214320e 100644 --- a/packages/design-system/modal/modal.container.web.tsx +++ b/packages/design-system/modal/modal.container.web.tsx @@ -16,7 +16,6 @@ const CONTAINER_TW = [ const MODAL_CONTAINER_TW = [ "flex overflow-hidden justify-center", "w-full sm:w-480px", - "max-h-[50%]", // TODO < verify this with the designer "bg-white dark:bg-black", "shadow-xl shadow-black dark:shadow-white", "rounded-t-[32px] rounded-b-0 sm:rounded-b-[32px]",