Now use Tippy for Tooltips
This commit is contained in:
parent
3873ef44f9
commit
d2294393b5
|
@ -11,6 +11,7 @@
|
||||||
"@fontsource/opendyslexic": "^4.5.2",
|
"@fontsource/opendyslexic": "^4.5.2",
|
||||||
"@fontsource/vollkorn": "^4.5.4",
|
"@fontsource/vollkorn": "^4.5.4",
|
||||||
"@fontsource/zen-maru-gothic": "^4.5.5",
|
"@fontsource/zen-maru-gothic": "^4.5.5",
|
||||||
|
"@tippyjs/react": "^4.2.6",
|
||||||
"markdown-to-jsx": "^7.1.7",
|
"markdown-to-jsx": "^7.1.7",
|
||||||
"next": "^12.1.0",
|
"next": "^12.1.0",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
|
@ -447,12 +448,34 @@
|
||||||
"node": ">= 8"
|
"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": {
|
"node_modules/@rushstack/eslint-patch": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz",
|
||||||
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/@types/json5": {
|
||||||
"version": "0.0.29",
|
"version": "0.0.29",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||||
|
@ -3409,6 +3432,14 @@
|
||||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||||
"dev": true
|
"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": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
@ -3894,12 +3925,25 @@
|
||||||
"fastq": "^1.6.0"
|
"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": {
|
"@rushstack/eslint-patch": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz",
|
||||||
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
"integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==",
|
||||||
"dev": true
|
"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": {
|
"@types/json5": {
|
||||||
"version": "0.0.29",
|
"version": "0.0.29",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||||
|
@ -6013,6 +6057,14 @@
|
||||||
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
|
||||||
"dev": true
|
"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": {
|
"to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"@fontsource/opendyslexic": "^4.5.2",
|
"@fontsource/opendyslexic": "^4.5.2",
|
||||||
"@fontsource/vollkorn": "^4.5.4",
|
"@fontsource/vollkorn": "^4.5.4",
|
||||||
"@fontsource/zen-maru-gothic": "^4.5.5",
|
"@fontsource/zen-maru-gothic": "^4.5.5",
|
||||||
|
"@tippyjs/react": "^4.2.6",
|
||||||
"markdown-to-jsx": "^7.1.7",
|
"markdown-to-jsx": "^7.1.7",
|
||||||
"next": "^12.1.0",
|
"next": "^12.1.0",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
|
|
|
@ -3,16 +3,12 @@ import { MouseEventHandler } from "react";
|
||||||
type ChipProps = {
|
type ChipProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
onMouseEnter?: MouseEventHandler<HTMLDivElement>;
|
|
||||||
onMouseLeave?: MouseEventHandler<HTMLDivElement>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Chip(props: ChipProps): JSX.Element {
|
export default function Chip(props: ChipProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div
|
<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] hover:opacity-100 ${props.className} `}
|
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}`}
|
||||||
onMouseEnter={props.onMouseEnter}
|
|
||||||
onMouseLeave={props.onMouseLeave}
|
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,6 @@ import {
|
||||||
GetWebsiteInterfaceQuery,
|
GetWebsiteInterfaceQuery,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/operations-types";
|
||||||
import { getStatusDescription } from "queries/helpers";
|
import { getStatusDescription } from "queries/helpers";
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
export type ChronologyItemComponentProps = {
|
export type ChronologyItemComponentProps = {
|
||||||
item: GetChronologyItemsQuery["chronologyItems"]["data"][number];
|
item: GetChronologyItemsQuery["chronologyItems"]["data"][number];
|
||||||
|
@ -18,7 +17,6 @@ export default function ChronologyItemComponent(
|
||||||
props: ChronologyItemComponentProps
|
props: ChronologyItemComponentProps
|
||||||
): JSX.Element {
|
): JSX.Element {
|
||||||
const { langui } = props;
|
const { langui } = props;
|
||||||
const [statusHovered, setStatusHovered] = useState(false);
|
|
||||||
|
|
||||||
function generateAnchor(year: number, month: number, day: number): string {
|
function generateAnchor(year: number, month: number, day: number): string {
|
||||||
let result: string = "";
|
let result: string = "";
|
||||||
|
@ -93,23 +91,12 @@ export default function ChronologyItemComponent(
|
||||||
<div className="place-items-start place-content-start grid grid-flow-col gap-2">
|
<div className="place-items-start place-content-start grid grid-flow-col gap-2">
|
||||||
{translation.status !==
|
{translation.status !==
|
||||||
Enum_Componenttranslationschronologyitem_Status.Done && (
|
Enum_Componenttranslationschronologyitem_Status.Done && (
|
||||||
<Chip
|
|
||||||
onMouseEnter={() => setStatusHovered(true)}
|
|
||||||
onMouseLeave={() => setStatusHovered(false)}
|
|
||||||
>
|
|
||||||
{translation.status}
|
|
||||||
<ToolTip
|
<ToolTip
|
||||||
direction="top"
|
content={getStatusDescription(translation.status, langui)}
|
||||||
hovered={statusHovered}
|
maxWidth={"20rem"}
|
||||||
offset={"1.5rem"}
|
|
||||||
maxWidth="max-w-[10rem]"
|
|
||||||
delayShow={100}
|
|
||||||
>
|
>
|
||||||
<p>
|
<Chip>{translation.status}</Chip>
|
||||||
{getStatusDescription(translation.status, langui)}
|
|
||||||
</p>
|
|
||||||
</ToolTip>
|
</ToolTip>
|
||||||
</Chip>
|
|
||||||
)}
|
)}
|
||||||
{translation.title ? <h3>{translation.title}</h3> : ""}
|
{translation.title ? <h3>{translation.title}</h3> : ""}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { MouseEventHandler, useState } from "react";
|
import { MouseEventHandler } from "react";
|
||||||
import ToolTip from "components/ToolTip";
|
import ToolTip from "components/ToolTip";
|
||||||
|
|
||||||
type NavOptionProps = {
|
type NavOptionProps = {
|
||||||
|
@ -23,14 +23,21 @@ export default function NavOption(props: NavOptionProps): JSX.Element {
|
||||||
props.border ? border : ""
|
props.border ? border : ""
|
||||||
} ${isActive ? divActive : ""}`;
|
} ${isActive ? divActive : ""}`;
|
||||||
|
|
||||||
const [hovered, setHovered] = useState(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<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>
|
<Link href={props.url} passHref>
|
||||||
<div
|
<div
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
onMouseEnter={() => props.reduced && setHovered(true)}
|
|
||||||
onMouseLeave={() => setHovered(false)}
|
|
||||||
className={`relative grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${
|
className={`relative grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${
|
||||||
props.icon ? "text-left" : "text-center"
|
props.icon ? "text-left" : "text-center"
|
||||||
} ${divCommon}`}
|
} ${divCommon}`}
|
||||||
|
@ -42,15 +49,13 @@ export default function NavOption(props: NavOptionProps): JSX.Element {
|
||||||
{!props.reduced && (
|
{!props.reduced && (
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-2xl">{props.title}</h3>
|
<h3 className="text-2xl">{props.title}</h3>
|
||||||
{props.subtitle && <p className="col-start-2">{props.subtitle}</p>}
|
{props.subtitle && (
|
||||||
|
<p className="col-start-2">{props.subtitle}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<ToolTip hovered={hovered} direction="right" offset="3.5rem">
|
|
||||||
<h3 className="text-2xl">{props.title}</h3>
|
|
||||||
{props.subtitle && <p className="col-start-2">{props.subtitle}</p>}
|
|
||||||
</ToolTip>
|
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
</ToolTip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
|
||||||
import Markdown from "markdown-to-jsx";
|
import Markdown from "markdown-to-jsx";
|
||||||
import { useMediaDesktop } from "hooks/useMediaQuery";
|
import { useMediaDesktop } from "hooks/useMediaQuery";
|
||||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||||
|
import ToolTip from "components/ToolTip";
|
||||||
|
|
||||||
type MainPanelProps = {
|
type MainPanelProps = {
|
||||||
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
|
||||||
|
@ -61,10 +62,18 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
? "flex-col gap-3"
|
? "flex-col gap-3"
|
||||||
: "flex-row"
|
: "flex-row"
|
||||||
} flex-wrap gap-2`}
|
} flex-wrap gap-2`}
|
||||||
|
>
|
||||||
|
<ToolTip
|
||||||
|
content={<h3 className="text-2xl">{"Open settings"}</h3>}
|
||||||
|
placement="right"
|
||||||
|
className="text-left"
|
||||||
|
disabled={!appLayout.mainPanelReduced}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
className={
|
className={
|
||||||
appLayout.mainPanelReduced && isDesktop ? "" : "!py-0.5 !px-2.5"
|
appLayout.mainPanelReduced && isDesktop
|
||||||
|
? ""
|
||||||
|
: "!py-0.5 !px-2.5"
|
||||||
}
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
appLayout.setConfigPanelOpen(true);
|
appLayout.setConfigPanelOpen(true);
|
||||||
|
@ -78,8 +87,15 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
settings
|
settings
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
</ToolTip>
|
||||||
|
|
||||||
{router.locale && (
|
{router.locale && (
|
||||||
|
<ToolTip
|
||||||
|
content={<h3 className="text-2xl">{"Change language"}</h3>}
|
||||||
|
placement="right"
|
||||||
|
className="text-left"
|
||||||
|
disabled={!appLayout.mainPanelReduced}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => appLayout.setLanguagePanelOpen(true)}
|
onClick={() => appLayout.setLanguagePanelOpen(true)}
|
||||||
className={
|
className={
|
||||||
|
@ -90,11 +106,20 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
>
|
>
|
||||||
{router.locale.toUpperCase()}
|
{router.locale.toUpperCase()}
|
||||||
</Button>
|
</Button>
|
||||||
|
</ToolTip>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<ToolTip
|
||||||
|
content={<h3 className="text-2xl">{"Open search"}</h3>}
|
||||||
|
placement="right"
|
||||||
|
className="text-left"
|
||||||
|
disabled={!appLayout.mainPanelReduced}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
className={
|
className={
|
||||||
appLayout.mainPanelReduced && isDesktop ? "" : "!py-0.5 !px-2.5"
|
appLayout.mainPanelReduced && isDesktop
|
||||||
|
? ""
|
||||||
|
: "!py-0.5 !px-2.5"
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
@ -105,6 +130,7 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
|
||||||
search
|
search
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
</ToolTip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {
|
||||||
GetContentTextQuery,
|
GetContentTextQuery,
|
||||||
GetWebsiteInterfaceQuery,
|
GetWebsiteInterfaceQuery,
|
||||||
} from "graphql/operations-types";
|
} from "graphql/operations-types";
|
||||||
import { useState } from "react";
|
|
||||||
import Img, { ImageQuality } from "./Img";
|
import Img, { ImageQuality } from "./Img";
|
||||||
import ToolTip from "./ToolTip";
|
import ToolTip from "./ToolTip";
|
||||||
|
|
||||||
|
@ -17,24 +16,9 @@ export default function RecorderChip(props: RecorderChipProps): JSX.Element {
|
||||||
const recorder = props.recorder;
|
const recorder = props.recorder;
|
||||||
const langui = props.langui;
|
const langui = props.langui;
|
||||||
|
|
||||||
const [hovered, setHovered] = useState(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Chip
|
|
||||||
key={recorder.id}
|
|
||||||
onMouseEnter={() => setHovered(true)}
|
|
||||||
onMouseLeave={() => setHovered(false)}
|
|
||||||
>
|
|
||||||
{recorder.attributes.anonymize
|
|
||||||
? `Recorder#${recorder.attributes.anonymous_code}`
|
|
||||||
: recorder.attributes.username}
|
|
||||||
|
|
||||||
<ToolTip
|
<ToolTip
|
||||||
hovered={hovered}
|
content={
|
||||||
direction="top"
|
|
||||||
offset="1.5rem"
|
|
||||||
delayShow={150}
|
|
||||||
>
|
|
||||||
<div className="p-2 py-5 grid gap-2">
|
<div className="p-2 py-5 grid gap-2">
|
||||||
<div className="grid grid-flow-col gap-2 place-items-center place-content-start">
|
<div className="grid grid-flow-col gap-2 place-items-center place-content-start">
|
||||||
{recorder.attributes.avatar.data && (
|
{recorder.attributes.avatar.data && (
|
||||||
|
@ -68,7 +52,14 @@ export default function RecorderChip(props: RecorderChipProps): JSX.Element {
|
||||||
recorder.attributes.bio[0].bio}
|
recorder.attributes.bio[0].bio}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</ToolTip>
|
}
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<Chip key={recorder.id}>
|
||||||
|
{recorder.attributes.anonymize
|
||||||
|
? `Recorder#${recorder.attributes.anonymous_code}`
|
||||||
|
: recorder.attributes.username}
|
||||||
</Chip>
|
</Chip>
|
||||||
|
</ToolTip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,82 +1,17 @@
|
||||||
import { useEffect, useState } from "react";
|
import Tippy, { TippyProps } from "@tippyjs/react";
|
||||||
|
|
||||||
type ToolTipProps = {
|
interface ToolTipProps extends TippyProps {}
|
||||||
hovered: boolean;
|
|
||||||
children: React.ReactNode;
|
|
||||||
direction: "right" | "bottom" | "top" | "left";
|
|
||||||
offset: string;
|
|
||||||
delayShow?: number;
|
|
||||||
maxWidth?: "max-w-[10rem]" | "max-w-xs" | "max-w-sm" | "max-w-md";
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function ToolTip(props: ToolTipProps): JSX.Element {
|
export default function ToolTip(props: ToolTipProps): JSX.Element {
|
||||||
const { children, hovered, direction, offset } = props;
|
let newProps = { ...props };
|
||||||
let { delayShow, maxWidth } = props;
|
|
||||||
if (delayShow === undefined) delayShow = 300;
|
|
||||||
if (maxWidth === undefined) maxWidth = "max-w-sm";
|
|
||||||
|
|
||||||
const [show, setShow] = useState(false);
|
// Set defaults
|
||||||
|
if (newProps.delay === undefined) newProps.delay = [150, 0];
|
||||||
useEffect(() => {
|
if (newProps.interactive === undefined) newProps.interactive = true;
|
||||||
let timeout = setTimeout(() => {});
|
|
||||||
if (hovered) {
|
|
||||||
timeout = setTimeout(() => hovered && setShow(true), delayShow);
|
|
||||||
} else {
|
|
||||||
setShow(false);
|
|
||||||
}
|
|
||||||
return () => clearTimeout(timeout);
|
|
||||||
}, [delayShow, hovered]);
|
|
||||||
|
|
||||||
let tooltipCSS = "";
|
|
||||||
let transformCSS = "";
|
|
||||||
let arrowParentCSS = "";
|
|
||||||
let arrowCSS = "";
|
|
||||||
|
|
||||||
switch (direction) {
|
|
||||||
case "left":
|
|
||||||
tooltipCSS = "[justify-self:end] [align-self:center]";
|
|
||||||
transformCSS = `translateX(-${offset})`;
|
|
||||||
arrowParentCSS = "w-4 -right-4 top-0 bottom-0";
|
|
||||||
arrowCSS = "border-l-light";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "right":
|
|
||||||
tooltipCSS = "[justify-self:start] [align-self:center]";
|
|
||||||
transformCSS = `translateX(${offset})`;
|
|
||||||
arrowParentCSS = "w-4 -left-4 top-0 bottom-0";
|
|
||||||
arrowCSS = "border-r-light";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "top":
|
|
||||||
tooltipCSS = "[align-self:end]";
|
|
||||||
transformCSS = `translateY(-${offset})`;
|
|
||||||
arrowParentCSS = "h-4 -bottom-4 left-0 right-0";
|
|
||||||
arrowCSS = "border-t-light";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "bottom":
|
|
||||||
tooltipCSS = "[align-self:start]";
|
|
||||||
transformCSS = `translateY(${offset})`;
|
|
||||||
arrowParentCSS = "h-4 -top-4 left-0 right-0";
|
|
||||||
arrowCSS = "border-b-light";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tippy {...newProps}>
|
||||||
className={`fixed z-[100] drop-shadow-shade-xl transition-opacity ${maxWidth} ${
|
<div>{props.children}</div>
|
||||||
show
|
</Tippy>
|
||||||
? "opacity-100 pointer-events-auto"
|
|
||||||
: "opacity-0 pointer-events-none"
|
|
||||||
} ${tooltipCSS}`}
|
|
||||||
style={{ transform: transformCSS }}
|
|
||||||
>
|
|
||||||
<div className={`absolute grid ${arrowParentCSS}`}>
|
|
||||||
<div
|
|
||||||
className={`w-0 h-0 border-8 border-[transparent] place-self-center ${arrowCSS}`}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="p-4 px-6 bg-light rounded-md">{children}</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type { AppProps } from "next/app";
|
||||||
import "tailwind.css";
|
import "tailwind.css";
|
||||||
import "@fontsource/zen-maru-gothic/500.css";
|
import "@fontsource/zen-maru-gothic/500.css";
|
||||||
import "@fontsource/vollkorn/700.css";
|
import "@fontsource/vollkorn/700.css";
|
||||||
import "@fontsource/opendyslexic/400.css"
|
import "@fontsource/opendyslexic/400.css";
|
||||||
import "@fontsource/material-icons";
|
import "@fontsource/material-icons";
|
||||||
|
|
||||||
import { AppContextProvider } from "contexts/AppLayoutContext";
|
import { AppContextProvider } from "contexts/AppLayoutContext";
|
||||||
|
|
|
@ -28,7 +28,6 @@ import RecorderChip from "components/RecorderChip";
|
||||||
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
|
||||||
import TOC from "components/Markdown/TOC";
|
import TOC from "components/Markdown/TOC";
|
||||||
import ToolTip from "components/ToolTip";
|
import ToolTip from "components/ToolTip";
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
interface ContentReadProps extends AppStaticProps {
|
interface ContentReadProps extends AppStaticProps {
|
||||||
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
content: GetContentTextQuery["contents"]["data"][number]["attributes"];
|
||||||
|
@ -40,8 +39,6 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
||||||
const { langui, content, languages } = props;
|
const { langui, content, languages } = props;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const [statusHovered, setStatusHovered] = useState(false);
|
|
||||||
|
|
||||||
const subPanel = (
|
const subPanel = (
|
||||||
<SubPanel>
|
<SubPanel>
|
||||||
<ReturnButton
|
<ReturnButton
|
||||||
|
@ -82,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">
|
<div className="grid grid-flow-col place-items-center place-content-center gap-2">
|
||||||
<p className="font-headers">{langui.status}:</p>
|
<p className="font-headers">{langui.status}:</p>
|
||||||
|
|
||||||
<Chip
|
|
||||||
onMouseEnter={() => setStatusHovered(true)}
|
|
||||||
onMouseLeave={() => setStatusHovered(false)}
|
|
||||||
>
|
|
||||||
{content.text_set[0].status}
|
|
||||||
<ToolTip
|
<ToolTip
|
||||||
direction="top"
|
content={getStatusDescription(content.text_set[0].status, langui)}
|
||||||
hovered={statusHovered}
|
maxWidth={"20rem"}
|
||||||
offset={"1.5rem"}
|
|
||||||
maxWidth="max-w-[10rem]"
|
|
||||||
delayShow={100}
|
|
||||||
>
|
>
|
||||||
<p>
|
<Chip>{content.text_set[0].status}</Chip>
|
||||||
{getStatusDescription(content.text_set[0].status, langui)}
|
|
||||||
</p>
|
|
||||||
</ToolTip>
|
</ToolTip>
|
||||||
</Chip>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{content.text_set[0].transcribers.data.length > 0 && (
|
{content.text_set[0].transcribers.data.length > 0 && (
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
mark {
|
mark {
|
||||||
@apply bg-mid px-2
|
@apply bg-mid px-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SCROLLBARS STYLING */
|
/* 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];
|
@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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue