Now using Tippy for Tooltips + prettier integration #11

Merged
DrMint merged 9 commits from develop into main 2022-03-13 15:26:56 +00:00
30 changed files with 451 additions and 342 deletions

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
.next

View File

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

10
next-env.d.ts vendored
View File

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

99
package-lock.json generated
View File

@ -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",

View File

@ -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": {

View File

@ -2,5 +2,5 @@ module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
},
};

View File

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

View File

@ -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" />

1
run_accords_prettier.sh Executable file
View File

@ -0,0 +1 @@
npx prettier --end-of-line auto --write .

View File

@ -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 = "Accords 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>
);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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)}
/>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,7 +16,6 @@ class MyDocument extends Document {
return (
<Html>
<Head>
<link
rel="apple-touch-icon"
sizes="180x180"

View File

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

View File

@ -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&rsquo;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} />
)}

View File

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

View File

@ -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")

View File

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

View File

@ -72,7 +72,6 @@ module.exports = {
},
},
plugins: [
plugin(function ({ addUtilities }) {
addUtilities({
".set-theme-light": {