aboutsummaryrefslogtreecommitdiffstats
path: root/packages/react-shared/src/components/link.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/react-shared/src/components/link.tsx')
-rw-r--r--packages/react-shared/src/components/link.tsx100
1 files changed, 100 insertions, 0 deletions
diff --git a/packages/react-shared/src/components/link.tsx b/packages/react-shared/src/components/link.tsx
new file mode 100644
index 000000000..7425b9365
--- /dev/null
+++ b/packages/react-shared/src/components/link.tsx
@@ -0,0 +1,100 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+import { Link as ReactRounterLink } from 'react-router-dom';
+import { Link as ScrollLink } from 'react-scroll';
+
+import { LinkType } from '../types';
+import { constants } from '../utils/constants';
+
+export interface LinkProps {
+ to: string;
+ type?: LinkType;
+ shouldOpenInNewTab?: boolean;
+ style?: React.CSSProperties;
+ className?: string;
+ onMouseOver?: (event: React.MouseEvent<HTMLElement>) => void;
+ onMouseLeave?: (event: React.MouseEvent<HTMLElement>) => void;
+ onMouseEnter?: (event: React.MouseEvent<HTMLElement>) => void;
+ containerId?: string;
+}
+
+/**
+ * A generic link component which let's the developer render internal & external links, and their associated
+ * behaviors with a single link component. Many times we want a menu including both internal & external links
+ * and this abstracts away the differences of rendering both types of links.
+ */
+export const Link: React.StatelessComponent<LinkProps> = ({
+ style,
+ className,
+ type,
+ to,
+ shouldOpenInNewTab,
+ children,
+ onMouseOver,
+ onMouseLeave,
+ onMouseEnter,
+ containerId,
+}) => {
+ const styleWithDefault = {
+ textDecoration: 'none',
+ ...style,
+ };
+
+ switch (type) {
+ case LinkType.External:
+ return (
+ <a
+ target={shouldOpenInNewTab ? '_blank' : ''}
+ className={className}
+ style={styleWithDefault}
+ href={to}
+ onMouseOver={onMouseOver}
+ onMouseEnter={onMouseEnter}
+ onMouseLeave={onMouseLeave}
+ >
+ {children}
+ </a>
+ );
+ case LinkType.ReactRoute:
+ return (
+ <ReactRounterLink
+ to={to}
+ className={className}
+ style={styleWithDefault}
+ target={shouldOpenInNewTab ? '_blank' : ''}
+ onMouseOver={onMouseOver}
+ onMouseEnter={onMouseEnter}
+ onMouseLeave={onMouseLeave}
+ >
+ {children}
+ </ReactRounterLink>
+ );
+ case LinkType.ReactScroll:
+ return (
+ <ScrollLink
+ to={to}
+ offset={0}
+ hashSpy={true}
+ duration={constants.DOCS_SCROLL_DURATION_MS}
+ containerId={containerId}
+ >
+ {children}
+ </ScrollLink>
+ );
+ default:
+ throw new Error(`Unrecognized LinkType: ${type}`);
+ }
+};
+
+Link.defaultProps = {
+ type: LinkType.ReactRoute,
+ shouldOpenInNewTab: false,
+ style: {},
+ className: '',
+ onMouseOver: _.noop.bind(_),
+ onMouseLeave: _.noop.bind(_),
+ onMouseEnter: _.noop.bind(_),
+ containerId: constants.DOCS_CONTAINER_ID,
+};
+
+Link.displayName = 'Link';