Added basic mobile Layout
This commit is contained in:
parent
7c7d60bab7
commit
635fd437da
6 changed files with 275 additions and 49 deletions
|
@ -1,4 +1,4 @@
|
|||
import { Footer } from "../components/styles/generic"
|
||||
import { Footer, MobileFooter } from "../components/styles/generic"
|
||||
|
||||
const PageFooter = () => {
|
||||
return (
|
||||
|
@ -8,4 +8,12 @@ const PageFooter = () => {
|
|||
);
|
||||
}
|
||||
|
||||
const NavMenuFooter = () => {
|
||||
return (
|
||||
<MobileFooter>
|
||||
Built using Next.js
|
||||
</MobileFooter>
|
||||
);
|
||||
}
|
||||
|
||||
export default PageFooter;
|
|
@ -2,9 +2,14 @@ import PageFooter from './footer';
|
|||
import PageNavbar from './navbar';
|
||||
import Script from 'next/script';
|
||||
import { Page, Main } from './styles/generic';
|
||||
import useWindowSize from './windowsize';
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
const isMobile = useWindowSize();
|
||||
|
||||
let ret: JSX.Element;
|
||||
if(isMobile) {
|
||||
ret = (
|
||||
<Page>
|
||||
<Script id="matomo_analytics"
|
||||
defer src='https://static.cloudflareinsights.com/beacon.min.js'
|
||||
|
@ -29,13 +34,48 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
|||
`}
|
||||
</Script>
|
||||
|
||||
<PageNavbar />
|
||||
<PageNavbar mobile={isMobile}/>
|
||||
<Main>
|
||||
{children}
|
||||
</Main>
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
else {
|
||||
ret = (
|
||||
<Page>
|
||||
<Script id="matomo_analytics"
|
||||
defer src='https://static.cloudflareinsights.com/beacon.min.js'
|
||||
data-cf-beacon='{"token": "826fc083aa86417890c0ceb3e0a597fa"}'>
|
||||
</Script>
|
||||
<Script id="matomo_analytics">
|
||||
{`
|
||||
var _paq = window._paq = window._paq || [];
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
_paq.push(["setDocumentTitle", document.domain + "/" + document.title]);
|
||||
_paq.push(["setCookieDomain", "www.neshweb.net"]);
|
||||
_paq.push(["disableCookies"]);
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
(function() {
|
||||
var u="//tracking.neshweb.net/";
|
||||
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
||||
_paq.push(['setSiteId', '2']);
|
||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
||||
})();
|
||||
`}
|
||||
</Script>
|
||||
|
||||
<PageNavbar mobile={isMobile}/>
|
||||
<Main>
|
||||
{children}
|
||||
</Main>
|
||||
<PageFooter />
|
||||
</Page>
|
||||
);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
export default Layout;
|
|
@ -1,12 +1,57 @@
|
|||
import { usePathname } from 'next/navigation'
|
||||
import { NavBar, NavLink, NavWrap } from './styles/navbar';
|
||||
import { NavBar, NavBarMobile, NavIndicator, NavIndicators, NavLink, NavSideMenu, NavSideMenuButton, NavSideMenuPanel, NavSideMenuButtonPlaceholder, NavWrap, NavWrapMobile, NavWrapMobileGhost, NavSideMenuGhost } from './styles/navbar';
|
||||
import { StyleSelector, StyleSelectorPlaceholder } from './themeselector';
|
||||
import Links from '../public/data/navbar.json';
|
||||
import { useState } from 'react';
|
||||
import NavMenuFooter from './footer';
|
||||
|
||||
const PageNavbar = () => {
|
||||
const PageNavbar = ({ mobile }: { mobile: number }) => {
|
||||
const path = usePathname();
|
||||
const [sideBarActive, setSideBarActive] = useState(true); //DEBUG: set to false
|
||||
|
||||
return (
|
||||
function handleSidebar(event: any) {
|
||||
if (!event.currentTarget.contains(event.relatedTarget)) {
|
||||
setSideBarActive(false);
|
||||
console.log(event.relatedTarget); // DEBUG
|
||||
}
|
||||
else { console.log("nah") } // DEBUG
|
||||
}
|
||||
|
||||
let navbar: JSX.Element;
|
||||
if (mobile) {
|
||||
navbar = (
|
||||
<>
|
||||
<NavSideMenu onBlur={(event) => handleSidebar(event)} active={+sideBarActive}>
|
||||
<NavBarMobile>
|
||||
{Links.links.map((item) => (
|
||||
<NavLink active={path === item.href ? +true : +false} key={item.name} href={item.href}>
|
||||
{item.name}
|
||||
</NavLink>
|
||||
))}
|
||||
<NavLink key="Mastodon_Verify" rel="me" href="https://mastodon.neshweb.net/@neshura">
|
||||
Mastodon
|
||||
</NavLink>
|
||||
</NavBarMobile>
|
||||
<NavSideMenuGhost/>
|
||||
<StyleSelector />
|
||||
<NavSideMenuGhost/>
|
||||
<NavMenuFooter />
|
||||
</NavSideMenu>
|
||||
<NavWrapMobile>
|
||||
<NavSideMenuButton onClick={() => setSideBarActive(!sideBarActive)} active={+sideBarActive}>Menu</NavSideMenuButton>
|
||||
<NavIndicators>
|
||||
{Links.links.map((item) => (
|
||||
<NavIndicator active={path === item.href ? +true : +false} key={item.name} href={item.href} />
|
||||
))}
|
||||
</NavIndicators>
|
||||
<NavSideMenuButtonPlaceholder />
|
||||
</NavWrapMobile>
|
||||
<NavWrapMobileGhost/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
else {
|
||||
navbar = (
|
||||
<NavWrap>
|
||||
<StyleSelector></StyleSelector>
|
||||
<NavBar>
|
||||
|
@ -22,6 +67,8 @@ const PageNavbar = () => {
|
|||
<StyleSelectorPlaceholder></StyleSelectorPlaceholder>
|
||||
</NavWrap>
|
||||
);
|
||||
}
|
||||
return navbar;
|
||||
}
|
||||
|
||||
export default PageNavbar;
|
|
@ -43,3 +43,8 @@ export const Footer = styled.footer`
|
|||
flex-grow: 1;
|
||||
}
|
||||
`
|
||||
|
||||
export const MobileFooter = styled(Footer)`
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
`
|
||||
|
|
|
@ -13,6 +13,61 @@ export const NavWrap = styled.div`
|
|||
border-bottom: 1px solid ${({ theme }) => theme.colors.primary};
|
||||
`
|
||||
|
||||
|
||||
export const NavWrapMobile = styled(NavWrap)`
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
`
|
||||
|
||||
export const NavWrapMobileGhost = styled.div`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 57px;
|
||||
`
|
||||
|
||||
export const NavSideMenu = styled.div <ActivePropType>`
|
||||
position: fixed;
|
||||
top: 0%; left: 0%; right: 0%; bottom: 0%;
|
||||
max-width: ${ props => props.active ? "60%" : "0%"};
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
|
||||
background-color: ${({ theme }) => theme.colors.background};
|
||||
visibility: ${ props => props.active ? "visible" : "hidden"};
|
||||
width: ${ props => props.active ? "360px" : "0%"};
|
||||
transition-delay: ${ props => props.active ? "0s, 0s" : "0s, 0.3s"};
|
||||
`
|
||||
|
||||
export const NavSideMenuPanel = styled.div <ActivePropType>`
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
`
|
||||
|
||||
export const NavSideMenuButton = styled.button <ActivePropType>`
|
||||
z-index: 100;
|
||||
margin: 16px;
|
||||
color: ${ props => props.active ? ({ theme }) => theme.colors.background : ({ theme }) => theme.colors.primary };
|
||||
background-color: ${ props => props.active ? ({ theme }) => theme.colors.secondary : ({ theme }) => theme.colors.background };
|
||||
`
|
||||
|
||||
export const NavSideMenuButtonPlaceholder = styled.div`
|
||||
width: 48px;
|
||||
margin: 16px;
|
||||
`
|
||||
|
||||
export const NavSideMenuGhost = styled.div`
|
||||
|
||||
`
|
||||
|
||||
export const NavBar = styled.nav`
|
||||
margin-right: 1%;
|
||||
display: flex;
|
||||
|
@ -23,6 +78,10 @@ export const NavBar = styled.nav`
|
|||
align-items: center;
|
||||
`
|
||||
|
||||
export const NavBarMobile = styled(NavBar)`
|
||||
flex-direction: column;
|
||||
`
|
||||
|
||||
export const NavLink = styled(Link) <ActivePropType>`
|
||||
color: ${props => props.active ?
|
||||
({ theme }) => theme.invertButtons ?
|
||||
|
@ -54,3 +113,36 @@ export const NavLink = styled(Link) <ActivePropType>`
|
|||
theme.colors.background};
|
||||
}
|
||||
`
|
||||
|
||||
export const NavIndicators = styled.nav`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding: 1rem 0;
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
export const NavIndicator = styled(Link) <ActivePropType>`
|
||||
margin: 0.2rem;
|
||||
border-radius: 50%;
|
||||
aspect-ratio: 1;
|
||||
width: 10px;
|
||||
border: 1px solid ${({ theme }) => theme.colors.primary};
|
||||
|
||||
background-color: ${props => props.active ?
|
||||
({ theme }) => theme.invertButtons ?
|
||||
theme.colors.secondary : theme.colors.background :
|
||||
({ theme }) => theme.colors.background};
|
||||
|
||||
&:hover {
|
||||
color: ${({ theme }) => theme.invertButtons ?
|
||||
theme.colors.text ? theme.colors.text : theme.colors.primary :
|
||||
theme.colors.secondary};
|
||||
|
||||
background-color: ${({ theme }) => theme.invertButtons ?
|
||||
theme.colors.secondary :
|
||||
theme.colors.background};
|
||||
}
|
||||
`
|
34
components/windowsize.tsx
Normal file
34
components/windowsize.tsx
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { useEffect, useState } from "react";
|
||||
|
||||
interface ScreenSize {
|
||||
width: number | undefined;
|
||||
height: number | undefined;
|
||||
}
|
||||
|
||||
export default function useWindowSize(): number {
|
||||
const [windowSize, setWindowSize] = useState<ScreenSize>({
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
function handleResize() {
|
||||
setWindowSize({
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight,
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
handleResize();
|
||||
|
||||
return () => window.removeEventListener("resize", handleResize);
|
||||
}, []);
|
||||
if(typeof(windowSize.width) === "number") {
|
||||
return windowSize.width <= 1080 ? 1 : 0;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue