diff --git a/src/Nav/Nav.css b/src/Nav/Nav.css
index cfc6bdec..6f1dc9e7 100644
--- a/src/Nav/Nav.css
+++ b/src/Nav/Nav.css
@@ -6,6 +6,16 @@
height: auto;
}
+.horizontal {
+ display: flex;
+ flex-direction: row;
+}
+
.nav a {
text-decoration: none;
+}
+
+.horizontal.nav .nav li:not(:first-child) {
+ position: absolute;
+ z-index: 9998;
}
\ No newline at end of file
diff --git a/src/Nav/Nav.js b/src/Nav/Nav.js
index af29de9f..5af3949e 100644
--- a/src/Nav/Nav.js
+++ b/src/Nav/Nav.js
@@ -10,8 +10,11 @@ export class Nav extends React.Component {
super(props);
this.state = {
"activeIndex": props.activeIndex, // The index of selected menu item.
- "collapsed": props.collapsed // Whether or not sub-nav menu collapsed.
+ "collapsed": props.collapsed, // Whether or not sub-nav menu collapsed.
+ "subNavItemHeight": 0, // the NavItem's height in subNav
+ "subNavItemMaxWidth": 0
};
+ this.subNavItemRef = React.createRef();
}
UNSAFE_componentWillReceiveProps(nextProps) {
@@ -34,50 +37,130 @@ export class Nav extends React.Component {
}
};
- _buildNavByData = () => {
- const { className, data, ignoreActive, onClick, style } = this.props;
+ _setDimension = (height, width) => {
+ console.log("height", height);
+ console.log("width", width);
+ if (width > 0 && width > this.state.subNavItemMaxWidth) {
+ this.setState({
+ "subNavItemHeight": height,
+ "subNavItemMaxWidth": width
+ });
+ } else {
+ this.setState({
+ "subNavItemHeight": height
+ });
+ }
+ };
+
+ // use this ternary helper to avoid nested ternary in JSX
+ // not working for _buidNavByData
+ widthStyleTernaryHelper = (cond1, cond2, child, index, data) => {
+ let tempIndex = index;
+ if (cond1 && cond2) {
+ if (data) {
+ tempIndex += 2;
+ }
+ return {
+ "transform": `translateY(${(tempIndex - 1) *
+ this.state.subNavItemHeight}px)`,
+ "width": `${this.state.subNavItemMaxWidth}px`,
+ ...child.style
+ };
+ } else if (cond1 && !cond2) {
+ if (data) {
+ tempIndex += 2;
+ }
+ return {
+ "transform": `translateY(${(tempIndex - 1) *
+ this.state.subNavItemHeight}px)`,
+ ...child.style
+ };
+ } else {
+ return child.style;
+ }
+ };
+
+ _buildNavByData = data => {
+ const {
+ className,
+ ignoreActive,
+ onClick,
+ style,
+ subNav,
+ horizontal
+ } = this.props;
return (
);
@@ -90,15 +173,21 @@ export class Nav extends React.Component {
data,
ignoreActive,
style,
- subNav
+ subNav,
+ horizontal
} = this.props;
let styleName;
if (data) {
- return this._buildNavByData();
+ return this._buildNavByData(data);
}
// Avoid to append styleName to ul if rendering from json data.
styleName =
- className.indexOf("ra_Nav__nav") === -1 ? { "styleName": cx("nav") } : {};
+ className.indexOf("ra_Nav__nav") === -1
+ ? horizontal && typeof subNav === "undefined"
+ ? { "styleName": cx("nav", "horizontal") }
+ : { "styleName": cx("nav") }
+ : {};
+
return (
{React.Children.map(children, (child, index) => {
@@ -116,7 +205,8 @@ export class Nav extends React.Component {
"activeIndex": this.state.activeIndex,
"subNav": true,
"onClick": this._handleClick,
- "ignoreActive": ignoreActive
+ "ignoreActive": ignoreActive,
+ horizontal
});
}
let isParent = subNav && index === 0;
@@ -126,7 +216,20 @@ export class Nav extends React.Component {
"parent": isParent,
"collapsed": this.state.collapsed,
active,
- "onClick": isParent ? this._handleCollapse : this._handleClick
+ "onClick": isParent ? this._handleCollapse : this._handleClick,
+ horizontal,
+ "ref": horizontal && !isParent && subNav ? this.subNavItemRef : null,
+ "dimension": this._setDimension,
+ "style": this.widthStyleTernaryHelper(
+ horizontal && !isParent && subNav,
+ horizontal &&
+ !isParent &&
+ subNav &&
+ this.state.subNavItemMaxWidth > 0,
+ child.props,
+ index,
+ false
+ )
});
})}
@@ -151,21 +254,26 @@ Nav.propTypes = {
"data": PropTypes.array,
/** Set to true if you intend to set an active style externally. */
"ignoreActive": PropTypes.bool,
- /** Function that will be executed when onClick event occurs. */
+ /** Function that will be executed when onClick event occurs.
+ * @ignore
+ * */
"onClick": PropTypes.func,
/** Pass inline styling here. */
"style": PropTypes.object,
/** Set true If is a sub-Nav container, not a public prop.
* @ignore
*/
- "subNav": PropTypes.bool
+ "subNav": PropTypes.bool,
+ /** Define whether the Nav is vertical or horizontal, Nav is vertical by default */
+ "horizontal": PropTypes.bool
};
Nav.defaultProps = {
"className": "",
"collapsed": false,
"data": null,
- "ignoreActive": false
+ "ignoreActive": false,
+ "horizontal": false
};
export default CSSModules(Nav, styles, { "allowMultiple": true });
diff --git a/src/Nav/README.md b/src/Nav/README.md
index 7538e7ca..21c00975 100644
--- a/src/Nav/README.md
+++ b/src/Nav/README.md
@@ -1,4 +1,4 @@
-Basic Nav component:
+Basic Vertical Nav component:
Home
Catalog
@@ -6,7 +6,31 @@ Basic Nav component:
Administration
Support
-
+
+Basic Horizontal Nav component:
+
+ Home
+ Catalog
+ Customer Service
+ Administration
+ Support
+
+
+Horizontal Nav with sub-NavItems:
+
+ Home
+ Catalog
+ Customer Service
+
+ Reports
+ Create a Report
+ Edit a Report
+ Delete a Report
+
+ Administration
+ Support
+
+
Nav with sub-NavItems:
Home
@@ -102,7 +126,7 @@ Build Nav Menu via data attribute:
"navKey": 3,
"title": "Reports",
"collapsed": true,
- "subNav": [
+ "subNavArray": [
{
"navKey": 3.1,
"title": "Create a Report"
@@ -120,7 +144,7 @@ Build Nav Menu via data attribute:
];
_handleClick = (selectedIndex) => console.log('Item ' + selectedIndex + ' has been selected.');
-
+
Nav component with a routing library. Use the `as` property to define the component name (e.g. `Link` from react-router) and pass any router specific props to your NavItem component:
@@ -146,7 +170,7 @@ Nav component with React-Router using data instead of children:
"navKey": 0,
"title": "Form Components",
"collapsed": true,
- "subNav": [
+ "subNavArray": [
{
"navKey": 0.1,
"to": "button",
diff --git a/src/NavItem/NavItem.css b/src/NavItem/NavItem.css
index a23a9fbd..ff09d099 100644
--- a/src/NavItem/NavItem.css
+++ b/src/NavItem/NavItem.css
@@ -3,7 +3,7 @@
.base {
border-style: none;
- border-top: 1px solid #eee !important; /* Important designation needed to overwrite Button styling in prod build */
+ /*border-top: 1px solid #eee !important; !* Important designation needed to overwrite Button styling in prod build *!*/
}
.subNav {
@@ -11,28 +11,48 @@
transition: height .3s ease-in-out;
}
-.subNav.collapsed {
+.subNav.collapsed.initial {
+ height: auto;
+}
+
+.subNav.collapsed.initial button {
+ display: list-item;
+ visibility: hidden;
+}
+
+.subNav.collapsed.normal {
height: 0;
}
+.subNav.collapsed.normal button {
+ display: none;
+ visibility: visible;
+ transition: height .3s ease-in-out;
+}
+
.navItem button {
width: 100%;
border-color: var(--silver);
border-left: solid 5px transparent;
+ color: var(--dark-gray);
position: relative;
display: block;
padding: 10px 15px;
- text-align: left;
- color: var(--dark-gray);
background-color: var(--white);
+ text-align: left;
}
-.subNav button {
- padding-left: 38px;
+.horizontal button {
+ border-top: solid 5px transparent;
+ border-left: none;
}
-.subNav.collapsed button {
- display: none;
+.horizontal ~ li > button {
+ padding-left: 10px !important;
+}
+
+.subNav button {
+ padding-left: 38px;
}
.navItem button:hover {
@@ -50,18 +70,29 @@
color: var(--blue);
}
+.horizontal.active > button {
+ border-top: solid 5px var(--blue) !important;
+}
+
.caret::before {
content: "";
border: solid var(--blue);
border-width: 0 2px 2px 0;
display: inline-block;
padding: 5px;
- transform: rotate(45deg);
position: absolute;
top: -5px;
left: 5px;
}
+.caretHorizontal::before {
+ transform: rotate(45deg);
+}
+
+.caretVertical::before {
+ transform: rotate(45deg);
+}
+
.caret {
position: relative;
width: 18px;
@@ -77,6 +108,6 @@
}
-.collapsed .caret {
+.collapsed .caretVertical {
transform: rotate(90deg);
}
\ No newline at end of file
diff --git a/src/NavItem/NavItem.js b/src/NavItem/NavItem.js
index 7eccf38f..f32dd13a 100644
--- a/src/NavItem/NavItem.js
+++ b/src/NavItem/NavItem.js
@@ -6,6 +6,34 @@ import CSSModules from "react-css-modules";
import styles from "./NavItem.css";
export class NavItem extends React.Component {
+ constructor(props) {
+ super(props);
+ this.liRef = React.createRef();
+ this.state = {
+ "initial": true
+ };
+ }
+
+ componentDidMount() {
+ if (this.liRef.current && this.props.horizontal && this.props.subNav) {
+ const div = window.getComputedStyle(this.liRef.current);
+ const navItemHeight = parseInt(
+ div
+ .getPropertyValue("height")
+ .substring(0, div.getPropertyValue("height").length - 2)
+ );
+ const navItemWidth = parseInt(
+ div
+ .getPropertyValue("width")
+ .substring(0, div.getPropertyValue("width").length - 2)
+ );
+ this.props.dimension(navItemHeight, navItemWidth);
+ }
+ this.setState({
+ "initial": false
+ });
+ }
+
_handleClick = event => {
if (this.props.onClick) {
this.props.onClick(this.props.navKey, event);
@@ -24,30 +52,91 @@ export class NavItem extends React.Component {
subNav,
collapsed,
children,
+ horizontal,
...others
} = this.props;
+ const styleNameHelper = (horizontalCond, subNavCond, initialCond) => {
+ if (!horizontalCond || horizontalCond && subNavCond) {
+ if (initialCond) {
+ return cx("navItem", "initial", {
+ active,
+ disabled,
+ collapsed,
+ subNav
+ });
+ } else {
+ return cx("navItem", "normal", {
+ active,
+ disabled,
+ collapsed,
+ subNav
+ });
+ }
+ } else {
+ if (initialCond) {
+ return cx("navItem", "initial", "horizontal", {
+ active,
+ disabled,
+ collapsed,
+ subNav
+ });
+ } else {
+ return cx("navItem", "normal", "horizontal", {
+ active,
+ disabled,
+ collapsed,
+ subNav
+ });
+ }
+ }
+ };
+
const button =
;
+
const LinkElement = this.props.as;
if (typeof as !== "undefined" && !disabled) {
return (
{button}
@@ -58,9 +147,22 @@ export class NavItem extends React.Component {
return (
{button}
@@ -112,11 +214,16 @@ NavItem.propTypes = {
/** callback for Nav Component
* @ignore
*/
- "onClick": PropTypes.func
+ "onClick": PropTypes.func,
+ /** Define whether the NavItem is vertical or horizontal, NavItem is vertical by default */
+ "horizontal": PropTypes.bool,
+ /** callback for Nav Component for the height and width of the NavItem */
+ "dimension": PropTypes.func
};
NavItem.defaultProps = {
- "className": ""
+ "className": "",
+ "horizontal": false
};
export default CSSModules(NavItem, styles, { "allowMultiple": true });
diff --git a/src/styles/layout.css b/src/styles/layout.css
index 04fb7d20..a27c24a7 100755
--- a/src/styles/layout.css
+++ b/src/styles/layout.css
@@ -64,7 +64,7 @@
.pad-0 { padding: 0 }
-.pad-0-25 {padding: var(--space-0-25) };
+.pad-0-25 {padding: var(--space-0-25) }
.pad-v-0-25 {padding-top: var(--space-0-25); padding-bottom: var(--space-0-25) }
.pad-h-0-25 {padding-left: var(--space-0-25); padding-right: var(--space-0-25) }