optimizely-oui
Version:
Optimizely's Component Library.
152 lines (138 loc) • 5.18 kB
JavaScript
import classNames from "classnames";
import Icon from "react-oui-icons";
import PropTypes from "prop-types";
import React from "react";
import Link from "../../Link";
import Poptip from "../../Poptip";
const LINK = "link";
const PUSH_STATE = "pushstate";
const BUTTON = "button";
// Should have a main component on its own.
class IconLink extends React.PureComponent {
static propTypes = {
/* Boolean, whether an external icon should show */
hasExternalIcon: PropTypes.bool,
/* Boolean, Should show a separator line before this link */
hasSeparator: PropTypes.bool,
/* Navigates to this URL when clicked */
href: PropTypes.string,
/* String, name of Icon */
iconName: PropTypes.string.isRequired,
/* Boolean, whether the link is highlighted
* blue as the current active nav link */
isActive: PropTypes.bool,
/* Boolean, whether navbar is open or closed */
isOpen: PropTypes.bool,
/* Boolean, whether link is primary or secondary */
isSecondaryLink: PropTypes.bool,
/* String or Node, description of url */
linkLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
/* Function called when IconLink is clicked */
onClick: PropTypes.func,
/* String, name of test data section */
testSection: PropTypes.string.isRequired,
/* IconLink can be one of these types
* LINK
* PUSH_STATE
* BUTTON */
type: PropTypes.oneOf([LINK, PUSH_STATE, BUTTON]),
};
static defaultProps = {
hasSeparator: false,
href: "",
isActive: false,
isOpen: true,
isSecondaryLink: false,
hasExternalIcon: false,
onClick: () => null,
type: LINK,
};
renderNavLink = () => {
const { isActive, iconName, isOpen, isSecondaryLink, hasSeparator, hasExternalIcon, linkLabel } = this.props;
const iconSize = isSecondaryLink ? "medium" : "large";
return (
<React.Fragment>
{hasSeparator && <hr className="oui-rule push-double--sides" />}
<Poptip content={linkLabel} disable={isOpen} isAnimated={false} position="right">
<div
className={classNames("root-nav__link", {
"is-active": isActive,
"root-nav__link--primary": !isSecondaryLink,
"root-nav__link--secondary": isSecondaryLink,
"has-external-icon": hasExternalIcon,
})}
>
<div className="flex">
<Icon name={iconName} size={iconSize} />
</div>
<div className={classNames("root-nav__link__text", " truncate", { "root-nav-fader": !isOpen })}>
{linkLabel}
</div>
{isOpen && hasExternalIcon && (
<div className="flex anchor--right root-nav__link-external-icon">
<Icon name={"external"} size={"small"} />
</div>
)}
</div>
</Poptip>
</React.Fragment>
);
};
onAppRouteLinkClick = event => {
const { href, onClick } = this.props;
return onClick(href, event);
};
renderAppRouteLink = () => {
const { testSection, href } = this.props;
return (
<Link
style="reverse"
href={href}
onClick={this.onAppRouteLinkClick}
testSection={`${testSection}-internal-link`}
>
{this.renderNavLink()}
</Link>
);
};
renderExternalLink = () => {
const { testSection, href } = this.props;
return (
<Link href={href} style="reverse" testSection={`${testSection}-external-link`}>
{this.renderNavLink()}
</Link>
);
};
renderButton = () => {
const { testSection, onClick } = this.props;
return (
<Link onClick={onClick} style="reverse" testSection={`${testSection}-button`}>
{this.renderNavLink()}
</Link>
);
};
render() {
const { testSection, type } = this.props;
let linkToRender;
switch (type) {
case PUSH_STATE:
linkToRender = this.renderAppRouteLink();
break;
case LINK:
linkToRender = this.renderExternalLink();
break;
case BUTTON:
linkToRender = this.renderButton();
break;
default:
// Should never reach here
linkToRender = null;
}
return (
<li className="display--inline-block" data-test-section={testSection}>
{linkToRender}
</li>
);
}
}
export default IconLink;