Fix external links
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -2,4 +2,4 @@
|
||||
'@backstage/canon': minor
|
||||
---
|
||||
|
||||
**Breaking changes** We are updating our Link component to use React Aria under the hood. To match their API we are updating the `to` prop to `href` to match both internal and expernal routing. We are also updating our variant naming to include all our new font sizes.
|
||||
**Breaking changes** We are updating our Link component to use React Aria under the hood. To match their API we are updating the `to` prop to `href` to match both internal and external routing. We are also updating our variant naming to include all our new font sizes.
|
||||
|
||||
@@ -40,7 +40,7 @@ type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
href: '#',
|
||||
href: '/home',
|
||||
children: 'Sign up for Backstage',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -21,6 +21,28 @@ import { useStyles } from '../../hooks/useStyles';
|
||||
import type { LinkProps } from './types';
|
||||
import { useNavigate, useHref } from 'react-router-dom';
|
||||
|
||||
// Helper function to determine if a link is external
|
||||
function isExternalLink(href?: string): boolean {
|
||||
if (!href) return false;
|
||||
|
||||
// Check if it's an absolute URL with protocol
|
||||
if (href.startsWith('http://') || href.startsWith('https://')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if it's a protocol-relative URL
|
||||
if (href.startsWith('//')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if it's a mailto: or tel: link
|
||||
if (href.startsWith('mailto:') || href.startsWith('tel:')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
const navigate = useNavigate();
|
||||
@@ -29,6 +51,7 @@ export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
variant = 'body',
|
||||
weight = 'regular',
|
||||
color = 'primary',
|
||||
href,
|
||||
...restProps
|
||||
} = props;
|
||||
|
||||
@@ -38,11 +61,28 @@ export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
color,
|
||||
});
|
||||
|
||||
const isExternal = isExternalLink(href);
|
||||
|
||||
// If it's an external link, render AriaLink without RouterProvider
|
||||
if (isExternal) {
|
||||
return (
|
||||
<AriaLink
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, className)}
|
||||
href={href}
|
||||
{...dataAttributes}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// For internal links, use RouterProvider
|
||||
return (
|
||||
<RouterProvider navigate={navigate} useHref={useHref}>
|
||||
<AriaLink
|
||||
ref={ref}
|
||||
className={clsx(classNames.root, className)}
|
||||
href={href}
|
||||
{...dataAttributes}
|
||||
{...restProps}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user