mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
feat: Sidebar overlay.
This commit is contained in:
@@ -145,9 +145,10 @@ export default class MenuItem extends AbstractPureComponent2 {
|
||||
tagName = "a",
|
||||
dropdownType,
|
||||
caretIconSize = 16,
|
||||
hasSubmenu,
|
||||
...htmlProps
|
||||
} = this.props;
|
||||
const hasSubmenu = children != null;
|
||||
|
||||
|
||||
const intentClass = Classes.intentClass(intent);
|
||||
const anchorClasses = classNames(
|
||||
|
||||
@@ -8,6 +8,11 @@ import { MenuItemLabel } from 'components';
|
||||
import classNames from 'classnames';
|
||||
import SidebarOverlay from 'components/SidebarOverlay';
|
||||
|
||||
const DEFAULT_ITEM = {
|
||||
text: '',
|
||||
href: '',
|
||||
}
|
||||
|
||||
export default function SidebarMenu() {
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
@@ -17,18 +22,16 @@ export default function SidebarMenu() {
|
||||
|
||||
const menuItemsMapper = (list) => {
|
||||
return list.map((item, index) => {
|
||||
const children = Array.isArray(item.children)
|
||||
? menuItemsMapper(item.children)
|
||||
: null;
|
||||
const hasChildren = Array.isArray(item.children);
|
||||
|
||||
const matchPath = (pathname, path) => {
|
||||
return item.matchExact
|
||||
? pathname === path
|
||||
: pathname.indexOf(path) !== -1;
|
||||
};
|
||||
const isActive = item.children
|
||||
const isActive = (item.children
|
||||
? item.children.some((c) => matchPath(location.pathname, c.href))
|
||||
: item.href && matchPath(location.pathname, item.href);
|
||||
: item.href && matchPath(location.pathname, item.href)) || currentItem ===item;
|
||||
|
||||
const handleItemClick = () => {
|
||||
if (item.href) {
|
||||
@@ -69,28 +72,34 @@ export default function SidebarMenu() {
|
||||
text={item.text}
|
||||
label={maybeRenderLabel(item)}
|
||||
disabled={item.disabled}
|
||||
children={children}
|
||||
dropdownType={item.dropdownType || 'collapse'}
|
||||
caretIconSize={16}
|
||||
onClick={handleItemClick}
|
||||
callapseActive={!!isActive}
|
||||
itemClassName={classNames({
|
||||
'is-active': isActive,
|
||||
'has-icon': !children && item.icon,
|
||||
'has-icon': !hasChildren && item.icon,
|
||||
})}
|
||||
hasSubmenu={hasChildren}
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
const items = menuItemsMapper(sidebarMenuList);
|
||||
|
||||
const handleSidebarOverlayClose = () => {
|
||||
setIsOpen(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Menu className="sidebar-menu">{items}</Menu>{' '}
|
||||
|
||||
<SidebarOverlay
|
||||
isOpen={isOpen}
|
||||
label={currentItem?.text || ''}
|
||||
items={currentItem?.children || []}
|
||||
onClose={handleSidebarOverlayClose}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -2,24 +2,24 @@ import React from 'react';
|
||||
import { Overlay } from '@blueprintjs/core';
|
||||
import { Link } from 'react-router-dom';
|
||||
import SidebarOverlayContainer from './SidebarOverlayContainer';
|
||||
|
||||
interface ISidebarOverlayItem {
|
||||
text: string;
|
||||
href: string;
|
||||
divider?: boolean;
|
||||
label?: boolean
|
||||
label?: boolean;
|
||||
}
|
||||
|
||||
interface ISidebarOverlayProps {
|
||||
isOpen: boolean;
|
||||
items: ISidebarOverlayItem[];
|
||||
overlayProps: any;
|
||||
overlayContainerRef: any;
|
||||
label: string;
|
||||
onClose: Function;
|
||||
}
|
||||
|
||||
interface ISidebarOverlayItemProps {
|
||||
text: string;
|
||||
href: string;
|
||||
onLinkClick: Function;
|
||||
}
|
||||
|
||||
interface ISidebarOverlayItemDivider {
|
||||
@@ -28,16 +28,25 @@ interface ISidebarOverlayItemDivider {
|
||||
/**
|
||||
* Sidebar overlay item.
|
||||
*/
|
||||
function SidebarOverlayItem({ text, href }: ISidebarOverlayItemProps) {
|
||||
function SidebarOverlayItem({
|
||||
text,
|
||||
href,
|
||||
onLinkClick,
|
||||
}: ISidebarOverlayItemProps) {
|
||||
const handleLinkClick = () => {
|
||||
onLinkClick && onLinkClick();
|
||||
};
|
||||
return (
|
||||
<div className="sidebar-overlay__item">
|
||||
<Link to={href}>{text}</Link>
|
||||
<Link onClick={handleLinkClick} to={href}>
|
||||
{text}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface ISidebarOverlayItemLabel {
|
||||
text: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
function SidebarOverlayLabel({ text }: ISidebarOverlayItemLabel) {
|
||||
@@ -52,34 +61,75 @@ function SidebarOverlayDivider() {
|
||||
* Sidebar overlay component.
|
||||
*/
|
||||
export default function SidebarOverlay({
|
||||
isOpen = false,
|
||||
label,
|
||||
isOpen: controllerdIsOpen,
|
||||
onClose,
|
||||
items,
|
||||
}: ISidebarOverlayProps) {
|
||||
//
|
||||
if (!isOpen) {
|
||||
const [isEverOpened, setEverOpened] = React.useState(false);
|
||||
const [isOpen, setIsOpen] = React.useState(controllerdIsOpen);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (controllerdIsOpen && isOpen !== controllerdIsOpen) {
|
||||
setIsOpen(controllerdIsOpen);
|
||||
}
|
||||
}, [controllerdIsOpen, setIsOpen, isOpen]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isOpen && !isEverOpened) {
|
||||
setEverOpened(true);
|
||||
}
|
||||
}, [isEverOpened, isOpen]);
|
||||
|
||||
if (!isEverOpened) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Handle overlay close event.
|
||||
const handleOverlayClose = () => {
|
||||
|
||||
setIsOpen(false);
|
||||
onClose && onClose();
|
||||
};
|
||||
// Handle overlay open event.
|
||||
const handleOverlayOpen = () => {
|
||||
setIsOpen(true);
|
||||
};
|
||||
// Handle sidebar item link click.
|
||||
const handleItemClick = () => {
|
||||
setIsOpen(false);
|
||||
onClose && onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Overlay
|
||||
isOpen={isOpen}
|
||||
portalContainer={document.getElementById('dashboard') || document.body}
|
||||
onClose={handleOverlayClose}
|
||||
onClose={handleOverlayClose}
|
||||
onOpening={handleOverlayOpen}
|
||||
transitionDuration={200}
|
||||
backdropClassName={'sidebar-overlay-backdrop'}
|
||||
>
|
||||
<div className="sidebar-overlay">
|
||||
<div className="sidebar-overlay sidebar-overlay-transition">
|
||||
<SidebarOverlayContainer>
|
||||
<div className="sidebar-overlay__menu">
|
||||
{label && (
|
||||
<>
|
||||
<SidebarOverlayLabel text={label} />
|
||||
<SidebarOverlayDivider />
|
||||
</>
|
||||
)}
|
||||
|
||||
{items.map((item) =>
|
||||
item.divider ? (
|
||||
<SidebarOverlayDivider />
|
||||
) : item.label ? (
|
||||
<SidebarOverlayLabel text={item.text} />
|
||||
) : (
|
||||
<SidebarOverlayItem text={item.text} href={item.href} />
|
||||
<SidebarOverlayItem
|
||||
onLinkClick={handleItemClick}
|
||||
text={item.text}
|
||||
href={item.href}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user