@salesforce/design-system-react
Version:
Salesforce Lightning Design System for React
141 lines (124 loc) • 4.02 kB
JSX
/* Copyright (c) 2015-present, salesforce.com, inc. All rights reserved */
/* Licensed under BSD 3-Clause - see LICENSE.txt or git.io/sfdc-license */
// Implements the [Vertical Navigation design pattern](https://lightningdesignsystem.com/components/vertical-navigation/) in React.
// Based on SLDS v2.2.1
import React from 'react';
import PropTypes from 'prop-types';
// ### classNames
// [github.com/JedWatson/classnames](https://github.com/JedWatson/classnames)
// This project uses `classnames`, 'a simple javascript utility for conditionally
// joining classNames together.'
import classNames from 'classnames';
// ### shortid
// [npmjs.com/package/shortid](https://www.npmjs.com/package/shortid)
// shortid is a short, non-sequential, url-friendly, unique id generator
import shortid from 'shortid';
import { VERTICAL_NAVIGATION } from '../../utilities/constants';
// Child components
import Item from './private/item';
/**
* Vertical Navigation represents a list of links that either take the user to another page or parts of the page the user is in.
*/
class VerticalNavigation extends React.Component {
static displayName = VERTICAL_NAVIGATION;
static propTypes = {
/**
* HTML id for component. _Tested with snapshot testing._
*/
id: PropTypes.string,
/**
* CSS class names to be added to the container element. _Tested with snapshot testing._
*/
className: PropTypes.oneOfType([
PropTypes.array,
PropTypes.object,
PropTypes.string,
]),
/**
* Array of categories. The required shape is: `{id: string, label: string, items: array}`. The required shape of an item is `{id: string, label: string, url: string}`. All item ids are expected to be unique. _Tested with snapshot testing._
*/
categories: PropTypes.array,
/**
* The ID of the item that is currently selected. Defaults to the ID of the first item. _Tested with Mocha framework._
*/
selectedId: PropTypes.string,
/**
* Triggered when the selection changes. It receives an event and an item object in the shape: `event, {item: [object] }`. _Tested with Mocha framework._
*/
onSelect: PropTypes.func,
/**
* Determines component style:
* * Use `shade` when the component is placed on an existing background that is not lightly colored.
* _Tested with snapshot testing._
*/
variant: PropTypes.oneOf(['default', 'shade']),
};
static defaultProps = {
variant: 'default',
};
componentWillMount() {
this.generatedId = shortid.generate();
}
getId = () => this.props.id || this.generatedId;
getVariant = () => (this.props.variant === 'shade' ? 'shade' : 'default');
getSelectedId = () => {
const categories = this.props.categories;
let selectedId;
if (this.props.selectedId) {
selectedId = this.props.selectedId;
} else if (
categories.length > 0 &&
categories[0].items &&
categories[0].items.length > 0
) {
selectedId = categories[0].items[0].id;
}
return selectedId;
};
render() {
const rootId = this.getId();
const variant = this.getVariant();
return (
<nav
id={rootId}
className={classNames(
'slds-nav-vertical',
{
'slds-nav-vertical_shade': variant === 'shade',
},
this.props.className
)}
>
{this.props.categories.map((category) => {
const categoryId = `${rootId}-${category.id}`;
const selectedId = this.getSelectedId();
return (
<div
key={`${categoryId}-header`}
className="slds-nav-vertical__section"
>
<h2
id={categoryId}
className="slds-nav-vertical__title slds-text-title_caps"
>
{category.label}
</h2>
<ul key={categoryId}>
{category.items.map((item) => (
<Item
key={item.id}
item={item}
isSelected={item.id === selectedId}
categoryId={categoryId}
onSelect={this.props.onSelect}
/>
))}
</ul>
</div>
);
})}
</nav>
);
}
}
export default VerticalNavigation;