Coursemology/coursemology2

View on GitHub
client/app/lib/components/core/Link.tsx

Summary

Maintainability
A
2 hrs
Test Coverage
import { ComponentProps, forwardRef } from 'react';
import { Link as ReactRouterLink } from 'react-router-dom';
import { ArrowOutward } from '@mui/icons-material';
import { Link as MuiLink, Typography } from '@mui/material';

interface LinkProps extends ComponentProps<typeof MuiLink> {
  to?: string | null | boolean;
  reloads?: boolean;
  opensInNewTab?: boolean;
  external?: boolean;
  disabled?: boolean;
}

type LinkRef = HTMLAnchorElement;

const Link = forwardRef<LinkRef, LinkProps>((props, ref): JSX.Element => {
  const {
    opensInNewTab,
    external,
    to: route,
    reloads,
    disabled,
    ...linkProps
  } = props;

  const children = (
    <>
      {props.children}
      {external && <ArrowOutward className="-mt-1" fontSize="inherit" />}
    </>
  );

  if (disabled || (!route && !props.href && !props.onClick))
    return (
      <Typography
        ref={ref}
        className={props.className}
        color={disabled ? 'text.disabled' : undefined}
        component="span"
        id={props.id}
        variant={props.variant ?? 'body2'}
      >
        {children}
      </Typography>
    );

  return (
    <MuiLink
      ref={ref}
      color="links"
      variant="body2"
      {...linkProps}
      className={`cursor-pointer ${props.className ?? ''}`}
      {...(opensInNewTab && {
        target: '_blank',
        rel: 'noopener noreferrer',
      })}
      {...(route && {
        component: ReactRouterLink,
        to: route,
        reloadDocument: reloads,
      })}
    >
      {children}
    </MuiLink>
  );
});

Link.displayName = 'Link';

export default Link;