From 36064464eb4e7de1e22e8349fd1cef6a9d13ef67 Mon Sep 17 00:00:00 2001 From: Alessandro Dell'Oste Date: Fri, 13 Oct 2023 16:46:20 +0200 Subject: [PATCH] feat: [IOCOM-610] Add the new `ModuleAttachment` component (#5101) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Short description This PR adds the new `ModuleAttachment`, a component that is going to be used in the detail of a message. _Note_: It's in line with the guidelines of the old design. ### Preview | ModuleAttachment | | --- | | | ## List of changes proposed in this pull request - Added `ModuleAttachment` - Updated the Modules section ## How to test Go to the **_Profile → Design System → Modules_** --------- Co-authored-by: Damiano Plebani Co-authored-by: Andrea --- ts/components/ModuleAttachment.tsx | 248 +++++++++++++++++++ ts/features/design-system/core/DSModules.tsx | 62 +++++ 2 files changed, 310 insertions(+) create mode 100644 ts/components/ModuleAttachment.tsx diff --git a/ts/components/ModuleAttachment.tsx b/ts/components/ModuleAttachment.tsx new file mode 100644 index 00000000000..dd04e89b07e --- /dev/null +++ b/ts/components/ModuleAttachment.tsx @@ -0,0 +1,248 @@ +import React, { useCallback } from "react"; +import { + ActivityIndicator, + GestureResponderEvent, + Pressable, + PressableProps, + StyleSheet, + View +} from "react-native"; +import { + IOColors, + IOIconSizeScale, + IOIcons, + IOListItemVisualParams, + IOScaleValues, + IOSpacingScale, + IOSpringValues, + IOStyles, + Icon, + LabelSmall, + VSpacer, + WithTestID +} from "@pagopa/io-app-design-system"; +import Animated, { + Extrapolate, + interpolate, + useAnimatedStyle, + useDerivedValue, + useSharedValue, + withSpring +} from "react-native-reanimated"; +import Placeholder from "rn-placeholder"; +import I18n from "../i18n"; + +type PartialProps = WithTestID<{ + title: string; + format: "doc" | "pdf"; + subtitle?: string; + isLoading?: boolean; + isFetching?: boolean; + onPress: (event: GestureResponderEvent) => void; +}>; + +export type ModuleAttachmentProps = PartialProps & + Pick; + +const formatMap: Record< + NonNullable, + IOIcons +> = { + doc: "docAttach", + pdf: "docAttachPDF" +}; + +const styles = StyleSheet.create({ + button: { + flex: 1, + flexDirection: "row", + alignItems: "center", + justifyContent: "space-between", + paddingHorizontal: 16, + paddingVertical: 16, + borderRadius: 8, + borderColor: IOColors.bluegreyLight, + backgroundColor: IOColors.white, + borderStyle: "solid", + borderWidth: 1 + }, + rightSection: { + marginLeft: IOListItemVisualParams.iconMargin, + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-end" + } +}); + +const DISABLED_OPACITY = 0.5; +const ICON_SIZE: IOIconSizeScale = 32; +const MARGIN_SIZE: IOSpacingScale = 16; + +const ModuleAttachmentContent = ({ + isFetching, + format, + title, + subtitle +}: Pick< + ModuleAttachmentProps, + "isFetching" | "format" | "title" | "subtitle" +>) => { + const IconOrActivityIndicatorComponent = () => { + if (isFetching) { + return ( + + ); + } + + return ( + + ); + }; + + return ( + <> + + + + + + {title} + + {subtitle && ( + + {subtitle} + + )} + + + + + + ); +}; + +/** + * The `ModuleAttachment` component is a custom button component with an extended outline style. + * It provides an animated scaling effect when pressed. + * + * @param {boolean} isLoading - If true, displays a skeleton loading component. + * @param {boolean} isFetching - If true, displays an activity indicator. + * @param {boolean} disabled - If true, the button is disabled. + * @param {string} testID - The test ID for testing purposes. + * @param {string} title - The title text to display. + * @param {string} subtitle - The subtitle text to display. + * @param {string} iconName - The icon name to display. + * @param {function} onPress - The function to be executed when the item is pressed. + */ +export const ModuleAttachment = ({ + isLoading = false, + isFetching = false, + disabled = false, + testID, + accessibilityLabel, + onPress, + ...rest +}: ModuleAttachmentProps) => { + const isPressed: Animated.SharedValue = useSharedValue(0); + + // Scaling transformation applied when the button is pressed + const animationScaleValue = IOScaleValues?.magnifiedButton?.pressedState; + + const scaleTraversed = useDerivedValue(() => + withSpring(isPressed.value, IOSpringValues.button) + ); + + // Interpolate animation values from `isPressed` values + const animatedStyle = useAnimatedStyle(() => { + const scale = interpolate( + scaleTraversed.value, + [0, 1], + [1, animationScaleValue], + Extrapolate.CLAMP + ); + + return { + transform: [{ scale }] + }; + }); + + const onPressIn = useCallback(() => { + // eslint-disable-next-line functional/immutable-data + isPressed.value = 1; + }, [isPressed]); + + const onPressOut = useCallback(() => { + // eslint-disable-next-line functional/immutable-data + isPressed.value = 0; + }, [isPressed]); + + const handleOnPress = useCallback( + (event: GestureResponderEvent) => { + if (isFetching) { + return; + } + onPress(event); + }, + [isFetching, onPress] + ); + + if (isLoading) { + return ; + } + + return ( + + + + + + ); +}; + +const SkeletonComponent = () => ( + + + + + + + + + + +); diff --git a/ts/features/design-system/core/DSModules.tsx b/ts/features/design-system/core/DSModules.tsx index 1fda064631e..35b19073c4d 100644 --- a/ts/features/design-system/core/DSModules.tsx +++ b/ts/features/design-system/core/DSModules.tsx @@ -8,6 +8,7 @@ import { PaymentNoticeStatus, VSpacer } from "@pagopa/io-app-design-system"; +import { ModuleAttachment } from "../../../components/ModuleAttachment"; import { getBadgeTextByPaymentNoticeStatus } from "../../messages/utils/strings"; import { H2 } from "../../../components/core/typography/H2"; import { DSComponentViewerBox } from "../components/DSComponentViewerBox"; @@ -34,6 +35,17 @@ export const DSModules = () => ( {theme => ( +

+ ModuleAttachment +

+ {renderModuleAttachment()} + + +

( ); +const renderModuleAttachment = () => ( + + + + + + + + + + + + + + + +); + const renderModulePaymentNotice = () => (