Now using Tippy for Tooltips + prettier integration #11
|
@ -0,0 +1 @@
|
|||
.next
|
|
@ -10,6 +10,7 @@
|
|||
- Markdown format for the rich text fields
|
||||
|
||||
#### [Image Processor](https://github.com/Accords-Library/img.accords-library.com)
|
||||
|
||||
- Convert the images from the CMS to 4 formats
|
||||
- Small: 512x512, quality 60, .webp
|
||||
- Medium: 1024x1024, quality 75, .webp
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
"@fontsource/opendyslexic": "^4.5.2",
|
||||
"@fontsource/vollkorn": "^4.5.4",
|
||||
"@fontsource/zen-maru-gothic": "^4.5.5",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
"markdown-to-jsx": "^7.1.7",
|
||||
"next": "^12.1.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-swipeable": "^6.2.0",
|
||||
"react-tooltip": "^4.2.21",
|
||||
"turndown": "^7.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -448,12 +448,34 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.3.tgz",
|
||||
"integrity": "sha512-8U7hIl7+30XbIrJ0deQMXpXESM1L4yrt6BHok5hzcR0LivivuNkk+tHU1iRVScOwCmQcrOr6kvtIr29MNbQHqQ==",
|
||||
"hasInstallScript": true,
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@rushstack/eslint-patch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz",
|
||||
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tippyjs/react": {
|
||||
"version": "4.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@tippyjs/react/-/react-4.2.6.tgz",
|
||||
"integrity": "sha512-91RicDR+H7oDSyPycI13q3b7o4O60wa2oRbjlz2fyRLmHImc4vyDwuUP8NtZaN0VARJY5hybvDYrFzhY9+Lbyw==",
|
||||
"dependencies": {
|
||||
"tippy.js": "^6.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8",
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/json5": {
|
||||
"version": "0.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||
|
@ -2960,6 +2982,7 @@
|
|||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
|
@ -3035,7 +3058,8 @@
|
|||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/react-swipeable": {
|
||||
"version": "6.2.0",
|
||||
|
@ -3045,22 +3069,6 @@
|
|||
"react": "^16.8.3 || ^17"
|
||||
}
|
||||
},
|
||||
"node_modules/react-tooltip": {
|
||||
"version": "4.2.21",
|
||||
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz",
|
||||
"integrity": "sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.7.2",
|
||||
"uuid": "^7.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"npm": ">=6.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.0.0",
|
||||
"react-dom": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
|
@ -3424,6 +3432,14 @@
|
|||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tippy.js": {
|
||||
"version": "6.3.7",
|
||||
"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz",
|
||||
"integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
|
@ -3555,14 +3571,6 @@
|
|||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
|
||||
"integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==",
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/v8-compile-cache": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
|
||||
|
@ -3917,12 +3925,25 @@
|
|||
"fastq": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@popperjs/core": {
|
||||
"version": "2.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.3.tgz",
|
||||
"integrity": "sha512-8U7hIl7+30XbIrJ0deQMXpXESM1L4yrt6BHok5hzcR0LivivuNkk+tHU1iRVScOwCmQcrOr6kvtIr29MNbQHqQ=="
|
||||
},
|
||||
"@rushstack/eslint-patch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz",
|
||||
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
||||
"dev": true
|
||||
},
|
||||
"@tippyjs/react": {
|
||||
"version": "4.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@tippyjs/react/-/react-4.2.6.tgz",
|
||||
"integrity": "sha512-91RicDR+H7oDSyPycI13q3b7o4O60wa2oRbjlz2fyRLmHImc4vyDwuUP8NtZaN0VARJY5hybvDYrFzhY9+Lbyw==",
|
||||
"requires": {
|
||||
"tippy.js": "^6.3.1"
|
||||
}
|
||||
},
|
||||
"@types/json5": {
|
||||
"version": "0.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||
|
@ -5740,6 +5761,7 @@
|
|||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
|
@ -5786,7 +5808,8 @@
|
|||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"react-swipeable": {
|
||||
"version": "6.2.0",
|
||||
|
@ -5794,15 +5817,6 @@
|
|||
"integrity": "sha512-nWQ8dEM8e/uswZLSIkXUsAnQmnX4MTcryOHBQIQYRMJFDpgDBSiVbKsz/BZVCIScF4NtJh16oyxwaNOepR6xSw==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-tooltip": {
|
||||
"version": "4.2.21",
|
||||
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.21.tgz",
|
||||
"integrity": "sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2",
|
||||
"uuid": "^7.0.3"
|
||||
}
|
||||
},
|
||||
"readdirp": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
|
@ -6043,6 +6057,14 @@
|
|||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||
"dev": true
|
||||
},
|
||||
"tippy.js": {
|
||||
"version": "6.3.7",
|
||||
"resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz",
|
||||
"integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==",
|
||||
"requires": {
|
||||
"@popperjs/core": "^2.9.0"
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
|
@ -6143,11 +6165,6 @@
|
|||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"dev": true
|
||||
},
|
||||
"uuid": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz",
|
||||
"integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="
|
||||
},
|
||||
"v8-compile-cache": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
"@fontsource/opendyslexic": "^4.5.2",
|
||||
"@fontsource/vollkorn": "^4.5.4",
|
||||
"@fontsource/zen-maru-gothic": "^4.5.5",
|
||||
"@tippyjs/react": "^4.2.6",
|
||||
"markdown-to-jsx": "^7.1.7",
|
||||
"next": "^12.1.0",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react-swipeable": "^6.2.0",
|
||||
"react-tooltip": "^4.2.21",
|
||||
"turndown": "^7.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -2,5 +2,5 @@ module.exports = {
|
|||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -21,4 +21,4 @@ Insert the following code in the `head` section of your pages:
|
|||
<meta name="msapplication-TileImage" content="/mstile-144x144.png">
|
||||
<meta name="theme-color" content="#feecd6">
|
||||
|
||||
*Optional* - Check your favicon with the [favicon checker](https://realfavicongenerator.net/favicon_checker)
|
||||
_Optional_ - Check your favicon with the [favicon checker](https://realfavicongenerator.net/favicon_checker)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||
<link rel="manifest" href="/site.webmanifest">
|
||||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#9c6644">
|
||||
<meta name="apple-mobile-web-app-title" content="Accord's Library">
|
||||
<meta name="application-name" content="Accord's Library">
|
||||
<meta name="msapplication-TileColor" content="#feecd6">
|
||||
<meta name="msapplication-TileImage" content="/mstile-144x144.png">
|
||||
<meta name="theme-color" content="#feecd6">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#9c6644" />
|
||||
<meta name="apple-mobile-web-app-title" content="Accord's Library" />
|
||||
<meta name="application-name" content="Accord's Library" />
|
||||
<meta name="msapplication-TileColor" content="#feecd6" />
|
||||
<meta name="msapplication-TileImage" content="/mstile-144x144.png" />
|
||||
<meta name="theme-color" content="#feecd6" />
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
npx prettier --end-of-line auto --write .
|
|
@ -7,9 +7,8 @@ import Head from "next/head";
|
|||
import { useSwipeable } from "react-swipeable";
|
||||
import { useRouter } from "next/router";
|
||||
import Button from "components/Button";
|
||||
import { getOgImage, OgImage, prettyLanguage } from "queries/helpers";
|
||||
import { getOgImage, OgImage } from "queries/helpers";
|
||||
import { useMediaCoarse, useMediaMobile } from "hooks/useMediaQuery";
|
||||
import ReactTooltip from "react-tooltip";
|
||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
import { ImageQuality } from "./Img";
|
||||
import Popup from "./Popup";
|
||||
|
@ -25,7 +24,6 @@ interface AppLayoutProps extends AppStaticProps {
|
|||
navTitle: string;
|
||||
thumbnail?: StrapiImage;
|
||||
description?: string;
|
||||
extra?: React.ReactNode;
|
||||
}
|
||||
|
||||
export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
||||
|
@ -56,27 +54,6 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
},
|
||||
});
|
||||
|
||||
const mainPanelClass = `fixed desktop:left-0 desktop:top-0 desktop:bottom-0 ${
|
||||
appLayout.mainPanelReduced ? "desktop:w-[6rem]" : "desktop:w-[20rem]"
|
||||
}`;
|
||||
const subPanelClass = `fixed desktop:top-0 desktop:bottom-0 desktop:w-[20rem] ${
|
||||
appLayout.mainPanelReduced ? " desktop:left-[6rem]" : "desktop:left-[20rem]"
|
||||
}`;
|
||||
let contentPanelClass = "";
|
||||
if (subPanel) {
|
||||
contentPanelClass = `fixed desktop:top-0 desktop:bottom-0 desktop:right-0 ${
|
||||
appLayout.mainPanelReduced
|
||||
? "desktop:left-[26rem]"
|
||||
: "desktop:left-[40rem]"
|
||||
}`;
|
||||
} else if (contentPanel) {
|
||||
contentPanelClass = `fixed desktop:top-0 desktop:bottom-0 desktop:right-0 ${
|
||||
appLayout.mainPanelReduced
|
||||
? "desktop:left-[6rem]"
|
||||
: "desktop:left-[20rem]"
|
||||
}`;
|
||||
}
|
||||
|
||||
const turnSubIntoContent = subPanel && !contentPanel;
|
||||
|
||||
const titlePrefix = "Accord’s Library";
|
||||
|
@ -117,6 +94,21 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currencySelect]);
|
||||
|
||||
let gridCol = "";
|
||||
if (props.subPanel) {
|
||||
if (appLayout.mainPanelReduced) {
|
||||
gridCol = "grid-cols-[6rem_20rem_1fr]";
|
||||
} else {
|
||||
gridCol = "grid-cols-[20rem_20rem_1fr]";
|
||||
}
|
||||
} else {
|
||||
if (appLayout.mainPanelReduced) {
|
||||
gridCol = "grid-cols-[6rem_0px_1fr]";
|
||||
} else {
|
||||
gridCol = "grid-cols-[20rem_0px_1fr]";
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${
|
||||
|
@ -129,7 +121,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
>
|
||||
<div
|
||||
{...handlers}
|
||||
className="fixed inset-0 touch-pan-y p-0 m-0 bg-light text-black"
|
||||
className={`fixed inset-0 touch-pan-y p-0 m-0 bg-light text-black grid [grid-template-areas:'main_sub_content'] ${gridCol} mobile:grid-cols-[1fr] mobile:grid-rows-[1fr_5rem] mobile:[grid-template-areas:'content''navbar']`}
|
||||
>
|
||||
<Head>
|
||||
<title>{`${titlePrefix} - ${ogTitle}`}</title>
|
||||
|
@ -159,9 +151,32 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
<meta name="twitter:image" content={metaImage.image}></meta>
|
||||
</Head>
|
||||
|
||||
{/* Background when navbar is opened */}
|
||||
<div
|
||||
className={`[grid-area:content] mobile:z-10 absolute inset-0 transition-[backdrop-filter] duration-500 ${
|
||||
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
|
||||
? "[backdrop-filter:blur(2px)]"
|
||||
: "pointer-events-none touch-none "
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`absolute bg-shade inset-0 transition-opacity duration-500
|
||||
${turnSubIntoContent ? "" : ""}
|
||||
${
|
||||
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
|
||||
? "opacity-60"
|
||||
: "opacity-0"
|
||||
}`}
|
||||
onClick={() => {
|
||||
appLayout.setMainPanelOpen(false);
|
||||
appLayout.setSubPanelOpen(false);
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
|
||||
{/* Content panel */}
|
||||
<div
|
||||
className={`top-0 left-0 right-0 bottom-20 overflow-y-scroll bg-light texture-paper-dots ${contentPanelClass}`}
|
||||
className={`[grid-area:content] overflow-y-scroll bg-light texture-paper-dots`}
|
||||
>
|
||||
{contentPanel ? (
|
||||
contentPanel
|
||||
|
@ -175,38 +190,15 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* Background when navbar is opened */}
|
||||
<div
|
||||
className={`fixed inset-0 transition-[backdrop-filter] duration-500 ${
|
||||
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
|
||||
? "[backdrop-filter:blur(2px)]"
|
||||
: "pointer-events-none touch-none "
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`fixed bg-shade inset-0 transition-opacity duration-500
|
||||
${turnSubIntoContent ? "z-10" : ""}
|
||||
${
|
||||
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
|
||||
? "opacity-60"
|
||||
: "opacity-0"
|
||||
}`}
|
||||
onClick={() => {
|
||||
appLayout.setMainPanelOpen(false);
|
||||
appLayout.setSubPanelOpen(false);
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
|
||||
{/* Sub panel */}
|
||||
{subPanel && (
|
||||
<div
|
||||
className={`${subPanelClass} border-r-[1px] mobile:bottom-20 mobile:border-r-0 mobile:border-l-[1px] border-black border-dotted top-0 bottom-0 right-0 left-12 overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 bg-light texture-paper-dots
|
||||
className={`[grid-area:sub] mobile:[grid-area:content] mobile:z-10 mobile:w-[90%] mobile:justify-self-end border-r-[1px] mobile:border-r-0 mobile:border-l-[1px] border-black border-dotted overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 bg-light texture-paper-dots
|
||||
${
|
||||
turnSubIntoContent
|
||||
? "mobile:translate-x-0 mobile:left-0 mobile:border-l-0"
|
||||
? "mobile:border-l-0 mobile:w-full"
|
||||
: !appLayout.subPanelOpen
|
||||
? "mobile:translate-x-full"
|
||||
? "mobile:translate-x-[100vw]"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
|
@ -216,28 +208,14 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
|
||||
{/* Main panel */}
|
||||
<div
|
||||
className={`${mainPanelClass} border-r-[1px] mobile:bottom-20 border-black border-dotted top-0 bottom-0 left-0 right-12 overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 z-20 bg-light texture-paper-dots
|
||||
className={`[grid-area:main] mobile:[grid-area:content] mobile:z-10 mobile:w-[90%] mobile:justify-self-start border-r-[1px] border-black border-dotted overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 bg-light texture-paper-dots
|
||||
${appLayout.mainPanelOpen ? "" : "mobile:-translate-x-full"}`}
|
||||
>
|
||||
<MainPanel langui={langui} />
|
||||
</div>
|
||||
|
||||
{/* Main panel minimize button*/}
|
||||
<div
|
||||
className={`mobile:hidden translate-x-0 fixed top-1/2 z-20 ${
|
||||
appLayout.mainPanelReduced ? "left-[4.65rem]" : "left-[18.65rem]"
|
||||
}`}
|
||||
onClick={() =>
|
||||
appLayout.setMainPanelReduced(!appLayout.mainPanelReduced)
|
||||
}
|
||||
>
|
||||
<Button className="material-icons bg-light !px-2">
|
||||
{appLayout.mainPanelReduced ? "chevron_right" : "chevron_left"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Navbar */}
|
||||
<div className="fixed inset-0 z-30 top-auto h-20 border-t-[1px] border-black border-dotted grid grid-cols-[5rem_1fr_5rem] place-items-center desktop:hidden bg-light texture-paper-dots">
|
||||
<div className="[grid-area:navbar] border-t-[1px] border-black border-dotted grid grid-cols-[5rem_1fr_5rem] place-items-center desktop:hidden bg-light texture-paper-dots">
|
||||
<span
|
||||
className="material-icons mt-[.1em] cursor-pointer"
|
||||
onClick={() => {
|
||||
|
@ -413,20 +391,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
</div>
|
||||
</div>
|
||||
</Popup>
|
||||
|
||||
<ReactTooltip
|
||||
id="MainPanelTooltip"
|
||||
place="right"
|
||||
type="light"
|
||||
effect="solid"
|
||||
delayShow={300}
|
||||
delayHide={100}
|
||||
disable={!appLayout.mainPanelReduced || isMobile || isCoarse}
|
||||
className="drop-shadow-shade-xl !opacity-100 !bg-light !rounded-lg after:!border-r-light text-left !text-black"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{props.extra}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,25 +1,14 @@
|
|||
import { MouseEventHandler } from "react";
|
||||
|
||||
type ChipProps = {
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
"data-tip"?: string;
|
||||
"data-for"?: string;
|
||||
"data-html"?: boolean;
|
||||
"data-multiline"?: boolean;
|
||||
};
|
||||
|
||||
export default function Chip(props: ChipProps): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className={`grid place-content-center place-items-center text-xs pb-[0.14rem] px-1.5 border-[1px] rounded-full opacity-70 transition-[color,_opacity,border-color] ${
|
||||
props.className
|
||||
} ${
|
||||
props["data-tip"] &&
|
||||
"hover:text-dark hover:border-dark hover:opacity-100"
|
||||
}`}
|
||||
data-tip={props["data-tip"]}
|
||||
data-for={props["data-for"]}
|
||||
data-html={props["data-html"]}
|
||||
data-multiline={props["data-multiline"]}
|
||||
className={`grid relative place-content-center place-items-center text-xs pb-[0.14rem] px-1.5 border-[1px] rounded-full opacity-70 transition-[color,_opacity,_border-color] hover:opacity-100 ${props.className}`}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
import Chip from "components/Chip";
|
||||
import ToolTip from "components/ToolTip";
|
||||
import {
|
||||
Enum_Componenttranslationschronologyitem_Status,
|
||||
GetChronologyItemsQuery,
|
||||
GetWebsiteInterfaceQuery,
|
||||
} from "graphql/operations-types";
|
||||
import { getStatusDescription } from "queries/helpers";
|
||||
|
||||
export type ChronologyItemComponentProps = {
|
||||
item: GetChronologyItemsQuery["chronologyItems"]["data"][number];
|
||||
displayYear: boolean;
|
||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
||||
};
|
||||
|
||||
export default function ChronologyItemComponent(
|
||||
props: ChronologyItemComponentProps
|
||||
): JSX.Element {
|
||||
const { langui } = props;
|
||||
|
||||
function generateAnchor(year: number, month: number, day: number): string {
|
||||
let result: string = "";
|
||||
result += year;
|
||||
|
@ -85,23 +91,12 @@ export default function ChronologyItemComponent(
|
|||
<div className="place-items-start place-content-start grid grid-flow-col gap-2">
|
||||
{translation.status !==
|
||||
Enum_Componenttranslationschronologyitem_Status.Done && (
|
||||
<Chip
|
||||
data-tip={
|
||||
translation.status ===
|
||||
Enum_Componenttranslationschronologyitem_Status.Incomplete
|
||||
? "This entry is only partially translated/transcribed."
|
||||
: translation.status ===
|
||||
Enum_Componenttranslationschronologyitem_Status.Draft
|
||||
? "This entry is just a draft. It usually means that this is a work-in-progress. Translation/transcription might be poor and/or computer-generated."
|
||||
: translation.status ===
|
||||
Enum_Componenttranslationschronologyitem_Status.Review
|
||||
? "This entry has not yet being proofread. The content should still be accurate."
|
||||
: ""
|
||||
}
|
||||
data-for={"ChronologyTooltip"}
|
||||
<ToolTip
|
||||
content={getStatusDescription(translation.status, langui)}
|
||||
maxWidth={"20rem"}
|
||||
>
|
||||
{translation.status}
|
||||
</Chip>
|
||||
<Chip>{translation.status}</Chip>
|
||||
</ToolTip>
|
||||
)}
|
||||
{translation.title ? <h3>{translation.title}</h3> : ""}
|
||||
</div>
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
import ChronologyItemComponent from "components/Chronology/ChronologyItemComponent";
|
||||
import { GetChronologyItemsQuery } from "graphql/operations-types";
|
||||
import {
|
||||
GetChronologyItemsQuery,
|
||||
GetWebsiteInterfaceQuery,
|
||||
} from "graphql/operations-types";
|
||||
|
||||
type ChronologyYearComponentProps = {
|
||||
year: number;
|
||||
items: GetChronologyItemsQuery["chronologyItems"]["data"][number][];
|
||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
||||
};
|
||||
|
||||
export default function ChronologyYearComponent(
|
||||
props: ChronologyYearComponentProps
|
||||
): JSX.Element {
|
||||
const { langui } = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="target:bg-mid rounded-2xl target:py-4 target:my-4"
|
||||
|
@ -19,6 +25,7 @@ export default function ChronologyYearComponent(
|
|||
key={index}
|
||||
item={item}
|
||||
displayYear={index === 0}
|
||||
langui={langui}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
@ -55,7 +55,7 @@ export default function LibraryItemsPreview(
|
|||
<h3 className="mobile:text-xs leading-3">{item.subtitle}</h3>
|
||||
</div>
|
||||
|
||||
<div className="w-full grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start">
|
||||
<div className="w-full grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:h-0 [scrollbar-width:none] place-content-start">
|
||||
{item.categories.data.map((category) => (
|
||||
<Chip key={category.id} className="text-sm">
|
||||
{category.attributes.short}
|
||||
|
|
|
@ -21,6 +21,38 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
|
|||
options={{
|
||||
slugify: slugify,
|
||||
overrides: {
|
||||
h2: {
|
||||
component: (props: {
|
||||
id: string;
|
||||
style: React.CSSProperties;
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
return (
|
||||
<h2
|
||||
id={props.id}
|
||||
className="flex flex-row place-items-center place-content-center gap-3 hover:[--anchor-opacity:100] [--anchor-opacity:0]"
|
||||
style={props.style}
|
||||
>
|
||||
{props.children}
|
||||
<abbr title="Copy anchor link">
|
||||
<span
|
||||
className="material-icons opacity-[var(--anchor-opacity)] transition-all hover:text-dark cursor-pointer"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(
|
||||
process.env.NEXT_PUBLIC_URL_SELF +
|
||||
window.location.pathname +
|
||||
"#" +
|
||||
props.id
|
||||
);
|
||||
}}
|
||||
>
|
||||
link
|
||||
</span>
|
||||
</abbr>
|
||||
</h2>
|
||||
);
|
||||
},
|
||||
},
|
||||
Sep: {
|
||||
component: () => {
|
||||
return <div className="my-24"></div>;
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
import { NextRouter } from "next/router";
|
||||
import { slugify } from "queries/helpers";
|
||||
import { preprocessMarkDawn } from "./Markdawn";
|
||||
|
||||
type TOCProps = {
|
||||
text: string;
|
||||
title?: string;
|
||||
router: NextRouter;
|
||||
};
|
||||
|
||||
export default function TOC(props: TOCProps): JSX.Element {
|
||||
const toc = getTocFromMarkdawn(preprocessMarkDawn(props.text), props.title);
|
||||
const { router, text, title } = props;
|
||||
const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h3 className="text-xl">Table of content</h3>
|
||||
<ol className="text-left">
|
||||
<li className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap">
|
||||
<a className="" href={`#${toc.slug}`}>
|
||||
<a className="" onClick={() => router.replace(`#${toc.slug}`)}>
|
||||
{<abbr title={toc.title}>{toc.title}</abbr>}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -25,7 +28,7 @@ export default function TOC(props: TOCProps): JSX.Element {
|
|||
className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap"
|
||||
>
|
||||
<span className="text-dark">{`${h2Index + 1}. `}</span>
|
||||
<a href={`#${h2.slug}`}>
|
||||
<a onClick={() => router.replace(`#${h2.slug}`)}>
|
||||
{<abbr title={h2.title}>{h2.title}</abbr>}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -38,7 +41,7 @@ export default function TOC(props: TOCProps): JSX.Element {
|
|||
<span className="text-dark">{`${h2Index + 1}.${
|
||||
h3Index + 1
|
||||
}. `}</span>
|
||||
<a href={`#${h3.slug}`}>
|
||||
<a onClick={() => router.replace(`#${h3.slug}`)}>
|
||||
{<abbr title={h3.title}>{h3.title}</abbr>}
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import { useRouter } from "next/router";
|
||||
import Link from "next/link";
|
||||
import { MouseEventHandler } from "react";
|
||||
import ReactDOMServer from "react-dom/server";
|
||||
import ToolTip from "components/ToolTip";
|
||||
|
||||
type NavOptionProps = {
|
||||
url: string;
|
||||
icon?: string;
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
tooltipId?: string;
|
||||
border?: boolean;
|
||||
reduced?: boolean;
|
||||
onClick?: MouseEventHandler<HTMLDivElement>;
|
||||
|
@ -25,35 +24,38 @@ export default function NavOption(props: NavOptionProps): JSX.Element {
|
|||
} ${isActive ? divActive : ""}`;
|
||||
|
||||
return (
|
||||
<Link href={props.url} passHref>
|
||||
<div
|
||||
onClick={props.onClick}
|
||||
data-html
|
||||
data-multiline
|
||||
data-tip={ReactDOMServer.renderToStaticMarkup(
|
||||
<div className="px-4 py-3">
|
||||
<h3 className="text-2xl">{props.title}</h3>
|
||||
{props.subtitle && (
|
||||
<p className="max-w-[10rem]">{props.subtitle}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
data-for={props.tooltipId}
|
||||
className={`grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${
|
||||
props.icon ? "text-left" : "text-center"
|
||||
} ${divCommon}`}
|
||||
>
|
||||
{props.icon && (
|
||||
<span className="material-icons mt-[.1em]">{props.icon}</span>
|
||||
)}
|
||||
<ToolTip
|
||||
content={
|
||||
<div>
|
||||
<h3 className="text-2xl">{props.title}</h3>
|
||||
{props.subtitle && <p className="col-start-2">{props.subtitle}</p>}
|
||||
</div>
|
||||
}
|
||||
placement="right"
|
||||
className="text-left"
|
||||
disabled={!props.reduced}
|
||||
>
|
||||
<Link href={props.url} passHref>
|
||||
<div
|
||||
onClick={props.onClick}
|
||||
className={`relative grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${
|
||||
props.icon ? "text-left" : "text-center"
|
||||
} ${divCommon}`}
|
||||
>
|
||||
{props.icon && (
|
||||
<span className="material-icons mt-[.1em]">{props.icon}</span>
|
||||
)}
|
||||
|
||||
{!props.reduced && (
|
||||
<div>
|
||||
<h3 className="text-2xl">{props.title}</h3>
|
||||
{props.subtitle && <p className="col-start-2">{props.subtitle}</p>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
{!props.reduced && (
|
||||
<div>
|
||||
<h3 className="text-2xl">{props.title}</h3>
|
||||
{props.subtitle && (
|
||||
<p className="col-start-2">{props.subtitle}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Link>
|
||||
</ToolTip>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
|
|||
import Markdown from "markdown-to-jsx";
|
||||
import { useMediaDesktop } from "hooks/useMediaQuery";
|
||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
import ToolTip from "components/ToolTip";
|
||||
|
||||
type MainPanelProps = {
|
||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
||||
|
@ -24,6 +25,20 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
appLayout.mainPanelReduced && isDesktop && "px-4"
|
||||
}`}
|
||||
>
|
||||
{/* Reduce/expand main menu */}
|
||||
<div
|
||||
className={`mobile:hidden top-1/2 fixed ${
|
||||
appLayout.mainPanelReduced ? "left-[4.65rem]" : "left-[18.65rem]"
|
||||
}`}
|
||||
onClick={() =>
|
||||
appLayout.setMainPanelReduced(!appLayout.mainPanelReduced)
|
||||
}
|
||||
>
|
||||
<Button className="material-icons bg-light !px-2">
|
||||
{appLayout.mainPanelReduced ? "chevron_right" : "chevron_left"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="grid place-items-center">
|
||||
<Link href="/" passHref>
|
||||
|
@ -48,49 +63,74 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
: "flex-row"
|
||||
} flex-wrap gap-2`}
|
||||
>
|
||||
<Button
|
||||
className={
|
||||
appLayout.mainPanelReduced && isDesktop ? "" : "!py-0.5 !px-2.5"
|
||||
}
|
||||
onClick={() => {
|
||||
appLayout.setConfigPanelOpen(true);
|
||||
}}
|
||||
<ToolTip
|
||||
content={<h3 className="text-2xl">{"Open settings"}</h3>}
|
||||
placement="right"
|
||||
className="text-left"
|
||||
disabled={!appLayout.mainPanelReduced}
|
||||
>
|
||||
<span
|
||||
className={`material-icons ${
|
||||
!(appLayout.mainPanelReduced && isDesktop) && "!text-sm"
|
||||
} `}
|
||||
>
|
||||
settings
|
||||
</span>
|
||||
</Button>
|
||||
|
||||
{router.locale && (
|
||||
<Button
|
||||
onClick={() => appLayout.setLanguagePanelOpen(true)}
|
||||
className={
|
||||
appLayout.mainPanelReduced && isDesktop
|
||||
? ""
|
||||
: "!py-0.5 !px-2.5 !text-sm"
|
||||
: "!py-0.5 !px-2.5"
|
||||
}
|
||||
onClick={() => {
|
||||
appLayout.setConfigPanelOpen(true);
|
||||
}}
|
||||
>
|
||||
{router.locale.toUpperCase()}
|
||||
<span
|
||||
className={`material-icons ${
|
||||
!(appLayout.mainPanelReduced && isDesktop) && "!text-sm"
|
||||
} `}
|
||||
>
|
||||
settings
|
||||
</span>
|
||||
</Button>
|
||||
</ToolTip>
|
||||
|
||||
{router.locale && (
|
||||
<ToolTip
|
||||
content={<h3 className="text-2xl">{"Change language"}</h3>}
|
||||
placement="right"
|
||||
className="text-left"
|
||||
disabled={!appLayout.mainPanelReduced}
|
||||
>
|
||||
<Button
|
||||
onClick={() => appLayout.setLanguagePanelOpen(true)}
|
||||
className={
|
||||
appLayout.mainPanelReduced && isDesktop
|
||||
? ""
|
||||
: "!py-0.5 !px-2.5 !text-sm"
|
||||
}
|
||||
>
|
||||
{router.locale.toUpperCase()}
|
||||
</Button>
|
||||
</ToolTip>
|
||||
)}
|
||||
|
||||
<Button
|
||||
className={
|
||||
appLayout.mainPanelReduced && isDesktop ? "" : "!py-0.5 !px-2.5"
|
||||
}
|
||||
<ToolTip
|
||||
content={<h3 className="text-2xl">{"Open search"}</h3>}
|
||||
placement="right"
|
||||
className="text-left"
|
||||
disabled={!appLayout.mainPanelReduced}
|
||||
>
|
||||
<span
|
||||
className={`material-icons ${
|
||||
!(appLayout.mainPanelReduced && isDesktop) && "!text-sm"
|
||||
} `}
|
||||
<Button
|
||||
className={
|
||||
appLayout.mainPanelReduced && isDesktop
|
||||
? ""
|
||||
: "!py-0.5 !px-2.5"
|
||||
}
|
||||
>
|
||||
search
|
||||
</span>
|
||||
</Button>
|
||||
<span
|
||||
className={`material-icons ${
|
||||
!(appLayout.mainPanelReduced && isDesktop) && "!text-sm"
|
||||
} `}
|
||||
>
|
||||
search
|
||||
</span>
|
||||
</Button>
|
||||
</ToolTip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -102,7 +142,6 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
icon="library_books"
|
||||
title={langui.library}
|
||||
subtitle={langui.library_short_description}
|
||||
tooltipId="MainPanelTooltip"
|
||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
@ -112,7 +151,6 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
icon="workspaces"
|
||||
title={langui.contents}
|
||||
subtitle={langui.contents_short_description}
|
||||
tooltipId="MainPanelTooltip"
|
||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
@ -124,7 +162,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
icon="travel_explore"
|
||||
title={langui.wiki}
|
||||
subtitle={langui.wiki_short_description}
|
||||
tooltipId="MainPanelTooltip"
|
||||
|
||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
@ -134,7 +172,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
icon="watch_later"
|
||||
title={langui.chronicles}
|
||||
subtitle={langui.chronicles_short_description}
|
||||
tooltipId="MainPanelTooltip"
|
||||
|
||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
@ -147,7 +185,6 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
url="/news"
|
||||
icon="feed"
|
||||
title={langui.news}
|
||||
tooltipId="MainPanelTooltip"
|
||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
@ -156,7 +193,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
url="/merch"
|
||||
icon="store"
|
||||
title={langui.merch}
|
||||
tooltipId="MainPanelTooltip"
|
||||
|
||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
@ -167,7 +204,6 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
url="/gallery"
|
||||
icon="collections"
|
||||
title={langui.gallery}
|
||||
tooltipId="MainPanelTooltip"
|
||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
@ -178,7 +214,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
url="/archives"
|
||||
icon="inventory"
|
||||
title={langui.archives}
|
||||
tooltipId="MainPanelTooltip"
|
||||
|
||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
@ -190,7 +226,6 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
|||
url="/about-us"
|
||||
icon="info"
|
||||
title={langui.about_us}
|
||||
tooltipId="MainPanelTooltip"
|
||||
reduced={appLayout.mainPanelReduced && isDesktop}
|
||||
onClick={() => appLayout.setMainPanelOpen(false)}
|
||||
/>
|
||||
|
|
|
@ -4,7 +4,7 @@ type SubPanelProps = {
|
|||
|
||||
export default function SubPanel(props: SubPanelProps): JSX.Element {
|
||||
return (
|
||||
<div className="flex flex-col p-8 gap-y-2 justify-items-center text-center mobile:h-full">
|
||||
<div className="grid pt-10 pb-20 px-6 desktop:py-8 desktop:px-10 gap-y-2 text-center">
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -11,7 +11,9 @@ export default function Popup(props: PopupProps): JSX.Element {
|
|||
return (
|
||||
<div
|
||||
className={`fixed inset-0 z-50 grid place-content-center transition-[backdrop-filter] duration-500 ${
|
||||
props.state ? "[backdrop-filter:blur(2px)]" : "pointer-events-none touch-none"
|
||||
props.state
|
||||
? "[backdrop-filter:blur(2px)]"
|
||||
: "pointer-events-none touch-none"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
|
|
|
@ -4,7 +4,7 @@ import {
|
|||
GetWebsiteInterfaceQuery,
|
||||
} from "graphql/operations-types";
|
||||
import Img, { ImageQuality } from "./Img";
|
||||
import ReactDOMServer from "react-dom/server";
|
||||
import ToolTip from "./ToolTip";
|
||||
|
||||
type RecorderChipProps = {
|
||||
className?: string;
|
||||
|
@ -15,10 +15,10 @@ type RecorderChipProps = {
|
|||
export default function RecorderChip(props: RecorderChipProps): JSX.Element {
|
||||
const recorder = props.recorder;
|
||||
const langui = props.langui;
|
||||
|
||||
return (
|
||||
<Chip
|
||||
key={recorder.id}
|
||||
data-tip={ReactDOMServer.renderToStaticMarkup(
|
||||
<ToolTip
|
||||
content={
|
||||
<div className="p-2 py-5 grid gap-2">
|
||||
<div className="grid grid-flow-col gap-2 place-items-center place-content-start">
|
||||
{recorder.attributes.avatar.data && (
|
||||
|
@ -52,14 +52,14 @@ export default function RecorderChip(props: RecorderChipProps): JSX.Element {
|
|||
recorder.attributes.bio[0].bio}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
data-for={"RecordersTooltip"}
|
||||
data-multiline
|
||||
data-html
|
||||
}
|
||||
placement="top"
|
||||
>
|
||||
{recorder.attributes.anonymize
|
||||
? `Recorder#${recorder.attributes.anonymous_code}`
|
||||
: recorder.attributes.username}
|
||||
</Chip>
|
||||
<Chip key={recorder.id}>
|
||||
{recorder.attributes.anonymize
|
||||
? `Recorder#${recorder.attributes.anonymous_code}`
|
||||
: recorder.attributes.username}
|
||||
</Chip>
|
||||
</ToolTip>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import Tippy, { TippyProps } from "@tippyjs/react";
|
||||
import "tippy.js/animations/scale-subtle.css";
|
||||
|
||||
interface ToolTipProps extends TippyProps {}
|
||||
|
||||
export default function ToolTip(props: ToolTipProps): JSX.Element {
|
||||
let newProps = { ...props };
|
||||
|
||||
// Set defaults
|
||||
if (newProps.delay === undefined) newProps.delay = [150, 0];
|
||||
if (newProps.interactive === undefined) newProps.interactive = true;
|
||||
if (newProps.animation === undefined) newProps.animation = "scale-subtle";
|
||||
|
||||
return (
|
||||
<Tippy {...newProps}>
|
||||
<div>{props.children}</div>
|
||||
</Tippy>
|
||||
);
|
||||
}
|
|
@ -2,7 +2,7 @@ import type { AppProps } from "next/app";
|
|||
import "tailwind.css";
|
||||
import "@fontsource/zen-maru-gothic/500.css";
|
||||
import "@fontsource/vollkorn/700.css";
|
||||
import "@fontsource/opendyslexic/400.css"
|
||||
import "@fontsource/opendyslexic/400.css";
|
||||
import "@fontsource/material-icons";
|
||||
|
||||
import { AppContextProvider } from "contexts/AppLayoutContext";
|
||||
|
|
|
@ -16,7 +16,6 @@ class MyDocument extends Document {
|
|||
return (
|
||||
<Html>
|
||||
<Head>
|
||||
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
|
|
|
@ -14,6 +14,7 @@ import ThumbnailHeader from "components/Content/ThumbnailHeader";
|
|||
import AppLayout from "components/AppLayout";
|
||||
import Markdawn from "components/Markdown/Markdawn";
|
||||
import {
|
||||
getStatusDescription,
|
||||
prettyinlineTitle,
|
||||
prettyLanguage,
|
||||
prettySlug,
|
||||
|
@ -23,10 +24,10 @@ import {
|
|||
import Button from "components/Button";
|
||||
import { useRouter } from "next/router";
|
||||
import Chip from "components/Chip";
|
||||
import ReactTooltip from "react-tooltip";
|
||||
import RecorderChip from "components/RecorderChip";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
import TOC from "components/Markdown/TOC";
|
||||
import ToolTip from "components/ToolTip";
|
||||
|
||||
interface ContentReadProps extends AppStaticProps {
|
||||
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
||||
|
@ -35,7 +36,7 @@ interface ContentReadProps extends AppStaticProps {
|
|||
|
||||
export default function ContentRead(props: ContentReadProps): JSX.Element {
|
||||
useTesting(props);
|
||||
const { langui, content } = props;
|
||||
const { langui, content, languages } = props;
|
||||
const router = useRouter();
|
||||
|
||||
const subPanel = (
|
||||
|
@ -68,7 +69,8 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
|||
}
|
||||
>
|
||||
{prettyLanguage(
|
||||
content.text_set[0].source_language.data.attributes.code
|
||||
content.text_set[0].source_language.data.attributes.code,
|
||||
languages
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -77,23 +79,12 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
|||
<div className="grid grid-flow-col place-items-center place-content-center gap-2">
|
||||
<p className="font-headers">{langui.status}:</p>
|
||||
|
||||
<Chip
|
||||
data-tip={
|
||||
content.text_set[0].status ===
|
||||
Enum_Componentsetstextset_Status.Incomplete
|
||||
? langui.status_incomplete
|
||||
: content.text_set[0].status ===
|
||||
Enum_Componentsetstextset_Status.Draft
|
||||
? langui.status_draft
|
||||
: content.text_set[0].status ===
|
||||
Enum_Componentsetstextset_Status.Review
|
||||
? langui.status_review
|
||||
: langui.status_done
|
||||
}
|
||||
data-for={"StatusTooltip"}
|
||||
<ToolTip
|
||||
content={getStatusDescription(content.text_set[0].status, langui)}
|
||||
maxWidth={"20rem"}
|
||||
>
|
||||
{content.text_set[0].status}
|
||||
</Chip>
|
||||
<Chip>{content.text_set[0].status}</Chip>
|
||||
</ToolTip>
|
||||
</div>
|
||||
|
||||
{content.text_set[0].transcribers.data.length > 0 && (
|
||||
|
@ -148,6 +139,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
|||
<HorizontalLine />
|
||||
<TOC
|
||||
text={content.text_set[0].text}
|
||||
router={router}
|
||||
title={
|
||||
content.titles.length > 0
|
||||
? prettyinlineTitle(
|
||||
|
@ -183,32 +175,6 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
|||
</ContentPanel>
|
||||
);
|
||||
|
||||
const extra = (
|
||||
<>
|
||||
<ReactTooltip
|
||||
id="StatusTooltip"
|
||||
place="top"
|
||||
type="light"
|
||||
effect="solid"
|
||||
delayShow={50}
|
||||
clickable={true}
|
||||
className="drop-shadow-shade-xl !opacity-100 !bg-light !rounded-lg desktop:after:!border-t-light text-left !text-black max-w-xs"
|
||||
/>
|
||||
|
||||
<ReactTooltip
|
||||
id="RecordersTooltip"
|
||||
place="top"
|
||||
type="light"
|
||||
effect="solid"
|
||||
delayShow={100}
|
||||
delayUpdate={100}
|
||||
delayHide={100}
|
||||
clickable={true}
|
||||
className="drop-shadow-shade-xl !opacity-100 !bg-light !rounded-lg desktop:after:!border-t-light text-left !text-black max-w-[22rem]"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<AppLayout
|
||||
navTitle="Contents"
|
||||
|
@ -224,7 +190,6 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
|||
thumbnail={content.thumbnail.data?.attributes}
|
||||
contentPanel={contentPanel}
|
||||
subPanel={subPanel}
|
||||
extra={extra}
|
||||
description={`${langui.type}: ${
|
||||
content.type.data.attributes.titles.length > 0
|
||||
? content.type.data.attributes.titles[0].title
|
||||
|
|
|
@ -15,6 +15,13 @@ export default function Home(props: HomeProps): JSX.Element {
|
|||
const { post } = props;
|
||||
const contentPanel = (
|
||||
<ContentPanel>
|
||||
<div className="grid place-items-center place-content-center w-full gap-5 text-center">
|
||||
<div className="[mask:url('/icons/accords.svg')] [mask-size:contain] [mask-repeat:no-repeat] [mask-position:center] w-32 aspect-square mobile:w-[50vw] bg-black" />
|
||||
<h1 className="text-5xl mb-0">Accord’s Library</h1>
|
||||
<h2 className="text-xl -mt-5">
|
||||
Discover • Analyse • Translate • Archive
|
||||
</h2>
|
||||
</div>
|
||||
{post.translations.length > 0 && (
|
||||
<Markdawn text={post.translations[0].body} />
|
||||
)}
|
||||
|
|
|
@ -16,7 +16,6 @@ import {
|
|||
} from "queries/helpers";
|
||||
import InsetBox from "components/InsetBox";
|
||||
import { useRouter } from "next/router";
|
||||
import ReactTooltip from "react-tooltip";
|
||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||
|
||||
interface ChronologyProps extends AppStaticProps {
|
||||
|
@ -26,7 +25,7 @@ interface ChronologyProps extends AppStaticProps {
|
|||
|
||||
export default function Chronology(props: ChronologyProps): JSX.Element {
|
||||
useTesting(props);
|
||||
const { chronologyItems, chronologyEras } = props;
|
||||
const { chronologyItems, chronologyEras, langui } = props;
|
||||
|
||||
// Group by year the Chronology items
|
||||
let chronologyItemYearGroups: GetChronologyItemsQuery["chronologyItems"]["data"][number][][][] =
|
||||
|
@ -103,20 +102,11 @@ export default function Chronology(props: ChronologyProps): JSX.Element {
|
|||
key={`${eraIndex}-${index}`}
|
||||
year={items[0].attributes.year}
|
||||
items={items}
|
||||
langui={langui}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
|
||||
<ReactTooltip
|
||||
id="ChronologyTooltip"
|
||||
place="top"
|
||||
type="light"
|
||||
effect="solid"
|
||||
delayShow={50}
|
||||
clickable={true}
|
||||
className="drop-shadow-shade-xl !opacity-100 mobile:after:!border-r-light !bg-light !rounded-lg desktop:after:!border-t-light text-left !text-black max-w-xs"
|
||||
/>
|
||||
</ContentPanel>
|
||||
);
|
||||
|
||||
|
|
|
@ -4,7 +4,9 @@ import {
|
|||
ImageQuality,
|
||||
} from "components/Img";
|
||||
import {
|
||||
Enum_Componentsetstextset_Status,
|
||||
GetCurrenciesQuery,
|
||||
GetLanguagesQuery,
|
||||
GetLibraryItemQuery,
|
||||
GetLibraryItemsPreviewQuery,
|
||||
GetWebsiteInterfaceQuery,
|
||||
|
@ -138,23 +140,16 @@ export function prettyItemSubType(metadata: {
|
|||
}
|
||||
}
|
||||
|
||||
export function prettyLanguage(code: string): string {
|
||||
switch (code) {
|
||||
case "en":
|
||||
return "English";
|
||||
case "es":
|
||||
return "Español";
|
||||
case "fr":
|
||||
return "Français";
|
||||
case "ja":
|
||||
return "日本語";
|
||||
case "en":
|
||||
return "English";
|
||||
case "xx":
|
||||
return "██";
|
||||
default:
|
||||
return code;
|
||||
}
|
||||
export function prettyLanguage(
|
||||
code: string,
|
||||
languages: GetLanguagesQuery["languages"]["data"]
|
||||
): string {
|
||||
let result = code;
|
||||
languages.forEach((language) => {
|
||||
if (language.attributes.code === code)
|
||||
result = language.attributes.localized_name;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export function prettyTestWarning(
|
||||
|
@ -257,6 +252,28 @@ export function sortContent(
|
|||
});
|
||||
}
|
||||
|
||||
export function getStatusDescription(
|
||||
status: string,
|
||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]
|
||||
): string {
|
||||
switch (status) {
|
||||
case Enum_Componentsetstextset_Status.Incomplete:
|
||||
return langui.status_incomplete;
|
||||
|
||||
case Enum_Componentsetstextset_Status.Draft:
|
||||
return langui.status_draft;
|
||||
|
||||
case Enum_Componentsetstextset_Status.Review:
|
||||
return langui.status_review;
|
||||
|
||||
case Enum_Componentsetstextset_Status.Done:
|
||||
return langui.status_done;
|
||||
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
export function slugify(str: string): string {
|
||||
return str
|
||||
.replace(/[ÀÁÂÃÄÅàáâãäåæÆ]/g, "a")
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
}
|
||||
|
||||
a {
|
||||
@apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark;
|
||||
@apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark cursor-pointer;
|
||||
}
|
||||
|
||||
*::selection {
|
||||
|
@ -25,7 +25,7 @@
|
|||
}
|
||||
|
||||
mark {
|
||||
@apply bg-mid px-2
|
||||
@apply bg-mid px-2;
|
||||
}
|
||||
|
||||
/* SCROLLBARS STYLING */
|
||||
|
@ -142,3 +142,66 @@
|
|||
@apply [background-image:var(--theme-texture-dots)] [background-blend-mode:var(--theme-texture-dots-blend)] bg-local bg-[length:10cm];
|
||||
}
|
||||
}
|
||||
|
||||
.tippy-box[data-animation="fade"][data-state="hidden"] {
|
||||
@apply opacity-0;
|
||||
}
|
||||
[data-tippy-root] {
|
||||
max-width: calc(100vw - 10px);
|
||||
}
|
||||
.tippy-box {
|
||||
@apply relative bg-light drop-shadow-shade-xl rounded-lg transition-[transform,_visibility,_opacity];
|
||||
}
|
||||
.tippy-box[data-placement^="top"] > .tippy-arrow {
|
||||
@apply bottom-0;
|
||||
}
|
||||
.tippy-box[data-placement^="top"] > .tippy-arrow:before {
|
||||
bottom: -7px;
|
||||
left: 0;
|
||||
border-width: 8px 8px 0;
|
||||
border-top-color: initial;
|
||||
transform-origin: center top;
|
||||
}
|
||||
.tippy-box[data-placement^="bottom"] > .tippy-arrow {
|
||||
top: 0;
|
||||
}
|
||||
.tippy-box[data-placement^="bottom"] > .tippy-arrow:before {
|
||||
top: -7px;
|
||||
left: 0;
|
||||
border-width: 0 8px 8px;
|
||||
border-bottom-color: initial;
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
.tippy-box[data-placement^="left"] > .tippy-arrow {
|
||||
right: 0;
|
||||
}
|
||||
.tippy-box[data-placement^="left"] > .tippy-arrow:before {
|
||||
border-width: 8px 0 8px 8px;
|
||||
border-left-color: initial;
|
||||
right: -7px;
|
||||
transform-origin: center left;
|
||||
}
|
||||
.tippy-box[data-placement^="right"] > .tippy-arrow {
|
||||
left: 0;
|
||||
}
|
||||
.tippy-box[data-placement^="right"] > .tippy-arrow:before {
|
||||
left: -7px;
|
||||
border-width: 8px 8px 8px 0;
|
||||
border-right-color: initial;
|
||||
transform-origin: center right;
|
||||
}
|
||||
.tippy-box[data-inertia][data-state="visible"] {
|
||||
transition-timing-function: cubic-bezier(0.54, 1.5, 0.38, 1.11);
|
||||
}
|
||||
.tippy-arrow {
|
||||
@apply h-4 w-4 text-light;
|
||||
}
|
||||
.tippy-arrow:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
}
|
||||
.tippy-content {
|
||||
@apply relative px-6 py-4 z-10;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,6 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
plugins: [
|
||||
|
||||
plugin(function ({ addUtilities }) {
|
||||
addUtilities({
|
||||
".set-theme-light": {
|
||||
|
|
Loading…
Reference in New Issue