Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IOAPPX-333] Add dark mode support to all the Module… components #298

Merged
merged 18 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions example/src/pages/Modules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,18 @@ const renderModulePaymentNotice = () => (
/>
</View>
</ComponentViewerBox>
<ComponentViewerBox name="ModulePaymentNotice, default variant, loading">
<View>
<ModulePaymentNotice
isLoading
onPress={mockFn}
paymentNoticeStatus="default"
paymentNoticeAmount="100,00 €"
title="Codice avviso"
subtitle="302012131232131"
/>
</View>
</ComponentViewerBox>
</>
);

Expand Down Expand Up @@ -151,8 +163,18 @@ const renderModuleCheckout = () => (
onPress={modulePress}
/>
</ComponentViewerBox>
<ComponentViewerBox name="ModuleCheckout, no CTA, with image">
<ModuleCheckout
image={{
uri: "https://assets.cdn.platform.pagopa.it/apm/bancomatpay.png"
}}
title="3,50 $"
subtitle="Piú o meno"
onPress={modulePress}
/>
</ComponentViewerBox>
<ComponentViewerBox name="ModuleCheckout, loading">
<ModuleCheckout isLoading ctaText="Loading" />
<ModuleCheckout isLoading />
</ComponentViewerBox>
</>
);
Expand All @@ -161,7 +183,7 @@ const renderModuleAttachment = () => (
<>
<ComponentViewerBox name="ModuleAttachment, pdf variant">
<ModuleAttachment
title="Documento.pdf"
title="Documento dal nome molto molto molto lungo.pdf"
format="pdf"
onPress={modulePress}
/>
Expand Down
181 changes: 36 additions & 145 deletions src/components/modules/ModuleAttachment.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,20 @@
import React, { useCallback } from "react";
import {
GestureResponderEvent,
Pressable,
PressableProps,
StyleSheet,
View
} from "react-native";
import Animated, {
Extrapolate,
interpolate,
useAnimatedStyle,
useDerivedValue,
useSharedValue,
withSpring
} from "react-native-reanimated";
import { GestureResponderEvent, PressableProps, View } from "react-native";
import Placeholder from "rn-placeholder";
import {
IOColors,
IOListItemVisualParams,
IOScaleValues,
IOSpringValues,
useIOTheme
} from "../../core";
import { IOListItemVisualParams, useIOTheme } from "../../core";
import { WithTestID } from "../../utils/types";
import { Badge } from "../badge";
import { Icon } from "../icons";
import { LoadingSpinner } from "../loadingSpinner";
import { VSpacer } from "../spacer";
import { LabelSmallAlt } from "../typography";
import { ModuleStatic } from "./ModuleStatic";
import { PressableModuleBase } from "./PressableModuleBase";

type PartialProps = WithTestID<{
title: string;
format: "doc" | "pdf";
isLoading?: boolean;
loadingAccessibilityLabel?: string;
isFetching?: boolean;
fetchingAccessibilityLabel?: string;
onPress: (event: GestureResponderEvent) => void;
Expand All @@ -45,33 +26,6 @@ export type ModuleAttachmentProps = PartialProps &
"onPress" | "accessibilityLabel" | "disabled" | "testID"
>;

type SkeletonComponentProps = {
loadingAccessibilityLabel?: string;
};

const styles = StyleSheet.create({
button: {
flexDirection: "row",
alignItems: "center",
paddingHorizontal: 16,
paddingVertical: 16,
borderRadius: 8,
borderStyle: "solid",
borderWidth: 1
},
innerContent: {
alignItems: "flex-start",
flex: 1,
flexDirection: "column"
},
rightSection: {
marginLeft: IOListItemVisualParams.iconMargin,
alignItems: "center"
}
});

const DISABLED_OPACITY = 0.5;

const ModuleAttachmentContent = ({
isFetching,
format,
Expand All @@ -82,11 +36,13 @@ const ModuleAttachmentContent = ({
"isFetching" | "format" | "title" | "testID"
>) => {
const theme = useIOTheme();

const IconOrActivityIndicatorComponent = () => {
if (isFetching) {
const activityIndicatorTestId = testID
? `${testID}_activityIndicator`
: undefined;

return (
<LoadingSpinner
testID={activityIndicatorTestId}
Expand All @@ -106,17 +62,17 @@ const ModuleAttachmentContent = ({

return (
<>
<View style={styles.innerContent}>
<View style={{ alignItems: "flex-start", flexShrink: 1 }}>
mastro993 marked this conversation as resolved.
Show resolved Hide resolved
<LabelSmallAlt
numberOfLines={1}
numberOfLines={2}
color={theme["interactiveElem-default"]}
>
{title}
</LabelSmallAlt>
<VSpacer size={4} />
<Badge text={format.toUpperCase()} variant="default" />
</View>
<View style={styles.rightSection}>
<View style={{ marginLeft: IOListItemVisualParams.iconMargin }}>
<IconOrActivityIndicatorComponent />
</View>
</>
Expand All @@ -133,7 +89,6 @@ const ModuleAttachmentContent = ({
* @param {string} format - Badge content. PDF or DOC.
* @param {boolean} isLoading - If true, displays a skeleton loading component.
* @param {boolean} isFetching - If true, displays an activity indicator.
* @param {string} loadingAccessibilityLabel - Optional accessibility label to use during loading.
* @param {function} onPress - The function to be executed when the item is pressed.
* @param {string} testID - The test ID for testing purposes.
* @param {string} title - The title text to display.
Expand All @@ -146,45 +101,10 @@ export const ModuleAttachment = ({
format,
isLoading = false,
isFetching = false,
loadingAccessibilityLabel,
onPress,
testID,
title
}: ModuleAttachmentProps) => {
const theme = useIOTheme();
const isPressed: Animated.SharedValue<number> = 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) {
Expand All @@ -196,75 +116,46 @@ export const ModuleAttachment = ({
);

if (isLoading) {
return (
<SkeletonComponent
loadingAccessibilityLabel={loadingAccessibilityLabel}
/>
);
return <ModuleAttachmentSkeleton />;
}

const pressableAccessibilityLabel =
(isFetching && !!fetchingAccessibilityLabel
? fetchingAccessibilityLabel
: accessibilityLabel) ?? title;
return (
<Pressable

return disabled || isFetching ? (
<ModuleStatic disabled={disabled}>
<ModuleAttachmentContent
isFetching={isFetching}
title={title}
format={format}
/>
</ModuleStatic>
) : (
<PressableModuleBase
testID={testID}
onPress={handleOnPress}
onPressIn={onPressIn}
onPressOut={onPressOut}
accessible={true}
accessibilityRole={"button"}
accessibilityHint={format}
accessibilityLabel={pressableAccessibilityLabel}
disabled={disabled || isFetching}
>
<Animated.View
style={[
styles.button,
animatedStyle,
{
opacity: disabled ? DISABLED_OPACITY : 1,
borderColor: IOColors[theme["cardBorder-default"]],
backgroundColor: IOColors[theme["appBackground-primary"]]
}
]}
accessibilityElementsHidden={true}
importantForAccessibility="no-hide-descendants"
>
<ModuleAttachmentContent
isFetching={isFetching}
title={title}
format={format}
/>
</Animated.View>
</Pressable>
<ModuleAttachmentContent
isFetching={isFetching}
title={title}
format={format}
/>
</PressableModuleBase>
);
};

const SkeletonComponent = ({
loadingAccessibilityLabel
}: SkeletonComponentProps) => {
const theme = useIOTheme();

return (
<View
style={[
styles.button,
{
borderColor: IOColors[theme["cardBorder-default"]],
backgroundColor: IOColors[theme["appBackground-primary"]]
}
]}
accessible={true}
accessibilityState={{ busy: true }}
accessibilityLabel={loadingAccessibilityLabel}
>
<View style={styles.innerContent}>
<Placeholder.Box animate="fade" radius={8} width={107} height={22} />
const ModuleAttachmentSkeleton = () => (
<ModuleStatic
startBlock={
<View>
<Placeholder.Box animate="fade" radius={8} width={107} height={16} />
<VSpacer size={4} />
<Placeholder.Box animate="fade" radius={8} width={44} height={22} />
<Placeholder.Box animate="fade" radius={16} width={44} height={20} />
</View>
</View>
);
};
}
/>
);
Loading
Loading