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

feat: use RouterLink #357

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 7 additions & 9 deletions src/blocks/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useContext} from 'react';

import {Button, HTML, Media, RouterLink} from '../../components';
import {Button, HTML, Media} from '../../components';
import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs/HeaderBreadcrumbs';
import {getMediaImage} from '../../components/Media/Image/utils';
import YFMWrapper from '../../components/YFMWrapper/YFMWrapper';
Expand Down Expand Up @@ -141,14 +141,12 @@ export const HeaderBlock = (props: WithChildren<HeaderBlockFullProps>) => {
<div className={b('buttons')} data-qa="header-buttons">
{buttons &&
buttons.map((button, index) => (
<RouterLink href={button.url} key={index}>
<Button
key={index}
className={b('button')}
size="xl"
{...button}
/>
</RouterLink>
<Button
key={index}
className={b('button')}
size="xl"
{...button}
/>
))}
</div>
)}
Expand Down
6 changes: 3 additions & 3 deletions src/blocks/Icons/Icons.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useContext} from 'react';

import {BlockHeader, Image} from '../../components';
import {BlockHeader, Image, RouterLink} from '../../components';
import {LocationContext} from '../../context/locationContext';
import {IconsBlockProps} from '../../models';
import {block, getLinkProps} from '../../utils';
Expand All @@ -16,15 +16,15 @@ const Icons = ({title, size = 's', items}: IconsBlockProps) => {
<div className={b({size})}>
{title && <BlockHeader className={b('header')} title={title} colSizes={{all: 12}} />}
{items.map((item) => (
<a
<RouterLink
className={b('item')}
key={item.url}
href={item.url}
{...getLinkProps(item.url, hostname)}
>
<Image className={b('image')} src={item.src} />
<p className={b('text')}>{item.text}</p>
</a>
</RouterLink>
))}
</div>
);
Expand Down
3 changes: 3 additions & 0 deletions src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, {useCallback, useContext} from 'react';
import {Button as CommonButton, Icon, Platform, StoreBadge} from '@gravity-ui/uikit';

import {LocaleContext} from '../../context/localeContext/localeContext';
import {LocationContext} from '../../context/locationContext';
import {useAnalytics} from '../../hooks';
import {useMetrika} from '../../hooks/useMetrika';
import {Github} from '../../icons';
Expand All @@ -25,6 +26,7 @@ const b = block('button-block');

const Button = (props: ButtonProps) => {
const handleMetrika = useMetrika();
const {Link} = useContext(LocationContext);
const {lang, tld} = useContext(LocaleContext);
const {
className,
Expand Down Expand Up @@ -95,6 +97,7 @@ const Button = (props: ButtonProps) => {
size={toCommonSize(size as OldButtonSize)}
href={url ? setUrlTld(url, tld) : undefined}
width={width}
component={Link}
{...buttonProps}
>
{icon && buttonImg.position === 'left' ? icon : null}
Expand Down
14 changes: 2 additions & 12 deletions src/components/CardBase/CardBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,8 @@ export const Layout = (props: CardBaseProps) => {
};

return url ? (
<RouterLink href={url}>
<a
href={url}
target={target}
rel={target === '_blank' ? 'noopener noreferrer' : undefined}
className={fullClassName}
draggable={false}
onDragStart={(e) => e.preventDefault()}
onClick={onClick}
>
{cardContent}
</a>
<RouterLink href={url} target={target} className={fullClassName} onClick={onClick}>
{cardContent}
</RouterLink>
) : (
<div className={fullClassName}>{cardContent}</div>
Expand Down
10 changes: 8 additions & 2 deletions src/components/FileLink/FileLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, {useContext} from 'react';
import {LocationContext} from '../../context/locationContext';
import {FileLinkProps, WithChildren} from '../../models';
import {block, getLinkProps} from '../../utils';
import RouterLink from '../RouterLink/RouterLink';

import './FileLink.scss';

Expand Down Expand Up @@ -46,9 +47,14 @@ const FileLink = (props: WithChildren<FileLinkProps>) => {
<div className={b('file-label')}>{fileExt}</div>
)}
<div className={b('link')}>
<a href={href} {...getLinkProps(href, hostname)} onClick={onClick}>
<RouterLink
href={href}
{...getLinkProps(href, hostname)}
onClick={onClick}
forceAnchor
>
{text}
</a>
</RouterLink>
</div>
</div>
);
Expand Down
5 changes: 3 additions & 2 deletions src/components/HeaderBreadcrumbs/HeaderBreadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {useAnalytics} from '../../hooks';
import {useMetrika} from '../../hooks/useMetrika';
import {DefaultEventNames, HeaderBreadCrumbsProps} from '../../models';
import {block} from '../../utils';
import RouterLink from '../RouterLink/RouterLink';

import './HeaderBreadcrumbs.scss';

Expand All @@ -23,9 +24,9 @@ export default function HeaderBreadcrumbs(props: HeaderBreadCrumbsProps) {
<div className={b({theme}, className)}>
{items.map((item) => (
<div className={b('item')} key={item.url}>
<a href={item.url} className={b('text')} onClick={onClick}>
<RouterLink href={item.url} className={b('text')} onClick={onClick}>
{item.text}
</a>
</RouterLink>
</div>
))}
</div>
Expand Down
5 changes: 3 additions & 2 deletions src/components/Link/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {ClassNameProps, DefaultEventNames, LinkProps, TextSize, WithChildren} fr
import {block, getLinkProps, setUrlTld} from '../../utils';
import BackLink from '../BackLink/BackLink';
import FileLink from '../FileLink/FileLink';
import RouterLink from '../RouterLink/RouterLink';

import './Link.scss';

Expand Down Expand Up @@ -80,7 +81,7 @@ const LinkBlock = (props: WithChildren<LinkFullProps>) => {
const content = children || text;

return (
<a
<RouterLink
className={b('link', {theme: colorTheme, 'has-arrow': arrow})}
href={href}
onClick={onClick}
Expand All @@ -99,7 +100,7 @@ const LinkBlock = (props: WithChildren<LinkFullProps>) => {
) : (
content
)}
</a>
</RouterLink>
);
}
default:
Expand Down
44 changes: 40 additions & 4 deletions src/components/RouterLink/RouterLink.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,53 @@
import React, {Fragment, useContext} from 'react';
import React, {useContext} from 'react';

import {LocationContext} from '../../context/locationContext';
import {WithChildren} from '../../models';
import {EXTERNAL_LINK_PROPS, isLinkExternal} from '../../utils';

export interface RouterLinkProps {
href: string;
forceAnchor?: boolean;
target?: string;
rel?: string;
className?: string;
[key: string]: unknown;
}

const RouterLink = ({href, children}: WithChildren<RouterLinkProps>) => {
const {Link} = useContext(LocationContext);
const RouterLink = ({
href,
rel,
children,
target,
forceAnchor = false,
...commonProps
}: WithChildren<RouterLinkProps>) => {
const {Link, hostname} = useContext(LocationContext);

return Link ? <Link href={href}>{children}</Link> : <Fragment>{children}</Fragment>;
const isExternal = isLinkExternal(href, hostname);
const shouldAnchorTag =
typeof href === 'string' &&
(!Link || isExternal || forceAnchor || target === EXTERNAL_LINK_PROPS.target);
const component = shouldAnchorTag ? 'a' : Link;

if (!component) {
return <div>{JSON.stringify({isExternal, shouldAnchorTag, component})}</div>;
}

const linkProps = {
href,
target,
rel: target === EXTERNAL_LINK_PROPS.target && !rel ? EXTERNAL_LINK_PROPS.rel : rel,
};

return React.createElement(
component,
{
href,
...(shouldAnchorTag ? linkProps : {}),
...commonProps,
},
children,
);
};

export default RouterLink;
11 changes: 8 additions & 3 deletions src/components/Title/Title.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {Fragment, ReactNode, useContext} from 'react';

import {HTML, ToggleArrow} from '../';
import {HTML, RouterLink, ToggleArrow} from '../';
import {LocationContext} from '../../context/locationContext';
import {MobileContext} from '../../context/mobileContext';
import {TextSize, TitleProps} from '../../models';
Expand Down Expand Up @@ -81,9 +81,14 @@ const Title = (props: TitleFullProps) => {
content = textMarkup;
} else if (url) {
content = (
<a className={b('link')} href={url} {...getLinkProps(url, hostname)} onClick={onClick}>
<RouterLink
className={b('link')}
href={url}
{...getLinkProps(url, hostname)}
onClick={onClick}
>
{insideClickableContent}
</a>
</RouterLink>
);
} else if (onClick) {
content = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import {Button, RouterLink} from '../../../../../components';
import {Button} from '../../../../../components';
import {BlockIdContext} from '../../../../../context/blockIdContext';
import {ButtonProps} from '../../../../../models';
import {block} from '../../../../../utils';
Expand All @@ -15,17 +15,11 @@ const ANALYTICS_ID = 'navigation';
type NavigationButtonProps = Pick<NavigationItemProps, 'className'> & ButtonProps;

export const NavigationButton: React.FC<NavigationButtonProps> = (props) => {
const {url, target, className} = props;
const {url, className} = props;
const classes = b(null, className);
return (
<BlockIdContext.Provider value={ANALYTICS_ID}>
{target ? (
<Button className={classes} {...props} url={url} />
) : (
<RouterLink href={url}>
<Button {...props} className={classes} url={url} />
</RouterLink>
)}
<Button {...props} className={classes} url={url} />
</BlockIdContext.Provider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const b = block('navigation-link');
type NavigationLinkProps = NavigationItemProps & NavigationLinkItem;

export const NavigationLink: React.FC<NavigationLinkProps> = (props) => {
const {hostname, Link} = useContext(LocationContext);
const {hostname} = useContext(LocationContext);
const {url, text, icon, arrow, target, className, iconSize, ...rest} = props;
const linkExtraProps = getLinkProps(url, hostname, target);
const iconData = icon && getMediaImage(icon);
Expand All @@ -29,19 +29,9 @@ export const NavigationLink: React.FC<NavigationLinkProps> = (props) => {
</Fragment>
);

if (linkExtraProps?.target || !Link) {
return (
<a href={url} title={text} className={classes} {...rest} {...linkExtraProps}>
{content}
</a>
);
} else {
return (
<RouterLink href={url} passHref>
<a {...rest} className={classes}>
{content}
</a>
</RouterLink>
);
}
return (
<RouterLink href={url} title={text} className={classes} {...rest} {...linkExtraProps}>
{content}
</RouterLink>
);
};
6 changes: 3 additions & 3 deletions src/navigation/components/SocialIcon/SocialIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import {Image} from '../../../components';
import {Image, RouterLink} from '../../../components';
import {getMediaImage} from '../../../components/Media/Image/utils';
import {NavigationSocialItem} from '../../../models';
import {block} from '../../../utils';
Expand All @@ -17,9 +17,9 @@ const SocialIcon: React.FC<NavigationSocialItemOwnProps> = ({icon, url, classNam
const iconData = getMediaImage(icon);

return (
<a href={url} target="_blank" rel="noopener noreferrer" className={b(null, className)}>
<RouterLink href={url} target="_blank" className={b(null, className)}>
<Image className={b('icon')} {...iconData} />
</a>
</RouterLink>
);
};

Expand Down
20 changes: 9 additions & 11 deletions src/sub-blocks/BannerCard/BannerCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useContext} from 'react';

import {BackgroundImage, Button, HTML, RouterLink, YFMWrapper} from '../../components';
import {BackgroundImage, Button, HTML, YFMWrapper} from '../../components';
import {ThemeValueContext} from '../../context/theme/ThemeValueContext';
import {BannerCardProps} from '../../models';
import {block, getThemedValue} from '../../utils';
Expand Down Expand Up @@ -42,16 +42,14 @@ export const BannerCard = (props: BannerCardProps) => {
/>
)}
</div>
<RouterLink href={url}>
<Button
className={b('button')}
theme="raised"
size="xl"
text={text}
url={url}
target={target}
/>
</RouterLink>
<Button
className={b('button')}
theme="raised"
size="xl"
text={text}
url={url}
target={target}
/>
</div>
<BackgroundImage
className={b('image')}
Expand Down