From 0b72c8d738d1649065e07c20aa6e06f1ab3f7418 Mon Sep 17 00:00:00 2001 From: Damini Date: Fri, 23 Feb 2024 07:39:49 +0530 Subject: [PATCH 1/2] feat: add AlertDialog component in NativeWind --- .../nativewind/AlertDialog/index.tsx | 460 +++++++----------- .../components/AlertDialog/AlertDialog.tsx | 143 ++---- 2 files changed, 215 insertions(+), 388 deletions(-) diff --git a/example/storybook-nativewind/src/components-example/nativewind/AlertDialog/index.tsx b/example/storybook-nativewind/src/components-example/nativewind/AlertDialog/index.tsx index 326d3f0f01..6bde80b6f0 100644 --- a/example/storybook-nativewind/src/components-example/nativewind/AlertDialog/index.tsx +++ b/example/storybook-nativewind/src/components-example/nativewind/AlertDialog/index.tsx @@ -1,65 +1,60 @@ -import { - AnimatePresence, - AnimatedView, - AnimatedPressable, -} from '@gluestack-style/animation-resolver'; +import React, { useEffect } from 'react'; import { createAlertDialog } from '@gluestack-ui/alert-dialog'; -import { View, Pressable, ScrollView } from 'react-native'; import { + cssInterop, tva, + VariantProps, + withStyleContext, withStyleContextAndStates, useStyleContext, - withStates, } from '@gluestack-ui/nativewind-utils'; -import React from 'react'; -import { Platform } from 'react-native'; - +import Animated, { + Easing, + useSharedValue, + withSpring, + withTiming, +} from 'react-native-reanimated'; +import { + View, + StyleSheet, + Pressable, + ScrollView, + Platform, +} from 'react-native'; + +const AnimatedPressable = Animated.createAnimatedComponent(Pressable); const UIAccessibleAlertDialog = createAlertDialog({ - Root: withStyleContextAndStates(View), - Content: AnimatedView, - CloseButton: Platform.OS === 'web' ? Pressable : withStates(Pressable), + // @ts-ignore + Root: + Platform.OS === 'web' + ? withStyleContext(View) + : withStyleContextAndStates(View), + Body: ScrollView, + Content: Animated.View, + CloseButton: Pressable, Header: View, Footer: View, - Body: ScrollView, Backdrop: AnimatedPressable, - //@ts-ignore - AnimatePresence: AnimatePresence, + AnimatePresence: React.Fragment, //TODO: Add support for this }); +cssInterop(UIAccessibleAlertDialog, { className: 'style' }); +cssInterop(UIAccessibleAlertDialog.Content, { className: 'style' }); +cssInterop(UIAccessibleAlertDialog.CloseButton, { className: 'style' }); +cssInterop(UIAccessibleAlertDialog.Header, { className: 'style' }); +cssInterop(UIAccessibleAlertDialog.Footer, { className: 'style' }); +cssInterop(UIAccessibleAlertDialog.Body, { className: 'style' }); +cssInterop(UIAccessibleAlertDialog.Backdrop, { className: 'style' }); + const alertDialogStyle = tva({ - base: 'w-full h-full justify-center items-center web:pointer-events-none', + base: 'group/modal w-full h-full justify-center items-center web:pointer-events-none', + variants: { + size: {}, + }, }); -// const StyledRoot = styled( -// View, -// { -// w: '$full', -// h: '$full', -// justifyContent: 'center', -// alignItems: 'center', - -// variants: { -// size: { -// xs: { _content: { w: '60%', maxWidth: 360 } }, -// sm: { _content: { w: '70%', maxWidth: 420 } }, -// md: { _content: { w: '80%', maxWidth: 510 } }, -// lg: { _content: { w: '90%', maxWidth: 640 } }, -// full: { _content: { w: '$full' } }, -// }, -// }, -// defaultProps: { size: 'md' }, - -// _web: { -// pointerEvents: 'box-none', -// }, -// }, -// { -// descendantStyle: ['_content'], -// } -// ); - const alertDialogContentStyle = tva({ - base: 'bg-background-50 rounded-lg overflow-hidden shadow', + base: 'bg-background-50 rounded-lg overflow-hidden ', parentVariants: { size: { xs: 'w-[60%] max-w-[360px]', @@ -71,247 +66,108 @@ const alertDialogContentStyle = tva({ }, }); -// const StyledContent = styled( -// AnimatedView, -// { -// 'bg': '$background50', -// 'rounded': '$lg', -// 'overflow': 'hidden', - -// //@ts-ignore -// ':initial': { -// scale: 0.9, -// opacity: 0, -// }, - -// ':animate': { -// scale: 1, -// opacity: 1, -// }, - -// ':exit': { -// scale: 0.9, -// opacity: 0, -// }, - -// ':transition': { -// type: 'spring', -// damping: 18, -// stiffness: 250, -// opacity: { -// type: 'timing', -// duration: 250, -// }, -// }, - -// 'defaultProps': { -// softShadow: '3', -// }, -// }, -// { -// ancestorStyle: ['_content'], -// } -// ); - const alertDialogCloseButtonStyle = tva({ - base: 'z-10 rounded p-2 data-[focus-visible=true]:bg-background-100 web:cursor-pointer outline-0', - - // '_icon': { - // color: '$background400', - // }, - - // '_text': { - // color: '$background400', - // }, - - // ':hover': { - // _icon: { - // color: '$background700', - // }, - // _text: { - // color: '$background700', - // }, - // }, - - // ':active': { - // _icon: { - // color: '$background900', - // }, - // _text: { - // color: '$background900', - // }, - // }, - - // ':focusVisible': { - - // _icon: { - // color: '$background900', - // }, - - // _text: { - // color: '$background900', - // }, - // }, - // }, - // { - // descendantStyle: ['_icon', '_text'], + base: 'group/alert-dialog-close-button z-10 rounded-sm p-2 data-[focus-visible=true]:bg-background-100 web:cursor-pointer outline-0', }); -// const StyledCloseButton = styled( -// Pressable, -// { -// 'zIndex': 1, -// 'rounded': '$sm', -// 'p': '$2', - -// '_icon': { -// color: '$background400', -// }, - -// '_text': { -// color: '$background400', -// }, - -// ':hover': { -// _icon: { -// color: '$background700', -// }, -// _text: { -// color: '$background700', -// }, -// }, - -// ':active': { -// _icon: { -// color: '$background900', -// }, -// _text: { -// color: '$background900', -// }, -// }, - -// ':focusVisible': { -// bg: '$background100', - -// _icon: { -// color: '$background900', -// }, - -// _text: { -// color: '$background900', -// }, -// }, - -// '_web': { -// outlineWidth: 0, -// cursor: 'pointer', -// }, -// }, -// { -// descendantStyle: ['_icon', '_text'], -// } -// ); - const alertDialogHeaderStyle = tva({ - base: 'p-4 border-border-300 justify-between items-center flex-row', + base: 'p-4 border border-outline-300 justify-between items-center flex-row', }); -// const StyledHeader = styled( -// View, -// { -// p: '$4', -// borderColor: '$border300', -// justifyContent: 'space-between', -// alignItems: 'center', -// flexDirection: 'row', -// }, -// {} -// ); - const alertDialogFooterStyle = tva({ - base: 'p-4 flex-row justify-end items-center flex-wrap border-border-300', + base: 'p-4 flex-row justify-end items-center flex-wrap border-outline-300', }); -// const StyledFooter = styled( -// View, -// { -// p: '$4', -// flexDirection: 'row', -// justifyContent: 'flex-end', -// alignItems: 'center', -// flexWrap: 'wrap', -// borderColor: '$border300', -// }, -// {} -// ); - const alertDialogBodyStyle = tva({ base: 'px-4 py-2' }); -// const StyledBody = styled(ScrollView, { px: '$4', py: '$2' }, {}); - const alertDialogBackdropStyle = tva({ base: 'absolute left-0 top-0 right-0 bottom-0 bg-background-950 web:cursor-default', }); -// const StyledBackdrop = styled( -// AnimatedPressable, -// { -// ':initial': { -// opacity: 0, -// }, - -// ':animate': { -// opacity: 0.5, -// }, - -// ':exit': { -// opacity: 0, -// }, - -// ':transition': { -// type: 'spring', -// damping: 18, -// stiffness: 250, -// opacity: { -// type: 'timing', -// duration: 250, -// }, -// }, - -// 'position': 'absolute', -// 'left': 0, -// 'top': 0, -// 'right': 0, -// 'bottom': 0, -// 'bg': '$background950', - -// // @ts-ignore -// '_web': { -// cursor: 'default', -// }, -// }, -// {} -// ); - -export const AlertDialog = React.forwardRef( - ({ className, size = 'md', ...props }: any, ref) => { +type IAlertDialogProps = React.ComponentProps & + VariantProps; + +type IAlertDialogContentProps = React.ComponentProps< + typeof UIAccessibleAlertDialog.Content +> & + VariantProps; + +type IAlertDialogCloseButtonProps = React.ComponentProps< + typeof UIAccessibleAlertDialog.CloseButton +> & + VariantProps; + +type IAlertDialogHeaderProps = React.ComponentProps< + typeof UIAccessibleAlertDialog.Header +> & + VariantProps; + +type IAlertDialogFooterProps = React.ComponentProps< + typeof UIAccessibleAlertDialog.Footer +> & + VariantProps; + +type IAlertDialogBodyProps = React.ComponentProps< + typeof UIAccessibleAlertDialog.Body +> & + VariantProps; + +type IAlertDialogBackdropProps = React.ComponentProps< + typeof UIAccessibleAlertDialog.Backdrop +> & + VariantProps; + +const AlertDialog = React.forwardRef( + ( + { + className, + //@ts-ignore + size = 'md', + ...props + }: { className?: string } & IAlertDialogProps, + ref + ) => { return ( ); } ); -export const AlertDialogContent = React.forwardRef( - ({ className, size, ...props }: any, ref) => { +const AlertDialogContent = React.forwardRef( + ( + { + className, + size, + ...props + }: { className?: string } & IAlertDialogContentProps, + ref + ) => { const { size: parentSize } = useStyleContext(); + const opacity = useSharedValue(0); + const scale = useSharedValue(0.9); + useEffect(() => { + opacity.value = withTiming(1, { + easing: Easing.linear, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useEffect(() => { + scale.value = withSpring(1, { + damping: 18, + stiffness: 250, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return ( ); } ); -export const AlertDialogCloseButton = React.forwardRef( - ({ className, ...props }: any, ref) => { +const AlertDialogCloseButton = React.forwardRef( + ( + { + className, + ...props + }: { className?: string } & IAlertDialogCloseButtonProps, + ref + ) => { return ( { +const AlertDialogHeader = React.forwardRef( + ( + { className, ...props }: { className?: string } & IAlertDialogHeaderProps, + ref + ) => { return ( { +const AlertDialogFooter = React.forwardRef( + ( + { className, ...props }: { className?: string } & IAlertDialogFooterProps, + ref + ) => { return ( { +const AlertDialogBody = React.forwardRef( + ( + { className, ...props }: { className?: string } & IAlertDialogBodyProps, + ref + ) => { return ( { +const AlertDialogBackdrop = React.forwardRef( + ( + { className, ...props }: { className?: string } & IAlertDialogBackdropProps, + ref + ) => { + const opacity = useSharedValue(0); + + useEffect(() => { + opacity.value = withTiming(0.5, { + easing: Easing.linear, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return ( ); } ); -// AlertDialog.displayName = 'AlertDialog'; -// AlertDialogContent.displayName = 'AlertDialogContent'; -// AlertDialogCloseButton.displayName = 'AlertDialogCloseButton'; -// AlertDialogHeader.displayName = 'AlertDialogHeader'; -// AlertDialogFooter.displayName = 'AlertDialogFooter'; -// AlertDialogBody.displayName = 'AlertDialogBody'; -// AlertDialogBackdrop.displayName = 'AlertDialogBackdrop'; - -// export { -// AlertDialog, -// AlertDialogContent, -// AlertDialogCloseButton, -// AlertDialogHeader, -// AlertDialogFooter, -// AlertDialogBody, -// AlertDialogBackdrop, -// }; +AlertDialog.displayName = 'AlertDialog'; +AlertDialogContent.displayName = 'AlertDialogContent'; +AlertDialogCloseButton.displayName = 'AlertDialogCloseButton'; +AlertDialogHeader.displayName = 'AlertDialogHeader'; +AlertDialogFooter.displayName = 'AlertDialogFooter'; +AlertDialogBody.displayName = 'AlertDialogBody'; +AlertDialogBackdrop.displayName = 'AlertDialogBackdrop'; + +export { + AlertDialog, + AlertDialogContent, + AlertDialogCloseButton, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogBody, + AlertDialogBackdrop, +}; diff --git a/example/storybook-nativewind/src/components/AlertDialog/AlertDialog.tsx b/example/storybook-nativewind/src/components/AlertDialog/AlertDialog.tsx index 369e5a7951..edaf9e4b52 100644 --- a/example/storybook-nativewind/src/components/AlertDialog/AlertDialog.tsx +++ b/example/storybook-nativewind/src/components/AlertDialog/AlertDialog.tsx @@ -1,18 +1,8 @@ import React, { useState } from 'react'; - -import { - CloseIcon, - Button, - ButtonText, - ButtonGroup, - Text, - Center, - Icon, - Heading, - AlertCircleIcon, - CheckCircleIcon, - HStack, -} from '@gluestack-ui/themed'; +import { Button, ButtonText } from '@/components/ui/Button'; +import { Text } from '@/components/ui/Text'; +import { Heading } from '@/components/ui/Heading'; +import { X } from 'lucide-react-native'; import { AlertDialog, @@ -23,91 +13,45 @@ import { AlertDialogFooter, AlertDialogBody, } from '@/components/ui/AlertDialog'; -import { AlertTriangleIcon } from 'lucide-react-native'; -const AlertDialogBasic = ({ - showAlertDialog: showAlertDialogProp = true, - ...props -}) => { +const AlertDialogBasic = ({ ...props }) => { const [showAlertDialog, setShowAlertDialog] = useState(false); const handleClose = () => setShowAlertDialog(!showAlertDialog); return ( - - - - - Return Policy - - - - - - - Whoa, slow down there! This modal is like a red light at an - intersection, reminding you to stop and think before you proceed. Is - deleting this folder the right choice? - - - - - - - - - ); -}; - -const FigmaAlertDialogStory = ({ - showAlertDialog: _showAlertDialogProp = true, - _colorMode, - ...props -}) => { - return ( - - - - Return Policy - - - - - - - Whoa, slow down there! This modal is like a red light at an - intersection, reminding you to stop and think before you proceed. Is - deleting this folder the right choice? - - - - - - - - + <> + + + + + + Return Policy + + + + + + + Whoa, slow down there! This modal is like a red light at an + intersection, reminding you to stop and think before you proceed. + Is deleting this folder the right choice? + + + + + + + + + ); }; @@ -117,7 +61,6 @@ AlertDialogBasic.description = export default AlertDialogBasic; export { - FigmaAlertDialogStory, AlertDialog, AlertDialogBackdrop, AlertDialogContent, @@ -127,14 +70,6 @@ export { AlertDialogBody, Button, ButtonText, - ButtonGroup, Text, - CloseIcon, - Center, Heading, - Icon, - AlertCircleIcon, - HStack, - AlertTriangleIcon, - CheckCircleIcon, }; From 7543525633c60784cacd84c4ee0c2adbc8d5c7e3 Mon Sep 17 00:00:00 2001 From: Damini Date: Fri, 23 Feb 2024 11:02:27 +0530 Subject: [PATCH 2/2] fix: remove empty variant from alert dialog --- .../src/components-example/nativewind/AlertDialog/index.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/example/storybook-nativewind/src/components-example/nativewind/AlertDialog/index.tsx b/example/storybook-nativewind/src/components-example/nativewind/AlertDialog/index.tsx index 6bde80b6f0..bcdb7c9128 100644 --- a/example/storybook-nativewind/src/components-example/nativewind/AlertDialog/index.tsx +++ b/example/storybook-nativewind/src/components-example/nativewind/AlertDialog/index.tsx @@ -48,9 +48,6 @@ cssInterop(UIAccessibleAlertDialog.Backdrop, { className: 'style' }); const alertDialogStyle = tva({ base: 'group/modal w-full h-full justify-center items-center web:pointer-events-none', - variants: { - size: {}, - }, }); const alertDialogContentStyle = tva({