Added support for gestures to open close menus
This commit is contained in:
parent
76deea2aa7
commit
7dd2325e97
|
@ -12,7 +12,8 @@
|
|||
"markdown-to-jsx": "^7.1.6",
|
||||
"next": "^12.0.7",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
"react-dom": "17.0.2",
|
||||
"react-swipeable": "^6.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.0",
|
||||
|
@ -3316,6 +3317,14 @@
|
|||
"react": "17.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/react-swipeable": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-swipeable/-/react-swipeable-6.2.0.tgz",
|
||||
"integrity": "sha512-nWQ8dEM8e/uswZLSIkXUsAnQmnX4MTcryOHBQIQYRMJFDpgDBSiVbKsz/BZVCIScF4NtJh16oyxwaNOepR6xSw==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.3 || ^17"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.4",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz",
|
||||
|
@ -6464,6 +6473,12 @@
|
|||
"scheduler": "^0.20.2"
|
||||
}
|
||||
},
|
||||
"react-swipeable": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-swipeable/-/react-swipeable-6.2.0.tgz",
|
||||
"integrity": "sha512-nWQ8dEM8e/uswZLSIkXUsAnQmnX4MTcryOHBQIQYRMJFDpgDBSiVbKsz/BZVCIScF4NtJh16oyxwaNOepR6xSw==",
|
||||
"requires": {}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.4",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz",
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
"markdown-to-jsx": "^7.1.6",
|
||||
"next": "^12.0.7",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2"
|
||||
"react-dom": "17.0.2",
|
||||
"react-swipeable": "^6.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/typography": "^0.5.0",
|
||||
|
|
|
@ -2,6 +2,7 @@ import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
|
|||
import MainPanel from "./Panels/MainPanel";
|
||||
import { useState } from "react";
|
||||
import Head from "next/head";
|
||||
import { useSwipeable } from "react-swipeable";
|
||||
|
||||
type AppLayoutProps = {
|
||||
subPanel?: React.ReactNode;
|
||||
|
@ -17,6 +18,14 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
const [mainPanelOpen, setMainPanelOpen] = useState(false);
|
||||
const [subPanelOpen, setsubPanelOpen] = useState(false);
|
||||
|
||||
const handlers = useSwipeable({
|
||||
onSwipedLeft: () =>
|
||||
mainPanelOpen ? setMainPanelOpen(false) : props.subPanel && props.contentPanel ? setsubPanelOpen(true) : "",
|
||||
onSwipedRight: () =>
|
||||
subPanelOpen ? setsubPanelOpen(false) : setMainPanelOpen(true),
|
||||
preventDefaultTouchmoveEvent: true,
|
||||
});
|
||||
|
||||
const mainPanelClass =
|
||||
"fixed desktop:left-0 desktop:top-0 desktop:bottom-0 desktop:w-[20rem]";
|
||||
const subPanelClass =
|
||||
|
@ -34,7 +43,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div {...handlers}>
|
||||
<Head>
|
||||
<title>
|
||||
{props.title ? `${titlePrefix} - ${props.title}` : titlePrefix}
|
||||
|
@ -75,7 +84,9 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
<div className="grid place-content-center h-full">
|
||||
<div className="text-dark border-dark border-2 border-dotted rounded-2xl p-8 grid grid-flow-col place-items-center gap-9">
|
||||
<p className="text-4xl">❮</p>
|
||||
<p className="text-2xl w-64">Select one of the options in the sidebar</p>
|
||||
<p className="text-2xl w-64">
|
||||
Select one of the options in the sidebar
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -99,7 +110,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
{/* Sub panel */}
|
||||
{props.subPanel ? (
|
||||
<div
|
||||
className={`${subPanelClass} border-r-[1px] mobile:border-r-0 mobile:border-l-[1px] border-black top-0 bottom-0 right-0 left-12 bg-light overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-500
|
||||
className={`${subPanelClass} border-r-[1px] mobile:border-r-0 mobile:border-l-[1px] border-black top-0 bottom-0 right-0 left-12 bg-light overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300
|
||||
${
|
||||
turnSubIntoContent
|
||||
? "mobile:mobile:translate-x-0 mobile:bottom-20 mobile:left-0 mobile:border-l-0"
|
||||
|
@ -115,11 +126,11 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
|
||||
{/* Main panel */}
|
||||
<div
|
||||
className={`${mainPanelClass} border-r-[1px] border-black top-0 bottom-0 left-0 right-12 bg-light overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-500 z-20
|
||||
className={`${mainPanelClass} border-r-[1px] border-black top-0 bottom-0 left-0 right-12 bg-light overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 z-20
|
||||
${mainPanelOpen ? "" : "mobile:-translate-x-full"}`}
|
||||
>
|
||||
<MainPanel langui={props.langui} />
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
import Link from "next/link";
|
||||
import { GetLibraryItemsPreviewQuery } from "graphql/operations-types";
|
||||
import { getAssetURL, prettyDate, prettyPrice } from "queries/helpers";
|
||||
import Image from "next/image";
|
||||
|
||||
export type LibraryContentPreviewProps = {
|
||||
item: {
|
||||
slug: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["slug"];
|
||||
thumbnail: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["thumbnail"];
|
||||
title: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["title"];
|
||||
subtitle: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["subtitle"];
|
||||
price?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["price"];
|
||||
release_date?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"];
|
||||
};
|
||||
};
|
||||
|
||||
export default function LibraryContentPreview(
|
||||
props: LibraryContentPreviewProps
|
||||
): JSX.Element {
|
||||
const item = props.item;
|
||||
|
||||
return (
|
||||
<Link href={"/library/media/" + item.slug} passHref>
|
||||
<div className="drop-shadow-dark-xl cursor-pointer grid items-end hover:rounded-3xl [--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform">
|
||||
{item.thumbnail.data ? (
|
||||
<Image
|
||||
src={getAssetURL(item.thumbnail.data.attributes.url)}
|
||||
alt={item.thumbnail.data.attributes.alternativeText}
|
||||
height={item.thumbnail.data.attributes.height}
|
||||
width={item.thumbnail.data.attributes.width}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full aspect-[21/29.7] bg-light rounded-lg"></div>
|
||||
)}
|
||||
<div className="linearbg-1 drop-shadow-dark-lg absolute bottom-2 inset-x-[-0.15rem] opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-4 text-left">
|
||||
<div>
|
||||
<h2 className="text-lg leading-7">{item.title}</h2>
|
||||
<h3 className="leading-3">{item.subtitle}</h3>
|
||||
</div>
|
||||
<div className="grid grid-flow-col">
|
||||
{item.release_date ? (
|
||||
<p className="text-sm">
|
||||
<span className="material-icons !text-base translate-y-[.15em] mr-1">
|
||||
event
|
||||
</span>
|
||||
{prettyDate(item.release_date)}
|
||||
</p>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
{item.price ? (
|
||||
<p className="text-sm justify-self-end">
|
||||
<span className="material-icons !text-base translate-y-[.15em] mr-1">
|
||||
shopping_cart
|
||||
</span>
|
||||
{prettyPrice(item.price)}
|
||||
</p>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ type PanelHeaderProps = {
|
|||
|
||||
export default function PanelHeader(props: PanelHeaderProps): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<div className="w-full grid place-items-center">
|
||||
{props.icon ? (
|
||||
<span className="material-icons !text-4xl mb-3">{props.icon}</span>
|
||||
|
@ -16,7 +17,8 @@ export default function PanelHeader(props: PanelHeaderProps): JSX.Element {
|
|||
)}
|
||||
<h2 className="text-2xl">{props.title}</h2>
|
||||
{props.description ? <p>{props.description}</p> : ""}
|
||||
<HorizontalLine />
|
||||
</div>
|
||||
<HorizontalLine />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import Button from "components/Button";
|
|||
import HorizontalLine from "components/HorizontalLine";
|
||||
import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
|
||||
import Markdown from "markdown-to-jsx";
|
||||
import Script from "next/script";
|
||||
|
||||
type MainPanelProps = {
|
||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
||||
|
@ -15,18 +16,21 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
const langui = props.langui;
|
||||
const router = useRouter();
|
||||
return (
|
||||
<div className="grid justify-center content-start p-8 gap-y-2 justify-items-center text-center">
|
||||
<div
|
||||
id="mainPanel"
|
||||
className="flex flex-col justify-center content-start p-8 gap-y-2 justify-items-center text-center"
|
||||
>
|
||||
<div className="">
|
||||
<div className="grid place-items-center">
|
||||
<div className="grid place-items-center mobile:grid-flow-col">
|
||||
<Link href="/" passHref>
|
||||
<div className="w-1/2 cursor-pointer transition-[filter] hover:colorize-dark">
|
||||
<div className="mobile:w-10 mobile:self-end w-1/2 cursor-pointer transition-[filter] hover:colorize-dark">
|
||||
<SVG
|
||||
src={"/icons/accords.svg"}
|
||||
alt={"Logo of Accord's Library"}
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="relative mt-5">
|
||||
<div className="relative mt-5 mobile:self-start">
|
||||
{router.locale ? (
|
||||
<Button className="absolute right-0 top-[-1.3em] text-xs !py-0.5 !px-2.5">
|
||||
{router.locale.toUpperCase()}
|
||||
|
|
|
@ -4,7 +4,7 @@ type SubPanelProps = {
|
|||
|
||||
export default function SubPanel(props: SubPanelProps): JSX.Element {
|
||||
return (
|
||||
<div className="grid p-8 gap-y-2 justify-items-center text-center">
|
||||
<div className="flex flex-col p-8 gap-y-2 justify-items-center text-center mobile:h-full">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -4,7 +4,6 @@ import SVG from "components/SVG";
|
|||
import { getWebsiteInterface } from "graphql/operations";
|
||||
import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
|
||||
import { GetStaticProps } from "next";
|
||||
import Script from "next/script";
|
||||
type HomeProps = {
|
||||
langui: GetWebsiteInterfaceQuery;
|
||||
};
|
||||
|
@ -24,19 +23,6 @@ export default function Home(props: HomeProps): JSX.Element {
|
|||
<h2 className="mt-0">Discover • Analyse • Translate • Archive</h2>
|
||||
</div>
|
||||
|
||||
<button id="goFS">Go fullscreen</button>
|
||||
<Script
|
||||
id="myScript"
|
||||
strategy="afterInteractive"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
var goFS = document.getElementById("goFS");
|
||||
goFS.addEventListener("click", function() {
|
||||
document.body.requestFullscreen();
|
||||
}, false);`,
|
||||
}}
|
||||
></Script>
|
||||
|
||||
<h2>What is this?</h2>
|
||||
<p>
|
||||
Accord’s Library aims at gathering and archiving all of Yoko
|
||||
|
|
|
@ -50,6 +50,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
|||
/>
|
||||
<HorizontalLine />
|
||||
|
||||
<div className="grid gap-4">
|
||||
<NavOption
|
||||
title={langui.library_item_summary}
|
||||
url="#summary"
|
||||
|
@ -101,6 +102,7 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
|||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
</SubPanel>
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in New Issue