diff --git a/example/src/Screens/LinkComponent.tsx b/example/src/Screens/LinkComponent.tsx index f6000a14..96be55dd 100644 --- a/example/src/Screens/LinkComponent.tsx +++ b/example/src/Screens/LinkComponent.tsx @@ -3,6 +3,7 @@ import { View, StyleSheet, ScrollView } from 'react-native'; import { Button } from 'react-native-paper'; import { Link, + StackActions, RouteProp, ParamListBase, useLinkTo, @@ -46,6 +47,13 @@ const ArticleScreen = ({ > Go to /link-component/Album + + Replace with /link-component/Album + & { - href?: string; + to?: string; children: React.ReactNode; onPress?: ( e: React.MouseEvent | GestureResponderEvent diff --git a/packages/bottom-tabs/src/views/BottomTabBar.tsx b/packages/bottom-tabs/src/views/BottomTabBar.tsx index 75c897ea..53d4d33d 100644 --- a/packages/bottom-tabs/src/views/BottomTabBar.tsx +++ b/packages/bottom-tabs/src/views/BottomTabBar.tsx @@ -262,7 +262,7 @@ export default function BottomTabBar({ onPress={onPress} onLongPress={onLongPress} accessibilityLabel={accessibilityLabel} - href={buildLink(route.name, route.params)} + to={buildLink(route.name, route.params)} testID={options.tabBarTestID} allowFontScaling={allowFontScaling} activeTintColor={activeTintColor} diff --git a/packages/bottom-tabs/src/views/BottomTabItem.tsx b/packages/bottom-tabs/src/views/BottomTabItem.tsx index 9bfc9338..8d194ca8 100644 --- a/packages/bottom-tabs/src/views/BottomTabItem.tsx +++ b/packages/bottom-tabs/src/views/BottomTabItem.tsx @@ -42,7 +42,7 @@ type Props = { /** * URL to use for the link to the tab. */ - href?: string; + to?: string; /** * The button for the tab. Uses a `TouchableWithoutFeedback` by default. */ @@ -113,22 +113,22 @@ export default function BottomTabBarItem({ route, label, icon, - href, + to, button = ({ children, style, onPress, - href, + to, accessibilityRole, ...rest }: BottomTabBarButtonProps) => { - if (Platform.OS === 'web' && href) { + if (Platform.OS === 'web' && to) { // React Native Web doesn't forward `onClick` if we use `TouchableWithoutFeedback`. // We need to use `onClick` to be able to prevent default browser handling of links. return ( { if ( @@ -242,7 +242,7 @@ export default function BottomTabBarItem({ : inactiveBackgroundColor; return button({ - href, + to, onPress, onLongPress, testID, diff --git a/packages/drawer/src/views/DrawerItem.tsx b/packages/drawer/src/views/DrawerItem.tsx index e0033476..10539c8b 100644 --- a/packages/drawer/src/views/DrawerItem.tsx +++ b/packages/drawer/src/views/DrawerItem.tsx @@ -31,7 +31,7 @@ type Props = { /** * URL to use for the link to the tab. */ - href?: string; + to?: string; /** * Whether to highlight the drawer item as active. */ @@ -70,22 +70,22 @@ const Touchable = ({ children, style, onPress, - href, + to, accessibilityRole, delayPressIn, ...rest }: TouchableWithoutFeedbackProps & { - href?: string; + to?: string; children: React.ReactNode; onPress?: () => void; }) => { - if (Platform.OS === 'web' && href) { + if (Platform.OS === 'web' && to) { // React Native Web doesn't forward `onClick` if we use `TouchableWithoutFeedback`. // We need to use `onClick` to be able to prevent default browser handling of links. return ( { if ( @@ -124,7 +124,7 @@ export default function DrawerItem(props: Props) { icon, label, labelStyle, - href, + to, focused = false, activeTintColor = colors.primary, inactiveTintColor = Color(colors.text).alpha(0.68).rgb().string(), @@ -157,7 +157,7 @@ export default function DrawerItem(props: Props) { accessibilityComponentType="button" accessibilityRole="button" accessibilityStates={focused ? ['selected'] : []} - href={href} + to={to} > {iconNode} diff --git a/packages/drawer/src/views/DrawerItemList.tsx b/packages/drawer/src/views/DrawerItemList.tsx index 355a414a..04a00e17 100644 --- a/packages/drawer/src/views/DrawerItemList.tsx +++ b/packages/drawer/src/views/DrawerItemList.tsx @@ -56,7 +56,7 @@ export default function DrawerItemList({ inactiveBackgroundColor={inactiveBackgroundColor} labelStyle={labelStyle} style={itemStyle} - href={buildLink(route.name, route.params)} + to={buildLink(route.name, route.params)} onPress={() => { navigation.dispatch({ ...(focused diff --git a/packages/native/src/Link.tsx b/packages/native/src/Link.tsx index 163accfa..fa255e19 100644 --- a/packages/native/src/Link.tsx +++ b/packages/native/src/Link.tsx @@ -1,13 +1,27 @@ import * as React from 'react'; import { Text, TextProps, Platform, GestureResponderEvent } from 'react-native'; +import { + NavigationAction, + NavigationHelpersContext, +} from '@react-navigation/core'; import useLinkTo from './useLinkTo'; type Props = { to: string; + action?: NavigationAction; target?: string; } & (TextProps & { children: React.ReactNode }); -export default function Link({ to, children, ...rest }: Props) { +/** + * Component to render link to another screen using a path. + * Uses an anchor tag on the web. + * + * @param props.to Absolute path to screen (e.g. `/feeds/hot`). + * @param props.action Optional action to use for in-page navigation. By default, the path is parsed to an action based on linking config. + * @param props.children Child elements to render the content. + */ +export default function Link({ to, action, children, ...rest }: Props) { + const navigation = React.useContext(NavigationHelpersContext); const linkTo = useLinkTo(); const onPress = ( @@ -35,7 +49,15 @@ export default function Link({ to, children, ...rest }: Props) { } if (shouldHandle) { - linkTo(to); + if (action) { + if (navigation) { + navigation.dispatch(action); + } else { + throw new Error("Couldn't find a navigation object."); + } + } else { + linkTo(to); + } } };