diff --git a/components/footer.tsx b/components/footer.tsx
index 4b8550f..c5824b5 100644
--- a/components/footer.tsx
+++ b/components/footer.tsx
@@ -1,4 +1,4 @@
-import { Footer } from "../components/styles/generic"
+import { Footer, MobileFooter } from "../components/styles/generic"
const PageFooter = () => {
return (
@@ -7,5 +7,13 @@ const PageFooter = () => {
);
}
+
+export const NavMenuFooter = () => {
+ return (
+
+ Built using Next.js
+
+ );
+}
export default PageFooter;
\ No newline at end of file
diff --git a/components/layout.tsx b/components/layout.tsx
index 8482b63..6a2f966 100644
--- a/components/layout.tsx
+++ b/components/layout.tsx
@@ -2,40 +2,80 @@ 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();
-
-
- {children}
-
-
-
- );
+ let ret: JSX.Element;
+ if(isMobile) {
+ ret = (
+
+
+
+
+
+
+ {children}
+
+
+ );
+ }
+ else {
+ ret = (
+
+
+
+
+
+
+ {children}
+
+
+
+ );
+ }
+ return ret;
}
export default Layout;
\ No newline at end of file
diff --git a/components/navbar.tsx b/components/navbar.tsx
index 6994205..83a84c5 100644
--- a/components/navbar.tsx
+++ b/components/navbar.tsx
@@ -1,27 +1,74 @@
import { usePathname } from 'next/navigation'
-import { NavBar, NavLink, NavWrap } from './styles/navbar';
+import { NavBarMobile, NavIndicator, NavIndicators , NavSideMenu, NavSideMenuButton, NavSideMenuPanel, NavLinkMobile, NavWrapMobile, NavWrapMobileGhost, NavSideMenuGhost } from './styles/navbar/mobile';
+import { NavBar, NavLink, NavWrap } from './styles/navbar/desktop';
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 (
-
-
-
- {Links.links.map((item) => (
-
- {item.name}
+ function handleSidebar(event: any) {
+ if (!event.currentTarget.contains(event.relatedTarget)) {
+ setSideBarActive(false);
+ }
+ }
+
+ let navbar: JSX.Element;
+ if (mobile) {
+ navbar = (
+ <>
+ handleSidebar(event)} active={+sideBarActive}>
+ setSideBarActive(sideBarActive => !sideBarActive)} active={+sideBarActive}>Menu
+
+
+ {Links.links.map((item) => (
+
+ {item.name}
+
+ ))}
+
+ Mastodon
+
+
+
+
+
+
+
+
+
+
+ {Links.links.map((item) => (
+
+ ))}
+
+
+
+ >
+ );
+ }
+ else {
+ navbar = (
+
+
+
+ {Links.links.map((item) => (
+
+ {item.name}
+
+ ))}
+
+ Mastodon
- ))}
-
- Mastodon
-
-
-
-
- );
+
+
+
+ );
+ }
+ return navbar;
}
export default PageNavbar;
\ No newline at end of file
diff --git a/components/styles/content.tsx b/components/styles/content.tsx
index 31c35d8..376cc94 100644
--- a/components/styles/content.tsx
+++ b/components/styles/content.tsx
@@ -24,7 +24,7 @@ export const PageTitle = styled.h1`
export const PageDescription = styled.p`
background-color: ${({ theme }) => theme.colors.background ? theme.colors.background : ""};
padding: 0.25rem 0.5rem;
- margin: 4rem 0;
+ margin: 4rem 2rem;
line-height: 1.5;
font-size: 1.5rem;
text-align: center;
diff --git a/components/styles/generic.tsx b/components/styles/generic.tsx
index b74877c..e8354de 100644
--- a/components/styles/generic.tsx
+++ b/components/styles/generic.tsx
@@ -7,13 +7,18 @@ export const StyledBody = styled.body`
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
`
-export const Page = styled.div`
+interface MobilePropType {
+ mobile?: number;
+}
+
+export const Page = styled.div`
width: 100%;
background-color: ${({ theme }) => theme.colors.background};
background-image: ${({ theme }) => theme.backgroundImage ? "url(" + theme.backgroundImage + ")" : ""};
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
+ background-position: ${ props => props.mobile ? ({ theme }) => theme.backgroundOffset ? theme.backgroundOffset : "60%" : ""};
`
export const Main = styled.main`
@@ -43,3 +48,9 @@ export const Footer = styled.footer`
flex-grow: 1;
}
`
+
+export const MobileFooter = styled(Footer)`
+ white-space: nowrap;
+ flex: 0.5;
+ width: 100%;
+`
diff --git a/components/styles/navbar.tsx b/components/styles/navbar/desktop.tsx
similarity index 96%
rename from components/styles/navbar.tsx
rename to components/styles/navbar/desktop.tsx
index 4b9f0d3..b77b140 100644
--- a/components/styles/navbar.tsx
+++ b/components/styles/navbar/desktop.tsx
@@ -40,8 +40,6 @@ export const NavLink = styled(Link) `
margin: 0.2rem;
border-radius: 5px;
display: flex;
- justify-content: center;
- align-items: center;
transition: all 0.1s ease;
&:hover {
diff --git a/components/styles/navbar/mobile.tsx b/components/styles/navbar/mobile.tsx
new file mode 100644
index 0000000..9c903e5
--- /dev/null
+++ b/components/styles/navbar/mobile.tsx
@@ -0,0 +1,249 @@
+import styled from 'styled-components'
+import Link from 'next/link';
+import { NavBar, NavLink, NavWrap } from './desktop';
+
+interface ActivePropType {
+ active?: number;
+}
+
+interface MultipliesPropType {
+ num?: number;
+}
+
+export const NavWrapMobile = styled(NavWrap)`
+ width: 100%;
+ flex-direction: row;
+ position: fixed;
+ z-index: 50;
+`
+
+export const NavWrapMobileGhost = styled.div`
+ position: relative;
+ width: 100%;
+ height: 50px;
+`
+
+export const NavSideMenu = styled.div `
+ position: fixed;
+ top: 0%; left: 0%; right: 0%; bottom: 0%;
+ max-width: ${props => props.active ? "240px" : "0px"};
+ max-height: ${props => props.active ? "100%" : "50px"};
+ display: flex;
+ justify-content: space-between;
+ flex-direction: column;
+ height: 100%;
+ z-index: 100;
+ border-right: ${ props => ({ theme }) => {
+ let ret: string;
+ if(props.active) {
+ ret = "1px solid " + theme.colors.primary;
+ }
+ else {
+ ret = "0px solid";
+ }
+ return ret;
+ }};
+
+ background-color: ${ props => ({ theme }) => {
+ let ret: string;
+ if (props.active) {
+ ret = theme.colors.background;
+ }
+ else {
+ ret = "";
+ }
+ return ret;
+ }};
+ backdrop-filter: ${props => props.active ? "blur(5px)" : ""};
+
+ overflow-x: hidden;
+ transition-property: max-width, max-height, border-right, background-color, backdrop-filter;
+ transition-timing-function: ease-in-out;
+ transition-duration: 0.15s, 0s;
+ transition-delay: ${props => props.active ? "0s" : "0s, 0.15s"};
+`
+
+export const NavSideMenuPanel = styled.div `
+ height: 100%;
+ width: 240px;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+ align-items: left;
+`
+
+export const NavSideMenuButton = styled.button `
+ position: ${ props => props.active ? "absolute" : "fixed"};
+ z-index: 200;
+ left: ${ props => props.active ? "165px" : "0px"};
+
+ transition-property: left, color, background-color, border-color;
+ transition-timing-function: ease-in-out;
+ transition-duration: 0.135s, 0.15s;
+ transition-delay: ${props => props.active ? "0.03s, 0s" : "0s, 0s"};
+
+ align-self: flex-end;
+ cursor: pointer;
+ margin: 12px;
+ color: ${props => ({ theme }) => {
+ let ret: string;
+ if (props.active) {
+ if (theme.invertButtons) {
+ ret = theme.colors.text ? theme.colors.text : theme.colors.secondary;
+ }
+ else {
+ ret = theme.colors.secondary;
+ }
+ }
+ else {
+ ret = theme.colors.primary;
+ }
+ return ret;
+ }};
+ background-color: ${props => ({ theme }) => {
+ let ret: string;
+ if (props.active) {
+ if (theme.invertButtons) {
+ ret = theme.colors.secondary;
+ }
+ else {
+ ret = theme.colors.background;
+ }
+ }
+ else {
+ ret = theme.colors.background;
+ }
+ return ret;
+ }};
+
+ border: 2px solid;
+ border-radius: 5px;
+ border-color: ${props => ({ theme }) => {
+ let ret: string;
+ if (props.active) {
+ if (theme.invertButtons) {
+ ret = theme.colors.text ? theme.colors.text : theme.colors.secondary;
+ }
+ else {
+ ret = theme.colors.secondary;
+ }
+ }
+ else {
+ ret = theme.colors.primary;
+ }
+ return ret;
+ }};
+
+ &:hover {
+ color: ${({ theme }) => {
+ let ret: string;
+ if (theme.invertButtons) {
+ ret = theme.colors.text ? theme.colors.text : theme.colors.primary;
+ }
+ else {
+ ret = theme.colors.secondary;
+ }
+ return ret;
+ }};
+
+ background-color: ${({ theme }) => {
+ let ret: string;
+ if (theme.invertButtons) {
+ ret = theme.colors.secondary;
+ }
+ else {
+ ret = theme.colors.background;
+ }
+ return ret;
+ }};
+
+ border-color: ${({ theme }) => {
+ let ret: string;
+ if (theme.invertButtons) {
+ ret = theme.colors.text ? theme.colors.text : theme.colors.secondary;
+ }
+ else {
+ ret = theme.colors.secondary;
+ }
+ return ret;
+ }};
+ }
+`
+
+export const NavSideMenuGhost = styled.div `
+ flex: ${ props => props.num ? props.num * 2 : 2 };
+`
+
+export const NavBarMobile = styled(NavBar)`
+ margin-top: 56px;
+ flex-direction: column;
+ align-items: flex-start;
+`
+
+export const NavLinkMobile = styled(NavLink)`
+ display: block;
+ margin-left: 1rem;
+ margin-top: 1rem;
+ padding: 0.5rem;
+ border: none;
+ border-top: 2px solid;
+ width: 80%;
+ text-align: center;
+
+ color: ${props => ({ theme }) => props.active ? theme.colors.secondary : theme.colors.primary};
+ background-color: ${({ theme }) => theme.colors.backgroundAlt ? theme.colors.backgroundAlt : theme.colors.background};
+
+ &:hover {
+ color: ${({ theme }) => theme.colors.secondary };
+ background-color: ${({ theme }) => theme.colors.backgroundAlt ? theme.colors.backgroundAlt : theme.colors.background};
+ }
+`
+
+export const NavIndicators = styled.nav`
+ background-color: ${({ theme }) => theme.colors.background};
+ background-image: ${({ theme }) => theme.backgroundImage ? "url(" + theme.backgroundImage + ")" : ""};
+ background-repeat: no-repeat;
+ background-attachment: fixed;
+ background-size: cover;
+ background-position: ${({ theme }) => theme.backgroundOffset ? theme.backgroundOffset : "60%"};
+ width: 100%;
+ display: flex;
+ flex: 1;
+ padding: 1rem 0;
+ flex-wrap: nowrap;
+ justify-content: center;
+ align-items: center;
+`
+
+export const NavIndicator = styled(Link) `
+ margin: 0.2rem;
+ border-radius: 50%;
+ aspect-ratio: 1;
+ width: 10px;
+ border: 1px solid;
+ border-color: ${ props => ({ theme }) => props.active ?
+ theme.invertButtons ? theme.colors.secondary : theme.colors.primary :
+ theme.colors.primary
+ };
+
+ background-color: ${props => ({ theme }) => props.active ?
+ theme.invertButtons ? theme.colors.secondary : theme.colors.primary :
+ theme.colors.background
+ };
+
+ &:hover {
+ border-color: ${ props => ({ theme }) =>
+ theme.invertButtons ? theme.colors.secondary : theme.colors.primary
+ };
+
+ color: ${({ theme }) => theme.invertButtons ?
+ theme.invertButtons ? theme.colors.secondary : theme.colors.primary :
+ theme.colors.primary
+ };
+
+ background-color: ${({ theme }) => theme.invertButtons ?
+ theme.colors.secondary :
+ theme.colors.primary
+ };
+ }
+`
\ No newline at end of file
diff --git a/components/styles/themedropdown.tsx b/components/styles/themedropdown/desktop.tsx
similarity index 100%
rename from components/styles/themedropdown.tsx
rename to components/styles/themedropdown/desktop.tsx
diff --git a/components/styles/themedropdown/mobile.tsx b/components/styles/themedropdown/mobile.tsx
new file mode 100644
index 0000000..36a5eb3
--- /dev/null
+++ b/components/styles/themedropdown/mobile.tsx
@@ -0,0 +1,49 @@
+import styled from 'styled-components';
+import { ThemeDropDown, ThemeDropDownButton, ThemeDropDownOption, ThemeDropDownOptions } from './desktop';
+
+export const ThemeDropDownMobile = styled(ThemeDropDown)`
+ width: 80%;
+ margin-left: 1rem;
+`;
+
+export const ThemeDropDownButtonMobile = styled(ThemeDropDownButton)`
+ width: 100%;
+ padding: 0.5rem;
+ border: none;
+ border-top: 2px solid;
+ border-left: ${ props => props.show ? "2px solid" : "0px solid"};
+ border-right: ${ props => props.show ? "2px solid" : "0px solid"};
+
+ color: ${props => ({ theme }) => props.focus ? theme.colors.secondary : theme.colors.primary};
+ background-color: ${({ theme }) => theme.colors.backgroundAlt ? theme.colors.backgroundAlt : theme.colors.background};
+
+ &:focus,:hover {
+ color: ${({ theme }) => theme.colors.secondary};
+
+ background-color: ${({ theme }) => theme.colors.backgroundAlt ? theme.colors.backgroundAlt : theme.colors.background};
+ }
+
+ transition-property: color, border-bottom-left-radius, border-bottom-right-radius, background-color, border-left, border-right;
+ transition-timing-function: ease;
+ transition-duration: 0.15s;
+ transition-delay: 0s, ${ props => props.show ? "0s" : "0.6s, 0.6s, 0s, 0.6s, 0.6s" };
+`;
+
+export const ThemeDropDownOptionsMobile = styled(ThemeDropDownOptions)`
+ background-image: unset;
+ background-color: transparent;
+ border: 2px solid ${props => ({ theme }) => props.focus ? theme.colors.secondary : theme.colors.primary};
+ border-top: 0;
+ max-height: ${ props => props.show ? "100%" : "0%"};
+ position: relative;
+ width: 100%;
+`;
+
+export const ThemeDropDownOptionMobile = styled(ThemeDropDownOption)`
+ text-align: left;
+ margin: 0.5rem;
+ padding: 0rem 0.5rem;
+ width: 80%;
+ border-left: 2px solid;
+ border-radius: 5px;
+`;
\ No newline at end of file
diff --git a/components/themeselector.tsx b/components/themeselector.tsx
index eb4fee9..55be165 100644
--- a/components/themeselector.tsx
+++ b/components/themeselector.tsx
@@ -2,10 +2,11 @@ import { useUpdateTheme } from "../pages/_app";
import { useContext, useState } from 'react';
import { ThemeContext, DefaultTheme } from "styled-components";
import { darkTheme, lightTheme } from './themes';
-import { ThemeDropDown, ThemeDropDownButton, ThemeDropDownOption, ThemeDropDownOptions } from "./styles/themedropdown";
+import { ThemeDropDown, ThemeDropDownButton, ThemeDropDownOption, ThemeDropDownOptions } from "./styles/themedropdown/desktop";
+import { ThemeDropDownMobile, ThemeDropDownButtonMobile, ThemeDropDownOptionMobile, ThemeDropDownOptionsMobile } from "./styles/themedropdown/mobile";
import Themes from '../public/data/themes.json';
-export const StyleSelector = () => {
+export const StyleSelector = ({ mobile }: { mobile: number }) => {
const themes: DefaultTheme[] = Themes.themes;
const updateTheme = useUpdateTheme();
const currentTheme = useContext(ThemeContext);
@@ -34,7 +35,7 @@ export const StyleSelector = () => {
}
}
- const [visible, setVisible] = useState(false);
+ const [visible, setVisible] = useState(true); //DEBUG set to false
const [buttonFocus, setButtonFocus] = useState(visible);
function handleBlur(event:any) {
@@ -44,19 +45,39 @@ export const StyleSelector = () => {
}
}
- return (
- handleBlur(event)}>
- setButtonFocus(true)} onClick={() => setVisible(visible => !visible)}>{selectedTheme.themeName}
-
-
- {themes.map((theme) => (
- updateThemeWithStorage(theme)}>
- {theme.themeName}
-
- ))}
-
-
- );
+ let themeselector: JSX.Element;
+ if(mobile) {
+ themeselector = (
+ handleBlur(event)}>
+ setButtonFocus(true)} onClick={() => setVisible(visible => !visible)}>
+ {selectedTheme.themeName}
+
+
+ {themes.map((theme) => (
+ updateThemeWithStorage(theme)}>
+ {theme.themeName}
+
+ ))}
+
+
+ );
+ }
+ else {
+ themeselector = (
+ handleBlur(event)}>
+ setButtonFocus(true)} onClick={() => setVisible(visible => !visible)}>{selectedTheme.themeName}
+
+
+ {themes.map((theme) => (
+ updateThemeWithStorage(theme)}>
+ {theme.themeName}
+
+ ))}
+
+
+ );
+ }
+ return themeselector;
}
export const StyleSelectorPlaceholder = () => {
diff --git a/components/windowsize.tsx b/components/windowsize.tsx
new file mode 100644
index 0000000..61f6ca7
--- /dev/null
+++ b/components/windowsize.tsx
@@ -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({
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/public/data/themes.json b/public/data/themes.json
index 18b4933..eeba534 100644
--- a/public/data/themes.json
+++ b/public/data/themes.json
@@ -52,6 +52,7 @@
"themeName": "Nordlys",
"themeId": 4,
"backgroundImage": "https://images4.alphacoders.com/112/1123390.jpg",
+ "backgroundOffset": "60%",
"invertButtons": true,
"colors": {
"background": "#0008",
diff --git a/styled.d.ts b/styled.d.ts
index 1dc2225..d774093 100644
--- a/styled.d.ts
+++ b/styled.d.ts
@@ -5,6 +5,7 @@ declare module 'styled-components' {
themeName: string,
themeId: number,
backgroundImage?: string,
+ backgroundOffset?: string,
invertButtons?: boolean,
colors: {
background: string,