Added basic mobile Layout

This commit is contained in:
Neshura 2022-12-18 23:21:38 +01:00
parent 7c7d60bab7
commit 635fd437da
No known key found for this signature in database
GPG key ID: ACDF5B6EBECF6B0A
6 changed files with 275 additions and 49 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -43,3 +43,8 @@ export const Footer = styled.footer`
flex-grow: 1;
}
`
export const MobileFooter = styled(Footer)`
position: absolute;
bottom: 100%;
`

View file

@ -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
View 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;
}
}