Merge pull request #3 from kfnawaz/sidebar-nav

Feat - Sidebar navigation
This commit is contained in:
bluestreamlds
2022-01-08 08:51:35 +05:30
committed by GitHub
15 changed files with 294 additions and 17 deletions

View File

@@ -24,7 +24,8 @@
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"deploy": "scp -Cvpr -i <keyfile> build/* ubuntu@ec2-13-59-140-102.us-east-2.compute.amazonaws.com:/home/ubuntu/web-wms/"
},
"eslintConfig": {
"extends": [

View File

@@ -0,0 +1,19 @@
const HamburgerIcon = ({ width = 24, height = 24, color, ...props }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={width}
height={height}
viewBox="0 0 24 24"
stroke={color}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
{...props}
>
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
);
export default HamburgerIcon;

View File

@@ -0,0 +1,14 @@
const HomeIcon = ({ width = 24, height = 24, color = 'white', ...props }) => (
<svg width={width} height={height} viewBox="0 0 24 24" fill="none" {...props} xmlns="http://www.w3.org/2000/svg">
<path
d="M17.79 22.75H6.21C3.47 22.75 1.25 20.52 1.25 17.78V10.37C1.25 9.01 2.09 7.3 3.17 6.46L8.56 2.26C10.18 1 12.77 0.940005 14.45 2.12L20.63 6.45C21.82 7.28 22.75 9.06001 22.75 10.51V17.79C22.75 20.52 20.53 22.75 17.79 22.75ZM9.48 3.44L4.09 7.64C3.38 8.2 2.75 9.47001 2.75 10.37V17.78C2.75 19.69 4.3 21.25 6.21 21.25H17.79C19.7 21.25 21.25 19.7 21.25 17.79V10.51C21.25 9.55 20.56 8.22 19.77 7.68L13.59 3.35C12.45 2.55 10.57 2.59 9.48 3.44Z"
fill={color}
/>
<path
d="M12 18.75C11.59 18.75 11.25 18.41 11.25 18V15C11.25 14.59 11.59 14.25 12 14.25C12.41 14.25 12.75 14.59 12.75 15V18C12.75 18.41 12.41 18.75 12 18.75Z"
fill={color}
/>
</svg>
);
export default HomeIcon;

View File

@@ -0,0 +1,10 @@
const SidebarDownIcon = ({ width = 14, height = 8, color = 'white', ...props }) => (
<svg width={width} height={height} viewBox="0 0 15 8" fill="none" {...props} xmlns="http://www.w3.org/2000/svg">
<path
d="M8.51 7.19999L10.48 5.22999L13.69 2.01999C14.36 1.33999 13.88 0.179993 12.92 0.179993L6.69 0.179993L1.08 0.179993C0.120001 0.179993 -0.36 1.33999 0.320001 2.01999L5.5 7.19999C6.32 8.02999 7.68 8.02999 8.51 7.19999Z"
fill={color}
/>
</svg>
);
export default SidebarDownIcon;

View File

@@ -0,0 +1,19 @@
const XIcon = ({ width = 18, height = 18, color = '#ffffff', ...props }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={width}
height={height}
viewBox="0 0 14 14"
fill="none"
stroke={color}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
{...props}
>
<line x1="13" y1="1" x2="1" y2="13"></line>
<line x1="1" y1="1" x2="13" y2="13"></line>
</svg>
);
export default XIcon;

View File

@@ -1,9 +1,81 @@
import { NavLink } from 'react-router-dom';
import SidebarDownIcon from '../../assets/icons/SidebarDown-icon';
import HomeIcon from '../../assets/icons/Home-icon';
import XIcon from '../../assets/icons/X-close-icon';
import combineClasses from '../../utils/combineCssClasses';
import styles from './sidebar.module.css';
export default function Sidebar() {
const items = {
title: {
icon: '',
text: 'Main link',
link: '/',
},
subs: [
{
text: 'Sub links',
link: '/login',
},
{
text: 'Sub links',
link: '/login',
},
{
text: 'Sub links',
link: '/login',
},
{
text: 'Sub links',
link: '/',
},
{
text: 'Sub links',
link: '/login',
},
],
};
const NavGroupItems = ({ list }) => {
return (
<div className={styles.navSidebar}>
<div className={styles.sidebarBranding}>Plaidware</div>
<div className={styles.sidebarGroup}>
<div className={combineClasses(styles.sidebarMainItem)}>
<NavLink className={combineClasses(styles.alink, styles.mainItemContent)} to={list.title.link}>
<HomeIcon className={styles.mainItemIcon} />
<div>{list.title.text}</div>
</NavLink>
<SidebarDownIcon className={styles.dropdownIcon} />
</div>
{list.subs.map((subLink, idx) => (
<NavLink key={idx} className={styles.alink} to={subLink.link}>
{({ isActive }) => (
<div className={combineClasses(styles.sidebarSubItem, [isActive, styles.subActive])}>{subLink.text}</div>
)}
</NavLink>
))}
</div>
);
};
export default function Sidebar({ isMobileScreen, isOpen, setOpen }) {
if (!isMobileScreen && isOpen) {
return (
<div className={styles.navSidebar}>
<div className={styles.sidebarBrandingHeader}>
<div className={styles.sidebarBranding}>Plaidware</div>
<div
onClick={() => {
setOpen(false);
}}
>
<XIcon />
</div>
</div>
<div className={styles.sidebarList}>
<NavGroupItems list={items} />
<NavGroupItems list={items} />
</div>
</div>
);
}
return null;
}

View File

@@ -2,7 +2,18 @@
grid-column: 1;
background: #2d373c;
min-height: 100vh;
padding: 40px;
min-width: 350px;
}
/* @media only screen and (max-width: 800px) {
} */
.sidebarBrandingHeader {
display: grid;
padding: 40px 0px 30px 40px;
grid-template-columns: auto 40px;
align-items: center;
}
.sidebarBranding {
@@ -12,4 +23,60 @@
line-height: 44px;
color: #ffffff;
}
}
.sidebarList {
width: 100%;
}
.sidebarGroup {
}
.sidebarMainItem {
width: 100%;
display: grid;
align-items: center;
grid-template-columns: auto 55px;
height: 48px;
/* background: #007aff; */
}
.mainItemContent {
display: grid;
align-items: center;
grid-template-columns: 80px auto;
height: 100%;
color: white;
}
.mainItemIcon {
padding-left: 40px;
width: auto;
}
.dropdownIcon {
padding-left: 20px;
width: auto;
}
.sidebarSubItem {
width: 100%;
height: 46px;
display: grid;
align-items: center;
padding-left: 80px;
color: white;
}
.alink:visited,
.alink:link {
text-decoration: none;
}
.subActive {
background: #1f282d;
color: #007aff !important;
}

View File

@@ -1,8 +1,18 @@
import React from 'react'
import styles from './topbar.module.css'
import React from 'react';
import HamburgerIcon from '../../assets/icons/Hamburger-icon';
import styles from './topbar.module.css';
export default function TopBar() {
export default function TopBar({ isMobileScreen, isSidebarOpen, setSidebarOpen }) {
return (
<div className={styles.topBar}>search comes here</div>
)
<div className={styles.topBar}>
<div
onClick={() => {
setSidebarOpen(true);
}}
>
{isSidebarOpen ? null : <HamburgerIcon color="#000" />}
</div>
<div>Right side icons here</div>
</div>
);
}

View File

@@ -1,5 +1,10 @@
.topBar {
grid-row: 1;
padding: 24px 48px;
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.08);
}
display: flex;
align-items: center;
justify-content: space-between;
}

View File

View File

@@ -0,0 +1,25 @@
import { useState, useEffect } from 'react';
function getWindowDimensions() {
const { innerWidth: width, innerHeight: height } = window;
return {
width,
height,
isMobileScreen: width <= 800,
};
}
export default function useWindowDimensions() {
const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
useEffect(() => {
function handleResize() {
setWindowDimensions(getWindowDimensions());
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return windowDimensions;
}

View File

@@ -1,11 +1,13 @@
html,
body {
margin: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
* {
font-family: Averta;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
box-sizing: border-box;
}
code {

View File

@@ -1,7 +1,7 @@
.dashboardGrid {
width: 100vw;
display: grid;
grid-template-columns: 300px auto;
grid-template-columns: max-content auto;
}
.mainContent {
@@ -10,7 +10,19 @@
grid-template-rows: 108px 72px auto;
}
@media only screen and (max-width: 800px) {
.dashboardGrid {
grid-template-columns: auto;
}
.mainContent {
grid-column: 1;
grid-template-rows: 50px 50px auto;
}
}
.content {
grid-row: 3;
padding: 24px 48px;
min-height: 100%;
}

View File

@@ -1,15 +1,21 @@
import { useState } from 'react';
import { Outlet } from 'react-router-dom';
import Breadcrumbs from '../../components/breadcrumbs';
import Sidebar from '../../components/Sidebar';
import TopBar from '../../components/topbar';
import useWindowDimensions from '../../hooks/useWindowDimensions';
import styles from './dashboard.module.css';
export default function Dashboard() {
const [sidebarOpen, setSidebarOpen] = useState(true);
const { isMobileScreen } = useWindowDimensions();
return (
<div className={styles.dashboardGrid}>
<Sidebar />
<Sidebar isMobileScreen={isMobileScreen} isOpen={sidebarOpen} setOpen={setSidebarOpen} />
<div className={styles.mainContent}>
<TopBar />
<TopBar isMobileScreen={isMobileScreen} isSidebarOpen={sidebarOpen} setSidebarOpen={setSidebarOpen} />
<Breadcrumbs />
<div className={styles.content}>
<Outlet />

View File

@@ -0,0 +1,15 @@
export const combineClasses = (...classes) => {
return classes.reduce((classNames, currentClassName) => {
if (Array.isArray(currentClassName)) {
return currentClassName[0] ? classNames + ' ' + currentClassName[1] : classNames;
} else if (currentClassName) {
return classNames + ' ' + currentClassName;
} else {
return classNames;
}
}, '');
};
export default combineClasses;
// Ref: https://www.npmjs.com/package/combine-classes