From e1f42c47517cee898db90890bd668a9d7cdab74e Mon Sep 17 00:00:00 2001
From: Tore Brede <Tore.Brede@uib.no>
Date: Sat, 11 Sep 2021 14:58:38 +0200
Subject: [PATCH] GREG-41: Updating link component

---
 frontend/src/App.tsx                   |  11 +--
 frontend/src/components/link/index.tsx | 113 +++++++++++++++++++++----
 2 files changed, 103 insertions(+), 21 deletions(-)

diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 719320ed..fd3e451f 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -72,11 +72,12 @@ const App = () => {
             API reachable? {apiHealth}
           </p>
 
-          <Link to='test' external={false}>Test</Link>
-          <Link to='test2' external={true}>Test2</Link>
-        </header>
-      </div>
-    </Suspense>
+        <Link to='test@example.org' mail={true}>Mail link</Link>
+        <Link to='test4' external={false} underline={true} noExternalIcon={true}>Internal link</Link>
+        <Link to='test6' external={true} underline={false} noUnderline={true}>External link</Link>
+        <Link to='test5' external={false} noUnderline={true}>Another internal link</Link>
+      </header>
+    </div>
   )
 }
 
diff --git a/frontend/src/components/link/index.tsx b/frontend/src/components/link/index.tsx
index 65a9e8e0..139bd527 100644
--- a/frontend/src/components/link/index.tsx
+++ b/frontend/src/components/link/index.tsx
@@ -1,25 +1,106 @@
-import styled from 'styled-components/macro'
+import styled, {css, DefaultTheme} from 'styled-components/macro'
 
 
-interface LinkProps {
-  children?: React.ReactNode
-  external?: boolean
-  to?: string
+interface IStyledLink {
+    theme: DefaultTheme
+    external?: boolean
+    underline?: boolean
+    marginRight?: boolean
+    inheritColor?: boolean
+    noUnderline?: boolean
 }
 
-const StyledLink = styled.a<LinkProps>`
-  background: ${(props) => props.external ? 'green' : 'red'};
+
+interface ILink {
+    to: string
+    external?: boolean
+    children?: React.ReactNode
+    marginRight?: boolean
+    noExternalIcon?: boolean
+    mail?: boolean
+    inheritColor?: boolean
+    underline?: boolean
+    noUnderline?: boolean
+}
+
+const externalLinkIcon = (
+    <svg width="15.3" height="12.6" viewBox="0 0 17 14">
+        <g fill="#0F748D" fillRule="evenodd">
+            <path
+                d="M13.044 8.157h-.607a.3.3 0 0 0-.218.082.276.276 0 0 0-.085.208v2.907c0 .4-.148.742-.445 1.027a1.493 1.493 0 0 1-1.072.427H2.73c-.417 0-.774-.143-1.071-.427a1.371 1.371 0 0 1-.446-1.027V3.796c0-.4.149-.742.446-1.026a1.493 1.493 0 0 1 1.071-.427h6.674a.302.302 0 0 0 .218-.082.277.277 0 0 0 .085-.209v-.581a.277.277 0 0 0-.085-.21.302.302 0 0 0-.218-.08H2.73c-.752 0-1.395.255-1.93.767-.533.511-.8 1.128-.8 1.848v7.558c0 .721.267 1.337.801 1.849a2.689 2.689 0 0 0 1.93.768h7.886c.752 0 1.395-.256 1.93-.768.534-.512.8-1.128.8-1.849V8.448a.276.276 0 0 0-.085-.21.302.302 0 0 0-.218-.081z"/>
+            <path
+                d="M16.807.19a.596.596 0 0 0-.426-.173h-4.854a.596.596 0 0 0-.426.173.548.548 0 0 0-.18.409c0 .157.06.294.18.409l1.668 1.598-6.18 5.923a.281.281 0 0 0-.095.21c0 .078.031.148.094.208L7.67 9.983a.306.306 0 0 0 .436 0l6.18-5.923 1.67 1.599c.12.115.262.172.426.172a.596.596 0 0 0 .426-.172.547.547 0 0 0 .18-.409V.599a.548.548 0 0 0-.18-.409z"/>
+        </g>
+    </svg>
+);
+
+const ExternalIcon = styled.span`
+  margin-left: 1.2rem;
+  position: relative;
+  top: 1px;
+  zIndex: -1;
+`
+
+const baseInputStyles = css<IStyledLink>`
+  display: inline-flex;
+  align-items: center;
+
+  color: ${props => props.external ? props.theme.linkExternalColor : props.theme.linkInternalColor};
+
+  ${props => props.marginRight ? "margin-right: 3rem;" : ""}
+  ${props => props.inheritColor ? "color: inherit;" : ""}
+  ${props => props.underline ? "text-decoration: underline;" : ""}
+  ${props => props.noUnderline ? ":hover { text-decoration: none };" : ""}
 `
 
-export function Link(props: LinkProps) {
+const StyledLink = styled.a<IStyledLink>`
+  ${baseInputStyles}
+`
+// TODO Put back when routes are set up
+// const StyledRouterLink = styled(RouterLink)`
+//   ${baseInputStyles};
+// `
+
+export default function Link(props: ILink) {
+    const {children, external, to, noExternalIcon, mail} = props
+
+    if (mail) {
+        return (
+            <StyledLink href={`mailto:${to}`} {...props}>
+                {children}
+            </StyledLink>
+        );
+    }
+
+    if (external) {
+        const urlRegex = /^((http|https):\/\/)/;
+        const href = urlRegex.test(to) ? to : `//${to}`;
+
+        return (
+            <StyledLink
+                href={href}
+                target="_blank"
+                rel="noopener noreferrer"
+                {...props}
+            >
+                {children}
+                {!noExternalIcon && (
+                    <ExternalIcon>{externalLinkIcon}</ExternalIcon>
+                )}
+            </StyledLink>
+        );
+    }
+
+    // TODO Use StyledRouterLink for internal links when routes are set up
+    // return (
+    //     <StyledRouterLink {...props}>
+    //         {children}
+    //     </StyledRouterLink>
+    // )
 
-  if (props.external) {
     return (
-      <StyledLink href={props.to} {...props} />
+        <StyledLink {...props}>
+            {children}
+        </StyledLink>
     )
-  }
-
-  return (
-    <StyledLink href={props.to} {...props} />
-  )
-}
\ No newline at end of file
+}
-- 
GitLab