orcs-design-system
Version:
TeamForm's Design System, aka: ORCS
203 lines • 7.92 kB
JavaScript
import React, { useMemo } from "react";
import styled, { css as styledCss } from "styled-components";
import { css } from "@styled-system/css";
import { themeGet } from "@styled-system/theme-get";
import PropTypes from "prop-types";
import Icon from "../Icon";
import Popover from "../Popover";
import { BREAKPOINTS } from "./constants/sideNav";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const sharedNavItemStyles = styledCss(["cursor:pointer;padding:", ";text-decoration:none;border-radius:", ";width:100%;position:relative;border:none;path{transition:", ";fill:", ";}font-family:", ";display:flex;align-items:center;justify-content:center;transition:", ";background-color:transparent;font-size:1.4rem;font-weight:", ";&:hover,&:focus{color:", ";path{fill:", ";}}@media screen and (max-width:", "px){width:auto;max-height:30px;height:30px;}&:focus{outline:0;color:", ";path{fill:", ";}}"], themeGet("space.s"), themeGet("radii.2"), themeGet("transition.transitionDefault"), themeGet("colors.greyDarker"), themeGet("fonts.main"), themeGet("transition.transitionDefault"), themeGet("fontWeights.1"), themeGet("colors.primary"), themeGet("colors.primary"), BREAKPOINTS.SMALL_SCREEN, themeGet("colors.primary"), themeGet("colors.primary"));
const expandedNavItemStyles = props => styledCss(["justify-content:flex-start;gap:", ";.nav-item-text{font-size:", ";line-height:1;font-weight:", ";color:", ";white-space:nowrap;text-overflow:ellipsis;}&:hover .nav-item-text,&:focus .nav-item-text{color:", ";}"], themeGet("space.s"), themeGet("fontSizes.1"), themeGet("fontWeights.1"), props.active ? themeGet("colors.greyDarkest") : themeGet("colors.greyDarker"), props.active ? themeGet("colors.greyDarkest") : themeGet("colors.primary"));
const variantActiveStyles = {
expandableItem: props => styledCss(["color:", ";path{fill:", ";}:after{height:100%;position:absolute;right:0;transform:", ";content:\"\";border-right:3px solid ", ";z-index:5;}&:hover .nav-item-text,&:focus .nav-item-text{color:", ";}@media screen and (max-width:", "px){:after{border-top:3px solid ", ";border-right:none;transform:translateY(-10px);right:auto;width:100%;}}"], themeGet("colors.greyDarkest"), themeGet("colors.greyDarkest"), props.isExpanded ? "translateX(9px)" : "translateX(8px)", themeGet("colors.primary"), themeGet("colors.primary"), BREAKPOINTS.SMALL_SCREEN, themeGet("colors.primary")),
default: styledCss(["background-color:", ";path{fill:", ";}&:hover,&:focus{path{fill:", ";}}&:focus{path{fill:", ";}}"], themeGet("colors.primaryLightest"), themeGet("colors.greyDarkest"), themeGet("colors.greyDarkest"), themeGet("colors.greyDarkest"))
};
const getActiveStyles = props => {
if (!props.active) return "";
if (props["aria-expanded"]) {
return variantActiveStyles.expandableItem(props);
}
return variantActiveStyles.default;
};
const SideNavItemLink = styled.div.withConfig({
displayName: "NavItem__SideNavItemLink",
componentId: "sc-1qz1q0h-0"
})(["& > a{", " ", " ", "}"], sharedNavItemStyles, props => props.isExpanded ? expandedNavItemStyles(props) : "", getActiveStyles);
const SideNavItem = styled("button").withConfig({
displayName: "NavItem__SideNavItem",
componentId: "sc-1qz1q0h-1"
})(["", " ", " ", ""], sharedNavItemStyles, props => props.isExpanded ? expandedNavItemStyles(props) : "", getActiveStyles);
const BadgeNumber = styled("div").withConfig({
displayName: "NavItem__BadgeNumber",
componentId: "sc-1qz1q0h-2"
})(props => css({
position: "absolute",
height: "16px",
width: "16px",
bg: themeGet("colors.danger")(props),
fontSize: "1rem",
fontWeight: themeGet("fontWeights.2")(props),
color: themeGet("colors.white")(props),
borderRadius: "50%",
top: props.isExpanded ? "8px" : "0",
right: "0",
display: "flex",
alignItems: "center",
justifyContent: "center"
}));
const BadgeDot = styled("div").withConfig({
displayName: "NavItem__BadgeDot",
componentId: "sc-1qz1q0h-3"
})(props => css({
position: "absolute",
height: "8px",
width: "8px",
bg: themeGet("colors.primary")(props),
borderRadius: "50%",
top: props.isExpanded ? "12px" : "2px",
right: "0"
}));
const SideNavItemWrapper = styled.div.withConfig({
displayName: "NavItem__SideNavItemWrapper",
componentId: "sc-1qz1q0h-4"
})(props => css({
"&:nth-child(1 of .bottom-aligned) ": {
marginTop: props.bottomAligned && "auto"
}
}));
const NavItem = _ref => {
let {
item,
Component,
isActive,
handleItemClick,
navItemRefs,
isSmallScreen,
isExpanded
} = _ref;
const renderedNavItem = useMemo(() => {
const accessibilityProps = {
...(item.actionType === "component" && {
"aria-expanded": isActive ? "true" : "false"
}),
"aria-label": item.name
};
if (item.actionType === "link") {
return /*#__PURE__*/_jsx(SideNavItemLink, {
active: isActive,
bottomAligned: item.bottomAligned,
isExpanded: isExpanded,
onClick: () => handleItemClick(item),
ref: el => navItemRefs.current[item.index] = el,
children: /*#__PURE__*/_jsxs(Component, {
item: item,
children: [/*#__PURE__*/_jsx(Icon, {
icon: ["far", item.iconName]
}), isExpanded && !isSmallScreen && /*#__PURE__*/_jsx("span", {
className: "nav-item-text",
children: item.name
})]
})
}, item.index);
} else {
return /*#__PURE__*/_jsxs(SideNavItem, {
active: isActive,
onClick: () => handleItemClick(item),
bottomAligned: item.bottomAligned,
isExpanded: isExpanded,
...accessibilityProps,
ref: el => navItemRefs.current[item.index] = el,
children: [item.badgeNumber && /*#__PURE__*/_jsx(BadgeNumber, {
isExpanded: isExpanded,
children: item.badgeNumber
}), item.badgeDot && /*#__PURE__*/_jsx(BadgeDot, {
isExpanded: isExpanded
}), /*#__PURE__*/_jsx(Icon, {
icon: ["far", item.iconName]
}), isExpanded && !isSmallScreen && /*#__PURE__*/_jsx("span", {
className: "nav-item-text",
children: item.name
})]
}, item.index);
}
}, [item, isActive, isExpanded, isSmallScreen, handleItemClick, navItemRefs]);
return isSmallScreen ? /*#__PURE__*/_jsx(Popover, {
text: item.name,
direction: "top",
textAlign: "center",
width: "fit-content",
tabIndex: "-1",
children: renderedNavItem
}) : /*#__PURE__*/_jsx(SideNavItemWrapper, {
className: item.bottomAligned && "bottom-aligned",
bottomAligned: item.bottomAligned,
children: renderedNavItem
});
};
NavItem.propTypes = {
item: PropTypes.object,
Component: PropTypes.elementType,
isActive: PropTypes.bool,
handleItemClick: PropTypes.func,
navItemRefs: PropTypes.object,
isSmallScreen: PropTypes.bool,
isExpanded: PropTypes.bool
};
NavItem.__docgenInfo = {
"description": "",
"methods": [],
"displayName": "NavItem",
"props": {
"item": {
"description": "",
"type": {
"name": "object"
},
"required": false
},
"Component": {
"description": "",
"type": {
"name": "elementType"
},
"required": false
},
"isActive": {
"description": "",
"type": {
"name": "bool"
},
"required": false
},
"handleItemClick": {
"description": "",
"type": {
"name": "func"
},
"required": false
},
"navItemRefs": {
"description": "",
"type": {
"name": "object"
},
"required": false
},
"isSmallScreen": {
"description": "",
"type": {
"name": "bool"
},
"required": false
},
"isExpanded": {
"description": "",
"type": {
"name": "bool"
},
"required": false
}
}
};
export default NavItem;