optimizely-oui
Version:
Optimizely's Component Library.
162 lines (148 loc) • 4.19 kB
JavaScript
import React from "react";
import classNames from "classnames";
import PropTypes from "prop-types";
import { Resizable } from "re-resizable";
/**
* Sidebar
*
* Example:
*
* <Sidebar
* anchor='left'
* border={ true }
* docked={ true }
* isOpen={ false }
* width={ 100 }>
* sidebar content goes here
* </Sidebar>
*
*/
/**
*
* @param {Object} props - Properties passed to component
* @returns {ReactElement}
*/
const Sidebar = ({
anchor,
border,
boxShadow,
children,
className,
docked,
sticky,
isResizable,
isOpen,
width,
minWidth,
maxWidth,
testSection,
...props
}) => {
const baseClasses = classNames(
"background--white",
"flex",
"flex--1",
"flex--column",
"oui-sidebar",
"overflow--hidden"
);
const classes = classNames(baseClasses, {
"border--right": border && anchor === "left",
"border--left": border && anchor === "right",
"oui-shadow": boxShadow,
"position--relative": docked,
"position--absolute height--1-1": !docked && !sticky,
"position--fixed height--1-1": !docked && sticky,
"visibility--hidden": !isOpen,
}, className);
const anchorPosition = anchor === "left" ? -1 * width : 0;
const styles = {
width: isOpen ? width : 0,
maxWidth: isOpen ? width : 0,
[anchor]: isOpen ? 0 : anchorPosition,
};
const resizeEnabled = {
top: false,
right: anchor === "left" && isResizable,
bottom: false,
left: anchor === "right" && isResizable,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
};
const defaultSize = {
width: isOpen ? width : 0,
height: "auto",
};
if (isResizable && !docked) {
return (
<Resizable
defaultSize={defaultSize}
minWidth={minWidth}
maxWidth={maxWidth}
data-oui-component={true}
data-test-section={testSection}
className={classes}
style={styles}
enable={resizeEnabled}
>
{isOpen && children}
</Resizable>
);
}
return (
<div data-oui-component={true} data-test-section={testSection} className={classes} style={styles} {...props}>
{isOpen && children}
</div>
);
};
Sidebar.defaultProps = {
anchor: "right",
border: false,
docked: false,
sticky: false,
isResizable: false,
isOpen: false,
width: 0,
};
Sidebar.propTypes = {
/**
* Determines whether the sidebar should render on
* the left or right side of the page
*/
anchor: PropTypes.oneOf(["left", "right"]),
/** Determines if the sidebar should have a border */
border: PropTypes.bool,
/** Determines if the sidebar should have a box shadow */
boxShadow: PropTypes.bool,
/** Sidebar children */
children: PropTypes.node.isRequired,
/** CSS class names. */
className: PropTypes.string,
/**
* Docked sidebars push page-content to left or right when open.
* Un-docked sidebars render open over page-content (i.e postition absolute)
*/
docked: PropTypes.bool,
/**
* Sticky sidebars render open over page-content (i.e postition fixed).
* And maintain their position on the screen on scroll.
* This prop is only in effect when docked is false.
*/
isOpen: PropTypes.bool,
/** Determines if the sidebar is visible */
isResizable: PropTypes.bool,
/** When resizable, The maximum pixel width of the sidebar */
maxWidth: PropTypes.number,
/** When resizable, The minimum pixel width of the sidebar */
minWidth: PropTypes.number,
/** Determines if the sidebar is resizable.
Resizable only works for undocked sidebars. */
sticky: PropTypes.bool,
/** Hook for automated JavaScript tests */
testSection: PropTypes.string,
/** The pixel width of the sidebar */
width: PropTypes.number.isRequired,
};
export default Sidebar;