Skip to content

Commit

Permalink
[IOAPPX-356] Add animated divider to the HeaderFirstLevel component (
Browse files Browse the repository at this point in the history
…#368)

## Short description
This PR adds the new animated divider to the `HeaderFirstLevel`
component to enable the effect in the following PR in the `io-app` repo:
* pagopa/io-app#6054

## List of changes proposed in this pull request
- Update `HeaderFirstLevel` component

## How to test
N/A

---------

Co-authored-by: Emanuele Dall'Ara <[email protected]>
  • Loading branch information
dmnplb and LeleDallas authored Jan 15, 2025
1 parent 7cbb1e8 commit 85f00e6
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 75 deletions.
13 changes: 9 additions & 4 deletions example/src/pages/HeaderFirstLevel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,20 @@ export const HeaderFirstLevelScreen = () => {
header: () => (
<HeaderFirstLevel
ignoreSafeAreaMargin={alert !== undefined}
backgroundColor="light"
title={"Pagina"}
type="singleAction"
firstAction={{
icon: "help",
accessibilityLabel: "Go to the help section",
onPress: () => {
Alert.alert("Contextual Help");
},
accessibilityLabel: ""
}
}}
secondAction={{
icon: "coggle",
accessibilityLabel: "Go to the Settings section",
onPress: () => {
Alert.alert("Settings");
}
}}
/>
)
Expand Down
118 changes: 50 additions & 68 deletions src/components/layout/HeaderFirstLevel.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import * as React from "react";
import { useEffect, useLayoutEffect } from "react";
import { createRef, useEffect, useLayoutEffect } from "react";
import {
AccessibilityInfo,
findNodeHandle,
StyleSheet,
View
} from "react-native";
import Animated, {
AnimatedRef,
useAnimatedStyle,
useScrollViewOffset,
useSharedValue,
withTiming
} from "react-native-reanimated";
Expand All @@ -24,44 +26,15 @@ import { HStack } from "../stack";
import { H3 } from "../typography";
import { HeaderActionProps } from "./common";

type CommonProps = WithTestID<{
export type HeaderFirstLevel = WithTestID<{
title: string;
// This Prop will be removed once all the screens on the first level routing will be refactored
backgroundColor?: "light" | "dark";
ignoreSafeAreaMargin?: boolean;
}>;

interface Base extends CommonProps {
type: "base";
firstAction?: never;
secondAction?: never;
thirdAction?: never;
}

interface OneAction extends CommonProps {
type: "singleAction";
firstAction: HeaderActionProps;
secondAction?: never;
thirdAction?: never;
}

interface TwoActions extends CommonProps {
type: "twoActions";
firstAction: HeaderActionProps;
secondAction: HeaderActionProps;
thirdAction?: never;
}

interface ThreeActions extends CommonProps {
type: "threeActions";
firstAction: HeaderActionProps;
secondAction: HeaderActionProps;
thirdAction: HeaderActionProps;
}

export type HeaderFirstLevel = Base | OneAction | TwoActions | ThreeActions;

const HEADER_BG_COLOR_DARK: IOColors = "bluegrey";
thirdAction?: HeaderActionProps;
animatedRef?: AnimatedRef<Animated.ScrollView>;
animatedFlatListRef?: AnimatedRef<Animated.FlatList<any>>;
ignoreSafeAreaMargin?: boolean;
}>;

const styles = StyleSheet.create({
headerInner: {
Expand All @@ -71,20 +44,28 @@ const styles = StyleSheet.create({
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between"
},
headerDivider: {
position: "absolute",
width: "100%",
height: StyleSheet.hairlineWidth,
left: 0,
right: 0,
bottom: 0
}
});

export const HeaderFirstLevel = ({
title,
type,
testID,
backgroundColor = "light",
ignoreSafeAreaMargin = false,
firstAction,
secondAction,
thirdAction
thirdAction,
ignoreSafeAreaMargin = false,
animatedRef,
animatedFlatListRef
}: HeaderFirstLevel) => {
const titleRef = React.createRef<View>();
const titleRef = createRef<View>();
const insets = useSafeAreaInsets();
const theme = useIOTheme();
const paddingTop = useSharedValue(ignoreSafeAreaMargin ? 0 : insets.top);
Expand All @@ -96,6 +77,12 @@ export const HeaderFirstLevel = ({
}
});

/* We show the divider only when the header is scrolled down */
const offset = useScrollViewOffset(
(animatedRef as AnimatedRef<Animated.ScrollView>) ||
(animatedFlatListRef as AnimatedRef<Animated.FlatList<any>>)
);

useEffect(() => {
// eslint-disable-next-line functional/immutable-data
paddingTop.value = withTiming(
Expand All @@ -108,52 +95,47 @@ export const HeaderFirstLevel = ({
paddingTop: paddingTop.value
}));

const animatedDivider = useAnimatedStyle(() => ({
opacity: withTiming(offset.value > 0 ? 1 : 0, { duration: 200 })
}));

return (
<Animated.View
style={[
{
backgroundColor:
backgroundColor === "light"
? IOColors[theme["appBackground-primary"]]
: IOColors[HEADER_BG_COLOR_DARK]
},
{ backgroundColor: IOColors[theme["appBackground-primary"]] },
animatedStyle
]}
accessibilityRole="header"
testID={testID}
>
{/* Divider */}
{(animatedRef || animatedFlatListRef) && (
<Animated.View
style={[
{
...styles.headerDivider,
backgroundColor: IOColors[theme["divider-default"]]
},
animatedDivider
]}
/>
)}

<View style={styles.headerInner}>
<View ref={titleRef} accessible accessibilityRole="header">
<H3
weight="Bold"
style={{ flexShrink: 1 }}
numberOfLines={1}
color={
backgroundColor === "dark" ? "white" : theme["textBody-default"]
}
color={theme["textHeading-default"]}
>
{title}
</H3>
</View>
<HStack space={16} style={{ flexShrink: 0 }}>
{type === "threeActions" && (
<IconButton
{...thirdAction}
color={backgroundColor === "dark" ? "contrast" : "primary"}
/>
)}
{(type === "twoActions" || type === "threeActions") && (
<IconButton
{...secondAction}
color={backgroundColor === "dark" ? "contrast" : "primary"}
/>
)}
{type !== "base" && (
<IconButton
{...firstAction}
color={backgroundColor === "dark" ? "contrast" : "primary"}
/>
)}
{thirdAction && <IconButton {...thirdAction} color={"primary"} />}
<IconButton {...secondAction} color={"primary"} />
<IconButton {...firstAction} color={"primary"} />
</HStack>
</View>
</Animated.View>
Expand Down
3 changes: 0 additions & 3 deletions stories/foundation/templates/HeaderFirstLevel.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ type Story = StoryObj<typeof meta>;
export const Wallet: Story = {
args: {
title: "Portafoglio",
type: "twoActions",
backgroundColor: "dark",
firstAction: {
icon: "help",
accessibilityLabel: "Help",
Expand All @@ -41,7 +39,6 @@ export const Wallet: Story = {
export const Messages: Story = {
args: {
title: "Messaggi",
type: "twoActions",
firstAction: {
icon: "help",
accessibilityLabel: "Help",
Expand Down

0 comments on commit 85f00e6

Please sign in to comment.