Backdrop and menu
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
import classNames from 'classnames';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
const Backdrop = ({ open, onClose }) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onClick={onClose}
|
||||||
|
className={classNames('fixed z-10 inset-0 bg-black transition-opacity w-full h-full', {
|
||||||
|
'pointer-events-none': !open,
|
||||||
|
'opacity-10': open,
|
||||||
|
'opacity-0': !open,
|
||||||
|
})}
|
||||||
|
></div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Backdrop;
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
const Menu = ({ open, onClose }) => (
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
'fixed z-40 transform transform-gpu translate w-48 h-full bg-gray-100 transition-transform',
|
||||||
|
{
|
||||||
|
'-translate-x-full': !open,
|
||||||
|
'-translate-x-0': open,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="p-4">
|
||||||
|
<h2 className="text-xl select-none">Menu</h2>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="text-gray-800 hover:text-gray-400 block px-4 py-2 rounded-md text-base font-medium"
|
||||||
|
>
|
||||||
|
Calendar
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Menu;
|
||||||
+8
-45
@@ -1,30 +1,28 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Plugins } from '@capacitor/core';
|
import { Plugins } from '@capacitor/core';
|
||||||
|
|
||||||
const Nav = ({ page }) => {
|
const Nav = ({ page, onShowMenu }) => {
|
||||||
const [showMenu, setShowMenu] = useState(false);
|
const [showMenu, setShowMenu] = useState(false);
|
||||||
|
|
||||||
const [showMobileMenu, setShowMobileMenu] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
Plugins.StatusBar.setStyle({
|
Plugins.StatusBar.setStyle({
|
||||||
style: 'DARK'
|
style: 'DARK',
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav
|
<nav
|
||||||
className="bg-gray-800 w-full flex-0 flex items-end flex-row"
|
className="bg-gray-800 w-full flex-0 flex items-end flex-row z-10"
|
||||||
style={{
|
style={{
|
||||||
height: `calc(env(safe-area-inset-bottom, 0px) + 64px)`
|
height: `calc(env(safe-area-inset-bottom, 0px) + 64px)`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8 flex-1">
|
<div className="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8 flex-1">
|
||||||
<div className="relative flex items-center justify-between h-16">
|
<div className="relative flex items-center justify-between h-16">
|
||||||
<div
|
<div
|
||||||
className="absolute inset-y-0 left-0 flex items-center sm:hidden"
|
className="absolute inset-y-0 left-0 flex items-center sm:hidden"
|
||||||
onClick={() => setShowMobileMenu(!showMobileMenu)}
|
onClick={onShowMenu}
|
||||||
>
|
>
|
||||||
{/* Mobile menu button*/}
|
{/* Mobile menu button*/}
|
||||||
<button
|
<button
|
||||||
@@ -204,43 +202,8 @@ const Nav = ({ page }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/*
|
|
||||||
Mobile menu, toggle classes based on menu state.
|
|
||||||
|
|
||||||
Menu open: "block", Menu closed: "hidden"
|
|
||||||
*/}
|
|
||||||
<div className={`${showMobileMenu ? '' : 'hidden sm:hidden'}`}>
|
|
||||||
<div className="px-2 pt-2 pb-3 space-y-1">
|
|
||||||
{/* Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" */}
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className="bg-gray-900 text-white block px-3 py-2 rounded-md text-base font-medium"
|
|
||||||
>
|
|
||||||
Dashboard
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium"
|
|
||||||
>
|
|
||||||
Team
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium"
|
|
||||||
>
|
|
||||||
Projects
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium"
|
|
||||||
>
|
|
||||||
Calendar
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Nav;
|
export default Nav;
|
||||||
|
|||||||
Generated
+2
-1
@@ -4132,7 +4132,8 @@
|
|||||||
"prettier": {
|
"prettier": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz",
|
||||||
"integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q=="
|
"integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"pretty-hrtime": {
|
"pretty-hrtime": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
|
|||||||
+3
-1
@@ -16,9 +16,11 @@
|
|||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"next": "10.0.3",
|
"next": "10.0.3",
|
||||||
"postcss": "^8.2.1",
|
"postcss": "^8.2.1",
|
||||||
"prettier": "^2.2.1",
|
|
||||||
"react": "17.0.1",
|
"react": "17.0.1",
|
||||||
"react-dom": "17.0.1",
|
"react-dom": "17.0.1",
|
||||||
"tailwindcss": "^2.0.2"
|
"tailwindcss": "^2.0.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"prettier": "^2.2.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-9
@@ -1,6 +1,8 @@
|
|||||||
import { useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import App from '../components/App';
|
import App from '../components/App';
|
||||||
|
import Backdrop from '../components/Backdrop';
|
||||||
|
import Menu from '../components/Menu';
|
||||||
import Nav from '../components/Nav';
|
import Nav from '../components/Nav';
|
||||||
import Home from '../components/pages/Home';
|
import Home from '../components/pages/Home';
|
||||||
import Profile from '../components/pages/Profile';
|
import Profile from '../components/pages/Profile';
|
||||||
@@ -9,34 +11,54 @@ import Tab from '../components/Tab';
|
|||||||
import TabBar from '../components/TabBar';
|
import TabBar from '../components/TabBar';
|
||||||
|
|
||||||
const pages = [
|
const pages = [
|
||||||
{ id: 'home', title: 'Home', icon: "home-outline", selectedIcon: "home", component: Home },
|
{ id: 'home', title: 'Home', icon: 'home-outline', selectedIcon: 'home', component: Home },
|
||||||
{ id: 'profile', title: 'Profile', icon: "person-outline", selectedIcon: "person", component: Profile },
|
{
|
||||||
{ id: 'settings', title: 'Settings', icon: "cog-outline", selectedIcon: "cog", component: Settings },
|
id: 'profile',
|
||||||
]
|
title: 'Profile',
|
||||||
|
icon: 'person-outline',
|
||||||
|
selectedIcon: 'person',
|
||||||
|
component: Profile,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'settings',
|
||||||
|
title: 'Settings',
|
||||||
|
icon: 'cog-outline',
|
||||||
|
selectedIcon: 'cog',
|
||||||
|
component: Settings,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const CurrentPage = ({ page }) => {
|
const CurrentPage = ({ page }) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 overflow-hidden relative">
|
<div className="flex-1 overflow-hidden relative">
|
||||||
{pages.map(p => {
|
{pages.map(p => {
|
||||||
const Page = p.component;
|
const Page = p.component;
|
||||||
return <Page selected={page.id === p.id} />
|
return <Page selected={page.id === p.id} />;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function Index() {
|
export default function Index() {
|
||||||
const [page, setPage] = useState(pages[0]);
|
const [page, setPage] = useState(pages[0]);
|
||||||
|
|
||||||
|
const [showMenu, setShowMenu] = useState(false);
|
||||||
|
|
||||||
|
const openMenu = useCallback(() => {
|
||||||
|
setShowMenu(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<App>
|
<App>
|
||||||
<Nav page={page} />
|
<Menu open={showMenu} onClose={() => setShowMenu(false)} />
|
||||||
|
<Nav page={page} onShowMenu={openMenu} />
|
||||||
<CurrentPage page={page} />
|
<CurrentPage page={page} />
|
||||||
<TabBar>
|
<TabBar>
|
||||||
{pages.map(p => (
|
{pages.map(p => (
|
||||||
<Tab key={p.id} {...p} onClick={() => setPage(p)} selected={p.id === page.id} />
|
<Tab key={p.id} {...p} onClick={() => setPage(p)} selected={p.id === page.id} />
|
||||||
))}
|
))}
|
||||||
</TabBar>
|
</TabBar>
|
||||||
|
<Backdrop open={showMenu} onClose={() => setShowMenu(false)} />
|
||||||
</App>
|
</App>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user