Use of cJoin and cIf
This commit is contained in:
parent
1510366bc8
commit
c076ec06ad
|
@ -2,6 +2,7 @@ import { Button } from "components/Inputs/Button";
|
|||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
import { UploadImageFragment } from "graphql/generated";
|
||||
import { AppStaticProps } from "graphql/getAppStaticProps";
|
||||
import { cIf, cJoin } from "helpers/className";
|
||||
import { prettyLanguage, prettySlug } from "helpers/formatters";
|
||||
import { getOgImage, ImageQuality, OgImage } from "helpers/img";
|
||||
// import { getClient, Indexes, search, SearchResult } from "helpers/search";
|
||||
|
@ -181,19 +182,23 @@ export function AppLayout(props: Immutable<Props>): JSX.Element {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`${
|
||||
appLayout.darkMode ? "set-theme-dark" : "set-theme-light"
|
||||
} ${
|
||||
appLayout.dyslexic
|
||||
? "set-theme-font-dyslexic"
|
||||
: "set-theme-font-standard"
|
||||
}`}
|
||||
className={cJoin(
|
||||
cIf(appLayout.darkMode, "set-theme-dark", "set-theme-light"),
|
||||
cIf(
|
||||
appLayout.dyslexic,
|
||||
"set-theme-font-dyslexic",
|
||||
"set-theme-font-standard"
|
||||
)
|
||||
)}
|
||||
>
|
||||
<div
|
||||
{...handlers}
|
||||
className={`fixed inset-0 m-0 grid touch-pan-y bg-light p-0 text-black
|
||||
[grid-template-areas:'main_sub_content'] ${gridCol} mobile:grid-cols-[1fr]
|
||||
mobile:grid-rows-[1fr_5rem] mobile:[grid-template-areas:'content''navbar']`}
|
||||
className={cJoin(
|
||||
`fixed inset-0 m-0 grid touch-pan-y bg-light p-0 text-black
|
||||
[grid-template-areas:'main_sub_content'] mobile:grid-cols-[1fr]
|
||||
mobile:grid-rows-[1fr_5rem] mobile:[grid-template-areas:'content''navbar']`,
|
||||
gridCol
|
||||
)}
|
||||
>
|
||||
<Head>
|
||||
<title>{metaTitle}</title>
|
||||
|
@ -222,21 +227,25 @@ export function AppLayout(props: Immutable<Props>): JSX.Element {
|
|||
|
||||
{/* Background when navbar is opened */}
|
||||
<div
|
||||
className={`absolute inset-0 transition-[backdrop-filter]
|
||||
duration-500 [grid-area:content] mobile:z-10 ${
|
||||
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
|
||||
? "[backdrop-filter:blur(2px)]"
|
||||
: "pointer-events-none touch-none "
|
||||
}`}
|
||||
className={cJoin(
|
||||
`absolute inset-0 transition-[backdrop-filter] duration-500 [grid-area:content]
|
||||
mobile:z-10`,
|
||||
cIf(
|
||||
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile,
|
||||
"[backdrop-filter:blur(2px)]",
|
||||
"pointer-events-none touch-none"
|
||||
)
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={`absolute inset-0 bg-shade transition-opacity duration-500
|
||||
${turnSubIntoContent ? "" : ""}
|
||||
${
|
||||
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile
|
||||
? "opacity-60"
|
||||
: "opacity-0"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"absolute inset-0 bg-shade transition-opacity duration-500",
|
||||
cIf(
|
||||
(appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile,
|
||||
"opacity-60",
|
||||
"opacity-0"
|
||||
)
|
||||
)}
|
||||
onClick={() => {
|
||||
appLayout.setMainPanelOpen(false);
|
||||
appLayout.setSubPanelOpen(false);
|
||||
|
@ -267,16 +276,18 @@ export function AppLayout(props: Immutable<Props>): JSX.Element {
|
|||
{/* Sub panel */}
|
||||
{subPanel && (
|
||||
<div
|
||||
className={`texture-paper-dots overflow-y-scroll border-r-[1px] border-dotted
|
||||
className={cJoin(
|
||||
`texture-paper-dots overflow-y-scroll border-r-[1px] border-dotted
|
||||
border-black bg-light transition-transform duration-300 [grid-area:sub]
|
||||
[scrollbar-width:none] webkit-scrollbar:w-0 mobile:z-10 mobile:w-[90%]
|
||||
mobile:justify-self-end mobile:border-r-0 mobile:border-l-[1px]
|
||||
mobile:[grid-area:content]
|
||||
${
|
||||
mobile:[grid-area:content]`,
|
||||
turnSubIntoContent
|
||||
? "mobile:w-full mobile:border-l-0"
|
||||
: !appLayout.subPanelOpen && "mobile:translate-x-[100vw]"
|
||||
}`}
|
||||
: appLayout.subPanelOpen
|
||||
? ""
|
||||
: "mobile:translate-x-[100vw]"
|
||||
)}
|
||||
>
|
||||
{subPanel}
|
||||
</div>
|
||||
|
@ -284,12 +295,13 @@ export function AppLayout(props: Immutable<Props>): JSX.Element {
|
|||
|
||||
{/* Main panel */}
|
||||
<div
|
||||
className={`texture-paper-dots overflow-y-scroll border-r-[1px] border-dotted
|
||||
className={cJoin(
|
||||
`texture-paper-dots overflow-y-scroll border-r-[1px] border-dotted
|
||||
border-black bg-light transition-transform duration-300 [grid-area:main]
|
||||
[scrollbar-width:none] webkit-scrollbar:w-0 mobile:z-10 mobile:w-[90%]
|
||||
mobile:justify-self-start mobile:[grid-area:content] ${
|
||||
appLayout.mainPanelOpen ? "" : "mobile:-translate-x-full"
|
||||
}`}
|
||||
mobile:justify-self-start mobile:[grid-area:content]`,
|
||||
cIf(!appLayout.mainPanelOpen, "mobile:-translate-x-full")
|
||||
)}
|
||||
>
|
||||
<MainPanel langui={langui} />
|
||||
</div>
|
||||
|
@ -301,25 +313,28 @@ export function AppLayout(props: Immutable<Props>): JSX.Element {
|
|||
>
|
||||
<Ico
|
||||
icon={appLayout.mainPanelOpen ? Icon.Close : Icon.Menu}
|
||||
className="mt-[.1em] cursor-pointer"
|
||||
className="mt-[.1em] cursor-pointer !text-2xl"
|
||||
onClick={() => {
|
||||
appLayout.setMainPanelOpen(!appLayout.mainPanelOpen);
|
||||
appLayout.setSubPanelOpen(false);
|
||||
}}
|
||||
/>
|
||||
<p
|
||||
className={`overflow-hidden text-center font-headers font-black ${
|
||||
ogTitle && ogTitle.length > 30
|
||||
? "max-h-14 text-xl"
|
||||
: "max-h-16 text-2xl"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"overflow-hidden text-center font-headers font-black",
|
||||
cIf(
|
||||
ogTitle && ogTitle.length > 30,
|
||||
"max-h-14 text-xl",
|
||||
"max-h-16 text-2xl"
|
||||
)
|
||||
)}
|
||||
>
|
||||
{ogTitle}
|
||||
</p>
|
||||
{subPanel && !turnSubIntoContent && (
|
||||
<Ico
|
||||
icon={appLayout.subPanelOpen ? Icon.Close : subPanelIcon}
|
||||
className="mt-[.1em] cursor-pointer"
|
||||
className="mt-[.1em] cursor-pointer !text-2xl"
|
||||
onClick={() => {
|
||||
appLayout.setSubPanelOpen(!appLayout.subPanelOpen);
|
||||
appLayout.setMainPanelOpen(false);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
|
||||
interface Props {
|
||||
|
@ -8,9 +9,12 @@ interface Props {
|
|||
export function Chip(props: Immutable<Props>): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className={`grid place-content-center place-items-center whitespace-nowrap rounded-full
|
||||
className={cJoin(
|
||||
`grid place-content-center place-items-center whitespace-nowrap rounded-full
|
||||
border-[1px] px-1.5 pb-[0.14rem] text-xs opacity-70
|
||||
transition-[color,_opacity,_border-color] hover:opacity-100 ${props.className}`}
|
||||
transition-[color,_opacity,_border-color] hover:opacity-100`,
|
||||
props.className
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
|
||||
interface Props {
|
||||
|
@ -5,9 +6,13 @@ interface Props {
|
|||
}
|
||||
|
||||
export function HorizontalLine(props: Immutable<Props>): JSX.Element {
|
||||
const { className } = props;
|
||||
return (
|
||||
<div
|
||||
className={`my-8 h-0 w-full border-t-[3px] border-dotted border-black ${props.className}`}
|
||||
className={cJoin(
|
||||
"my-8 h-0 w-full border-t-[3px] border-dotted border-black",
|
||||
className
|
||||
)}
|
||||
></div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { MouseEventHandler } from "react";
|
||||
|
||||
|
@ -10,7 +11,13 @@ interface Props {
|
|||
export function Ico(props: Immutable<Props>): JSX.Element {
|
||||
const { onClick, icon, className } = props;
|
||||
return (
|
||||
<span onClick={onClick} className={`material-icons ${className}`}>
|
||||
<span
|
||||
onClick={onClick}
|
||||
className={cJoin(
|
||||
"material-icons [font-size:inherit] [line-height:inherit]",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{icon}
|
||||
</span>
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Ico, Icon } from "components/Ico";
|
||||
import { cIf, cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { useRouter } from "next/router";
|
||||
import { MouseEventHandler } from "react";
|
||||
|
@ -38,14 +39,18 @@ export function Button(props: Immutable<Props>): JSX.Element {
|
|||
draggable={draggable}
|
||||
id={id}
|
||||
onClick={onClick}
|
||||
className={`component-button group grid select-none grid-flow-col place-content-center
|
||||
place-items-center gap-2 rounded-full border-[1px] border-dark px-4 pt-[0.4rem] pb-[0.5rem]
|
||||
text-dark transition-all ${
|
||||
active
|
||||
? "!border-black bg-black text-light drop-shadow-black-lg"
|
||||
: `cursor-pointer hover:bg-dark hover:text-light hover:drop-shadow-shade-lg
|
||||
className={cJoin(
|
||||
`component-button group grid select-none grid-flow-col place-content-center
|
||||
place-items-center gap-2 rounded-full border-[1px] border-dark py-3 px-4 leading-none
|
||||
text-dark transition-all`,
|
||||
cIf(
|
||||
active,
|
||||
"!border-black bg-black text-light drop-shadow-black-lg",
|
||||
`cursor-pointer hover:bg-dark hover:text-light hover:drop-shadow-shade-lg
|
||||
active:border-black active:bg-black active:text-light active:drop-shadow-black-lg`
|
||||
} ${className}`}
|
||||
),
|
||||
className
|
||||
)}
|
||||
>
|
||||
{badgeNumber && (
|
||||
<div
|
||||
|
@ -55,7 +60,9 @@ export function Button(props: Immutable<Props>): JSX.Element {
|
|||
<p className="-translate-y-[0.05em]">{badgeNumber}</p>
|
||||
</div>
|
||||
)}
|
||||
{icon && <Ico className="translate-y-[0.04em] !text-base" icon={icon} />}
|
||||
{icon && (
|
||||
<Ico className="[font-size:150%] [line-height:0.66]" icon={icon} />
|
||||
)}
|
||||
{text && <p className="-translate-y-[0.05em] text-center">{text}</p>}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
|
@ -31,7 +32,7 @@ export function ButtonGroup(props: Immutable<Props>): JSX.Element {
|
|||
}, [children]);
|
||||
|
||||
return (
|
||||
<div ref={ref} className={`grid grid-flow-col ${className}`}>
|
||||
<div ref={ref} className={cJoin("grid grid-flow-col", className)}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Icon } from "components/Ico";
|
||||
import { AppStaticProps } from "graphql/getAppStaticProps";
|
||||
import { cJoin } from "helpers/className";
|
||||
import { prettyLanguage } from "helpers/formatters";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { Dispatch, Fragment, SetStateAction } from "react";
|
||||
|
@ -20,7 +21,7 @@ export function LanguageSwitcher(props: Immutable<Props>): JSX.Element {
|
|||
return (
|
||||
<ToolTip
|
||||
content={
|
||||
<div className={`flex flex-col gap-2 ${className}`}>
|
||||
<div className={cJoin("flex flex-col gap-2", className)}>
|
||||
{[...locales].map(([locale, value], index) => (
|
||||
<Fragment key={index}>
|
||||
{locale && (
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Icon } from "components/Ico";
|
||||
import { cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import { Button } from "./Button";
|
||||
|
@ -11,10 +12,10 @@ interface Props {
|
|||
}
|
||||
|
||||
export function PageSelector(props: Immutable<Props>): JSX.Element {
|
||||
const { page, setPage, maxPage } = props;
|
||||
const { page, setPage, maxPage, className } = props;
|
||||
|
||||
return (
|
||||
<div className={`flex flex-row place-content-center ${props.className}`}>
|
||||
<div className={cJoin("flex flex-row place-content-center", className)}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (page > 0) setPage(page - 1);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Ico, Icon } from "components/Ico";
|
||||
import { cIf, cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { Dispatch, Fragment, SetStateAction, useState } from "react";
|
||||
|
||||
|
@ -17,16 +18,19 @@ export function Select(props: Immutable<Props>): JSX.Element {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`relative text-center transition-[filter] ${
|
||||
opened && "z-10 drop-shadow-shade-lg"
|
||||
} ${className}`}
|
||||
className={cJoin(
|
||||
"relative text-center transition-[filter]",
|
||||
cIf(opened, "z-10 drop-shadow-shade-lg"),
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={`grid cursor-pointer grid-flow-col grid-cols-[1fr_auto_auto] place-items-center
|
||||
className={cJoin(
|
||||
`grid cursor-pointer grid-flow-col grid-cols-[1fr_auto_auto] place-items-center
|
||||
rounded-[1em] bg-light p-1 outline outline-2 outline-offset-[-2px] outline-mid
|
||||
transition-all hover:bg-mid hover:outline-[transparent] ${
|
||||
opened && "rounded-b-none bg-highlight outline-[transparent]"
|
||||
}`}
|
||||
transition-all hover:bg-mid hover:outline-[transparent]`,
|
||||
cIf(opened, "rounded-b-none bg-highlight outline-[transparent]")
|
||||
)}
|
||||
>
|
||||
<p onClick={() => setOpened(!opened)} className="w-full">
|
||||
{state === -1 ? "—" : options[state]}
|
||||
|
@ -44,18 +48,19 @@ export function Select(props: Immutable<Props>): JSX.Element {
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
className={`left-0 right-0 rounded-b-[1em] ${
|
||||
opened ? "absolute" : "hidden"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"left-0 right-0 rounded-b-[1em]",
|
||||
cIf(opened, "absolute", "hidden")
|
||||
)}
|
||||
>
|
||||
{options.map((option, index) => (
|
||||
<Fragment key={index}>
|
||||
{index !== state && (
|
||||
<div
|
||||
className={` ${
|
||||
opened ? "bg-highlight" : "bg-light"
|
||||
} cursor-pointer p-1
|
||||
transition-colors last-of-type:rounded-b-[1em] hover:bg-mid`}
|
||||
className={cJoin(
|
||||
"cursor-pointer p-1 transition-colors last-of-type:rounded-b-[1em] hover:bg-mid",
|
||||
cIf(opened, "bg-highlight", "bg-light")
|
||||
)}
|
||||
id={option}
|
||||
onClick={() => {
|
||||
setOpened(false);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { cIf, cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
|
||||
|
@ -12,23 +13,29 @@ export function Switch(props: Immutable<Props>): JSX.Element {
|
|||
const { state, setState, className, disabled } = props;
|
||||
return (
|
||||
<div
|
||||
className={`relative grid h-6 w-12 rounded-full border-2
|
||||
border-mid transition-colors ${
|
||||
disabled ? "cursor-not-allowed" : "cursor-pointer"
|
||||
} ${className} ${
|
||||
state ? "border-none bg-mid shadow-inner-sm shadow-shade" : "bg-light"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"relative grid h-6 w-12 rounded-full border-2 border-mid transition-colors",
|
||||
cIf(disabled, "cursor-not-allowed", "cursor-pointer"),
|
||||
cIf(
|
||||
state,
|
||||
"border-none bg-mid shadow-inner-sm shadow-shade",
|
||||
"bg-light"
|
||||
),
|
||||
className
|
||||
)}
|
||||
onClick={() => {
|
||||
if (!disabled) setState(!state);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={`absolute ${
|
||||
state ? "top-[2px] bottom-[2px] left-[2px]" : "top-0 bottom-0 left-0"
|
||||
}
|
||||
aspect-square rounded-full bg-dark transition-transform ${
|
||||
state && "translate-x-[120%]"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"absolute aspect-square rounded-full bg-dark transition-transform",
|
||||
cIf(
|
||||
state,
|
||||
"top-[2px] bottom-[2px] left-[2px] translate-x-[120%]",
|
||||
"top-0 bottom-0 left-0"
|
||||
)
|
||||
)}
|
||||
></div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Ico, Icon } from "components/Ico";
|
||||
import { cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
|
||||
|
@ -16,7 +17,7 @@ export function TextInput(props: Immutable<Props>): JSX.Element {
|
|||
const { state, setState, className, name, placeholder } = props;
|
||||
|
||||
return (
|
||||
<div className={`relative ${className}`}>
|
||||
<div className={cJoin("relative", className)}>
|
||||
<input
|
||||
className="w-full"
|
||||
type="text"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { cIf, cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
|
||||
interface Props {
|
||||
|
@ -10,12 +11,18 @@ export function WithLabel(props: Immutable<Props>): JSX.Element {
|
|||
const { label, input, disabled } = props;
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-row place-content-between place-items-center gap-2 ${
|
||||
disabled ? "text-dark brightness-150 contrast-75 grayscale" : ""
|
||||
}`}
|
||||
className={cJoin(
|
||||
"flex flex-row place-content-between place-items-center gap-2",
|
||||
cIf(disabled, "text-dark brightness-150 contrast-75 grayscale")
|
||||
)}
|
||||
>
|
||||
{label && (
|
||||
<p className={`text-left ${label.length < 10 ? "flex-shrink-0" : ""}`}>
|
||||
<p
|
||||
className={cJoin(
|
||||
"text-left",
|
||||
cIf(label.length < 10, "flex-shrink-0")
|
||||
)}
|
||||
>
|
||||
{label}:
|
||||
</p>
|
||||
)}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
|
||||
interface Props {
|
||||
|
@ -10,7 +11,10 @@ export function InsetBox(props: Immutable<Props>): JSX.Element {
|
|||
return (
|
||||
<div
|
||||
id={props.id}
|
||||
className={`w-full rounded-xl bg-mid p-8 shadow-inner-sm shadow-shade ${props.className}`}
|
||||
className={cJoin(
|
||||
"w-full rounded-xl bg-mid p-8 shadow-inner-sm shadow-shade",
|
||||
props.className
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Img } from "components/Img";
|
|||
import { InsetBox } from "components/InsetBox";
|
||||
import { ToolTip } from "components/ToolTip";
|
||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
import { cJoin } from "helpers/className";
|
||||
import { slugify } from "helpers/formatters";
|
||||
import { getAssetURL, ImageQuality } from "helpers/img";
|
||||
import { Immutable } from "helpers/types";
|
||||
|
@ -32,7 +33,7 @@ export function Markdawn(props: Immutable<Props>): JSX.Element {
|
|||
<>
|
||||
<LightBox />
|
||||
<Markdown
|
||||
className={`formatted ${props.className}`}
|
||||
className={cJoin("formatted", props.className)}
|
||||
options={{
|
||||
slugify: slugify,
|
||||
overrides: {
|
||||
|
|
|
@ -19,7 +19,7 @@ export function TOC(props: Immutable<Props>): JSX.Element {
|
|||
<h3 className="text-xl">Table of content</h3>
|
||||
<div className="max-w-[14.5rem] text-left">
|
||||
<p className="relative my-2 overflow-x-hidden text-ellipsis whitespace-nowrap text-left">
|
||||
<a className="" onClick={async () => router.replace(`#${toc.slug}`)}>
|
||||
<a onClick={async () => router.replace(`#${toc.slug}`)}>
|
||||
{<abbr title={toc.title}>{toc.title}</abbr>}
|
||||
</a>
|
||||
</p>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Ico, Icon } from "components/Ico";
|
||||
import { ToolTip } from "components/ToolTip";
|
||||
import { cJoin, cIf } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { useRouter } from "next/router";
|
||||
import { MouseEventHandler } from "react";
|
||||
|
@ -17,16 +18,6 @@ interface Props {
|
|||
export function NavOption(props: Immutable<Props>): JSX.Element {
|
||||
const router = useRouter();
|
||||
const isActive = router.asPath.startsWith(props.url);
|
||||
const divActive = "bg-mid shadow-inner-sm shadow-shade";
|
||||
|
||||
const border =
|
||||
"outline outline-mid outline-2 outline-offset-[-2px] hover:outline-[transparent]";
|
||||
|
||||
const divCommon = `gap-x-5 w-full rounded-2xl cursor-pointer p-4 hover:bg-mid
|
||||
hover:shadow-inner-sm hover:shadow-shade hover:active:shadow-inner
|
||||
hover:active:shadow-shade transition-all ${props.border ? border : ""} ${
|
||||
isActive ? divActive : ""
|
||||
}`;
|
||||
|
||||
return (
|
||||
<ToolTip
|
||||
|
@ -51,11 +42,21 @@ export function NavOption(props: Immutable<Props>): JSX.Element {
|
|||
}
|
||||
}
|
||||
}}
|
||||
className={`relative grid auto-cols-fr grid-flow-col grid-cols-[auto] justify-center ${
|
||||
props.icon ? "text-left" : "text-center"
|
||||
} ${divCommon}`}
|
||||
className={cJoin(
|
||||
`relative grid w-full cursor-pointer auto-cols-fr grid-flow-col grid-cols-[auto]
|
||||
justify-center gap-x-5 rounded-2xl p-4 transition-all hover:bg-mid hover:shadow-inner-sm
|
||||
hover:shadow-shade hover:active:shadow-inner hover:active:shadow-shade`,
|
||||
cIf(props.icon, "text-left", "text-center"),
|
||||
cIf(
|
||||
props.border,
|
||||
"outline outline-2 outline-offset-[-2px] outline-mid hover:outline-[transparent]"
|
||||
),
|
||||
cIf(isActive, "bg-mid shadow-inner-sm shadow-shade")
|
||||
)}
|
||||
>
|
||||
{props.icon && <Ico icon={props.icon} className="mt-[.1em]" />}
|
||||
{props.icon && (
|
||||
<Ico icon={props.icon} className="mt-[-.1em] !text-2xl" />
|
||||
)}
|
||||
|
||||
{!props.reduced && (
|
||||
<div>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { Icon } from "components/Ico";
|
|||
import { Button } from "components/Inputs/Button";
|
||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
import { AppStaticProps } from "graphql/getAppStaticProps";
|
||||
import { cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
|
||||
interface Props {
|
||||
|
@ -25,13 +26,14 @@ export function ReturnButton(props: Immutable<Props>): JSX.Element {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`${
|
||||
className={cJoin(
|
||||
props.displayOn === ReturnButtonType.Mobile
|
||||
? "desktop:hidden"
|
||||
: props.displayOn === ReturnButtonType.Desktop
|
||||
? "mobile:hidden"
|
||||
: ""
|
||||
} ${props.className}`}
|
||||
: "",
|
||||
props.className
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
onClick={() => appLayout.setSubPanelOpen(false)}
|
||||
|
|
|
@ -1,29 +1,33 @@
|
|||
import { cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
|
||||
interface Props {
|
||||
children: React.ReactNode;
|
||||
autoformat?: boolean;
|
||||
width?: ContentPanelWidthSizes;
|
||||
}
|
||||
|
||||
export enum ContentPanelWidthSizes {
|
||||
Default = "default",
|
||||
Large = "large",
|
||||
Full = "full",
|
||||
}
|
||||
|
||||
export function ContentPanel(props: Immutable<Props>): JSX.Element {
|
||||
const width = props.width ? props.width : ContentPanelWidthSizes.Default;
|
||||
const widthCSS =
|
||||
width === ContentPanelWidthSizes.Default ? "max-w-2xl" : "w-full";
|
||||
const { width = ContentPanelWidthSizes.Default, children } = props;
|
||||
|
||||
return (
|
||||
<div className={`grid px-4 pt-10 pb-20 desktop:py-20 desktop:px-10`}>
|
||||
<main
|
||||
className={`${
|
||||
props.autoformat && "formatted"
|
||||
} ${widthCSS} place-self-center`}
|
||||
className={cJoin(
|
||||
"place-self-center",
|
||||
width === ContentPanelWidthSizes.Default
|
||||
? "max-w-2xl"
|
||||
: width === ContentPanelWidthSizes.Large
|
||||
? "max-w-4xl"
|
||||
: "w-full"
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -9,6 +9,7 @@ import { useMediaDesktop } from "hooks/useMediaQuery";
|
|||
import Markdown from "markdown-to-jsx";
|
||||
import Link from "next/link";
|
||||
import { Icon } from "components/Ico";
|
||||
import { cIf, cJoin } from "helpers/className";
|
||||
|
||||
interface Props {
|
||||
langui: AppStaticProps["langui"];
|
||||
|
@ -21,15 +22,17 @@ export function MainPanel(props: Immutable<Props>): JSX.Element {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`grid content-start justify-center gap-y-2 p-8 text-center ${
|
||||
appLayout.mainPanelReduced && isDesktop && "px-4"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"grid content-start justify-center gap-y-2 p-8 text-center",
|
||||
cIf(appLayout.mainPanelReduced && isDesktop, "px-4")
|
||||
)}
|
||||
>
|
||||
{/* Reduce/expand main menu */}
|
||||
<div
|
||||
className={`fixed top-1/2 mobile:hidden ${
|
||||
appLayout.mainPanelReduced ? "left-[4.65rem]" : "left-[18.65rem]"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"fixed top-1/2 mobile:hidden",
|
||||
cIf(appLayout.mainPanelReduced, "left-[4.65rem]", "left-[18.65rem]")
|
||||
)}
|
||||
onClick={() =>
|
||||
appLayout.setMainPanelReduced(!appLayout.mainPanelReduced)
|
||||
}
|
||||
|
@ -46,26 +49,28 @@ export function MainPanel(props: Immutable<Props>): JSX.Element {
|
|||
<div className="grid place-items-center">
|
||||
<Link href="/" passHref>
|
||||
<div
|
||||
className={`${
|
||||
appLayout.mainPanelReduced && isDesktop ? "w-12" : "w-1/2"
|
||||
} mb-4 aspect-square cursor-pointer bg-black
|
||||
transition-colors [mask:url('/icons/accords.svg')]
|
||||
![mask-size:contain] ![mask-repeat:no-repeat] ![mask-position:center] hover:bg-dark`}
|
||||
className={cJoin(
|
||||
`mb-4 aspect-square cursor-pointer bg-black transition-colors
|
||||
[mask:url('/icons/accords.svg')] ![mask-size:contain] ![mask-repeat:no-repeat]
|
||||
![mask-position:center] hover:bg-dark`,
|
||||
cIf(appLayout.mainPanelReduced && isDesktop, "w-12", "w-1/2")
|
||||
)}
|
||||
></div>
|
||||
</Link>
|
||||
|
||||
{appLayout.mainPanelReduced && isDesktop ? (
|
||||
""
|
||||
) : (
|
||||
{(!appLayout.mainPanelReduced || !isDesktop) && (
|
||||
<h2 className="text-3xl">Accord’s Library</h2>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={`flex ${
|
||||
appLayout.mainPanelReduced && isDesktop
|
||||
? "flex-col gap-3"
|
||||
: "flex-row"
|
||||
} flex-wrap gap-2`}
|
||||
className={cJoin(
|
||||
"flex flex-wrap gap-2",
|
||||
cIf(
|
||||
appLayout.mainPanelReduced && isDesktop,
|
||||
"flex-col gap-3",
|
||||
"flex-row"
|
||||
)
|
||||
)}
|
||||
>
|
||||
<ToolTip
|
||||
content={<h3 className="text-2xl">{langui.open_settings}</h3>}
|
||||
|
@ -176,9 +181,10 @@ export function MainPanel(props: Immutable<Props>): JSX.Element {
|
|||
{appLayout.mainPanelReduced && isDesktop ? "" : <HorizontalLine />}
|
||||
|
||||
<div
|
||||
className={`text-center ${
|
||||
appLayout.mainPanelReduced && isDesktop ? "hidden" : ""
|
||||
}`}
|
||||
className={cJoin(
|
||||
"text-center",
|
||||
cIf(appLayout.mainPanelReduced && isDesktop, "hidden")
|
||||
)}
|
||||
>
|
||||
<p>
|
||||
{langui.licensing_notice && (
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
import { cIf, cJoin } from "helpers/className";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { Dispatch, SetStateAction, useEffect } from "react";
|
||||
import Hotkeys from "react-hot-keys";
|
||||
|
@ -40,32 +41,37 @@ export function Popup(props: Immutable<Props>): JSX.Element {
|
|||
}}
|
||||
>
|
||||
<div
|
||||
className={`fixed inset-0 z-50 grid place-content-center
|
||||
transition-[backdrop-filter] duration-500 ${
|
||||
state ? "[backdrop-filter:blur(2px)]" : "pointer-events-none touch-none"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"fixed inset-0 z-50 grid place-content-center transition-[backdrop-filter] duration-500",
|
||||
cIf(
|
||||
state,
|
||||
"[backdrop-filter:blur(2px)]",
|
||||
"pointer-events-none touch-none"
|
||||
)
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={`fixed inset-0 bg-shade transition-all duration-500 ${
|
||||
state ? "bg-opacity-50" : "bg-opacity-0"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"fixed inset-0 bg-shade transition-all duration-500",
|
||||
cIf(state, "bg-opacity-50", "bg-opacity-0")
|
||||
)}
|
||||
onClick={() => {
|
||||
setState(false);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div
|
||||
className={`${
|
||||
padding && "p-10 mobile:p-6"
|
||||
} grid place-items-center gap-4 transition-transform ${
|
||||
state ? "scale-100" : "scale-0"
|
||||
} ${
|
||||
fillViewport
|
||||
? "absolute inset-10"
|
||||
: "relative max-h-[80vh] overflow-y-auto mobile:w-[85vw]"
|
||||
} ${
|
||||
hideBackground ? "" : "rounded-lg bg-light shadow-2xl shadow-shade"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"grid place-items-center gap-4 transition-transform",
|
||||
cIf(padding, "p-10 mobile:p-6"),
|
||||
cIf(state, "scale-100", "scale-0"),
|
||||
cIf(
|
||||
fillViewport,
|
||||
"absolute inset-10",
|
||||
"relative max-h-[80vh] overflow-y-auto mobile:w-[85vw]"
|
||||
),
|
||||
cIf(!hideBackground, "rounded-lg bg-light shadow-2xl shadow-shade")
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
@ -5,6 +5,7 @@ import {
|
|||
UploadImageFragment,
|
||||
} from "graphql/generated";
|
||||
import { AppStaticProps } from "graphql/getAppStaticProps";
|
||||
import { cIf, cJoin } from "helpers/className";
|
||||
import {
|
||||
prettyDate,
|
||||
prettyDuration,
|
||||
|
@ -130,14 +131,15 @@ export function PreviewCard(props: Immutable<Props>): JSX.Element {
|
|||
{stackNumber > 0 && (
|
||||
<>
|
||||
<div
|
||||
className={`absolute inset-0 scale-[.85] overflow-hidden bg-light brightness-[0.8]
|
||||
sepia-[0.5] transition-[top_transform] group-hover:-top-8 ${
|
||||
thumbnailRounded && "rounded-md"
|
||||
}`}
|
||||
className={cJoin(
|
||||
`absolute inset-0 scale-[.85] overflow-hidden bg-light brightness-[0.8] sepia-[0.5]
|
||||
transition-[top_transform] group-hover:-top-8`,
|
||||
cIf(thumbnailRounded, "rounded-md")
|
||||
)}
|
||||
>
|
||||
{thumbnail && (
|
||||
<Img
|
||||
className="opacity-30 "
|
||||
className="opacity-30"
|
||||
image={thumbnail}
|
||||
quality={ImageQuality.Medium}
|
||||
/>
|
||||
|
@ -145,10 +147,11 @@ export function PreviewCard(props: Immutable<Props>): JSX.Element {
|
|||
</div>
|
||||
|
||||
<div
|
||||
className={`absolute inset-0 overflow-hidden bg-light brightness-[0.9] sepia-[0.2]
|
||||
transition-[top_transform] group-hover:-top-4 group-hover:scale-[.94] ${
|
||||
thumbnailRounded && "rounded-md"
|
||||
}`}
|
||||
className={cJoin(
|
||||
`absolute inset-0 overflow-hidden bg-light brightness-[0.9] sepia-[0.2]
|
||||
transition-[top_transform] group-hover:-top-4 group-hover:scale-[.94]`,
|
||||
cIf(thumbnailRounded, "rounded-md")
|
||||
)}
|
||||
>
|
||||
{thumbnail && (
|
||||
<Img
|
||||
|
@ -171,12 +174,17 @@ export function PreviewCard(props: Immutable<Props>): JSX.Element {
|
|||
}}
|
||||
>
|
||||
<Img
|
||||
className={`${
|
||||
thumbnailRounded &&
|
||||
(keepInfoVisible
|
||||
? "rounded-t-md"
|
||||
: "rounded-md notHoverable:rounded-b-none")
|
||||
} ${thumbnailForceAspectRatio && "h-full w-full object-cover"}`}
|
||||
className={cJoin(
|
||||
cIf(
|
||||
thumbnailRounded,
|
||||
cIf(
|
||||
keepInfoVisible,
|
||||
"rounded-t-md",
|
||||
"rounded-md notHoverable:rounded-b-none"
|
||||
)
|
||||
),
|
||||
cIf(thumbnailForceAspectRatio, "h-full w-full object-cover")
|
||||
)}
|
||||
image={thumbnail}
|
||||
quality={ImageQuality.Medium}
|
||||
/>
|
||||
|
@ -200,8 +208,8 @@ export function PreviewCard(props: Immutable<Props>): JSX.Element {
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
className="absolute right-2 bottom-2 rounded-full bg-black
|
||||
bg-opacity-60 px-2 text-light"
|
||||
className="absolute right-2 bottom-2 rounded-full bg-black bg-opacity-60 px-2
|
||||
text-light"
|
||||
>
|
||||
{prettyDuration(hoverlay.duration)}
|
||||
</div>
|
||||
|
@ -211,11 +219,14 @@ export function PreviewCard(props: Immutable<Props>): JSX.Element {
|
|||
) : (
|
||||
<div
|
||||
style={{ aspectRatio: thumbnailAspectRatio }}
|
||||
className={`relative w-full bg-light ${
|
||||
keepInfoVisible
|
||||
? "rounded-t-md"
|
||||
: "rounded-md notHoverable:rounded-b-none"
|
||||
}`}
|
||||
className={cJoin(
|
||||
"relative w-full bg-light",
|
||||
cIf(
|
||||
keepInfoVisible,
|
||||
"rounded-t-md",
|
||||
"rounded-md notHoverable:rounded-b-none"
|
||||
)
|
||||
)}
|
||||
>
|
||||
{stackNumber > 0 && (
|
||||
<div
|
||||
|
@ -228,11 +239,14 @@ export function PreviewCard(props: Immutable<Props>): JSX.Element {
|
|||
</div>
|
||||
)}
|
||||
<div
|
||||
className={`z-20 grid gap-2 p-4 transition-opacity linearbg-obi ${
|
||||
!keepInfoVisible &&
|
||||
className={cJoin(
|
||||
"z-20 grid gap-2 p-4 transition-opacity linearbg-obi",
|
||||
cIf(
|
||||
!keepInfoVisible,
|
||||
`-inset-x-0.5 bottom-2 opacity-0 group-hover:opacity-100 hoverable:absolute
|
||||
hoverable:drop-shadow-shade-lg notHoverable:rounded-b-md`
|
||||
}`}
|
||||
)
|
||||
)}
|
||||
>
|
||||
{metadata?.position === "Top" && metadataJSX}
|
||||
{topChips && topChips.length > 0 && (
|
||||
|
|
|
@ -34,9 +34,8 @@ export function PreviewLine(props: Immutable<Props>): JSX.Element {
|
|||
return (
|
||||
<Link href={href} passHref>
|
||||
<div
|
||||
className="flex h-36 w-full cursor-pointer
|
||||
flex-row place-items-center gap-4 overflow-hidden rounded-md
|
||||
bg-light pr-4 transition-transform drop-shadow-shade-xl hover:scale-[1.02]"
|
||||
className="flex h-36 w-full cursor-pointer flex-row place-items-center gap-4 overflow-hidden
|
||||
rounded-md bg-light pr-4 transition-transform drop-shadow-shade-xl hover:scale-[1.02]"
|
||||
>
|
||||
{thumbnail ? (
|
||||
<div className="aspect-[3/2] h-full">
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
import { Immutable } from "helpers/types";
|
||||
import Image from "next/image";
|
||||
|
||||
interface Props {
|
||||
src: string;
|
||||
alt: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function SVG(props: Immutable<Props>): JSX.Element {
|
||||
return (
|
||||
<div className={props.className}>
|
||||
<Image
|
||||
src={props.src}
|
||||
alt={props.src}
|
||||
height={1000}
|
||||
width={1000}
|
||||
unoptimized
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
import Tippy, { TippyProps } from "@tippyjs/react";
|
||||
import { cJoin } from "helpers/className";
|
||||
import "tippy.js/animations/scale-subtle.css";
|
||||
|
||||
interface Props extends TippyProps {}
|
||||
|
||||
export function ToolTip(props: Props): JSX.Element {
|
||||
const newProps: Props = {
|
||||
className: cJoin("text-[80%]", props.className),
|
||||
delay: [150, 0],
|
||||
interactive: true,
|
||||
animation: "scale-subtle",
|
||||
|
@ -12,7 +14,7 @@ export function ToolTip(props: Props): JSX.Element {
|
|||
};
|
||||
|
||||
return (
|
||||
<Tippy className={`text-[80%] ${newProps.className}`} {...newProps}>
|
||||
<Tippy {...newProps}>
|
||||
<div>{props.children}</div>
|
||||
</Tippy>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import { Chip } from "components/Chip";
|
||||
import { ToolTip } from "components/ToolTip";
|
||||
import { AppStaticProps } from "graphql/getAppStaticProps";
|
||||
import { getStatusDescription } from "helpers/others";
|
||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||
|
||||
interface Props {
|
||||
source?: string;
|
||||
translations:
|
||||
| {
|
||||
language: string | undefined;
|
||||
definition: string | null | undefined;
|
||||
status: string | undefined;
|
||||
}[]
|
||||
| undefined;
|
||||
languages: AppStaticProps["languages"];
|
||||
langui: AppStaticProps["langui"];
|
||||
index: number;
|
||||
}
|
||||
|
||||
export default function DefinitionCard(props: Props): JSX.Element {
|
||||
const { source, translations = [], languages, langui, index } = props;
|
||||
|
||||
const [selectedTranslation, LanguageSwitcher] = useSmartLanguage({
|
||||
items: translations,
|
||||
languages: languages,
|
||||
languageExtractor: (item) => item.language,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex place-items-center gap-2">
|
||||
{/* TODO: Langui */}
|
||||
<p className="font-headers text-lg">{`Definition ${index}`}</p>
|
||||
{selectedTranslation?.status && (
|
||||
<ToolTip
|
||||
content={getStatusDescription(selectedTranslation.status, langui)}
|
||||
maxWidth={"20rem"}
|
||||
>
|
||||
<Chip>{selectedTranslation.status}</Chip>
|
||||
</ToolTip>
|
||||
)}
|
||||
{translations.length > 1 && <LanguageSwitcher />}
|
||||
</div>
|
||||
|
||||
<p className="italic">{`${langui.source}: ${source}`}</p>
|
||||
<p>{selectedTranslation?.definition}</p>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export function cIf(
|
||||
condition: boolean | null | undefined | string,
|
||||
ifTrueCss: string,
|
||||
ifFalseCss?: string
|
||||
) {
|
||||
return condition ? ifTrueCss : ifFalseCss ?? "";
|
||||
}
|
||||
|
||||
export function cJoin(...args: (string | undefined)[]): string {
|
||||
return args.filter((elem) => elem).join(" ");
|
||||
}
|
|
@ -1,4 +1,8 @@
|
|||
import { GetContentTextQuery, GetPostQuery } from "graphql/generated";
|
||||
import {
|
||||
GetContentTextQuery,
|
||||
GetPostQuery,
|
||||
GetWikiPageQuery,
|
||||
} from "graphql/generated";
|
||||
import React from "react";
|
||||
|
||||
type Post = NonNullable<
|
||||
|
@ -17,6 +21,15 @@ export interface ContentWithTranslations extends Omit<Content, "translations"> {
|
|||
translations: NonNullable<Content["translations"]>;
|
||||
}
|
||||
|
||||
type WikiPage = NonNullable<
|
||||
NonNullable<GetWikiPageQuery["wikiPages"]>["data"][number]["attributes"]
|
||||
>;
|
||||
|
||||
export interface WikiPageWithTranslations
|
||||
extends Omit<WikiPage, "translations"> {
|
||||
translations: NonNullable<WikiPage["translations"]>;
|
||||
}
|
||||
|
||||
type ImmutableBlackList<T> = JSX.Element | React.ReactNode | Function;
|
||||
|
||||
export type Immutable<T> = {
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
getPostStaticProps,
|
||||
PostStaticProps,
|
||||
} from "graphql/getPostStaticProps";
|
||||
import { cIf, cJoin } from "helpers/className";
|
||||
import { randomInt } from "helpers/numbers";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { useRouter } from "next/router";
|
||||
|
@ -27,10 +28,13 @@ export default function AboutUs(
|
|||
const contactForm = (
|
||||
<div className="flex flex-col gap-8 text-center">
|
||||
<form
|
||||
className={`grid gap-8 ${
|
||||
formState !== "stale" &&
|
||||
className={cJoin(
|
||||
"grid gap-8",
|
||||
cIf(
|
||||
formState !== "stale",
|
||||
"pointer-events-none cursor-not-allowed touch-none opacity-60"
|
||||
}`}
|
||||
)
|
||||
)}
|
||||
onSubmit={(event) => {
|
||||
event.preventDefault();
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ export default function Channel(props: Props): JSX.Element {
|
|||
);
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
<div className="mb-8">
|
||||
<h1 className="text-3xl">{channel?.title}</h1>
|
||||
<p>{channel?.subscribers.toLocaleString()} subscribers</p>
|
||||
|
|
|
@ -82,7 +82,7 @@ export default function Videos(props: Props): JSX.Element {
|
|||
);
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
<PageSelector
|
||||
maxPage={Math.floor(videos.length / itemPerPage)}
|
||||
page={page}
|
||||
|
|
|
@ -72,7 +72,7 @@ export default function Video(props: Props): JSX.Element {
|
|||
);
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
<ReturnButton
|
||||
href="/library/"
|
||||
title={langui.library}
|
||||
|
|
|
@ -425,10 +425,7 @@ export async function getStaticProps(
|
|||
language_code: context.locale ?? "en",
|
||||
});
|
||||
|
||||
if (
|
||||
!content.contents ||
|
||||
!content.contents.data[0]?.attributes?.translations
|
||||
) {
|
||||
if (!content.contents?.data[0]?.attributes?.translations) {
|
||||
return { notFound: true };
|
||||
}
|
||||
const props: Props = {
|
||||
|
|
|
@ -143,16 +143,15 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
|||
</SubPanel>
|
||||
);
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
{[...groups].map(([name, items]) => (
|
||||
<Fragment key={name}>
|
||||
{items.length > 0 && (
|
||||
<Fragment>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
{[...groups].map(
|
||||
([name, items], index) =>
|
||||
items.length > 0 && (
|
||||
<Fragment key={index}>
|
||||
{name && (
|
||||
<h2
|
||||
key={`h2${name}`}
|
||||
className="flex flex-row place-items-center gap-2
|
||||
pb-2 pt-10 text-2xl first-of-type:pt-0"
|
||||
className="flex flex-row place-items-center gap-2 pb-2 pt-10 text-2xl
|
||||
first-of-type:pt-0"
|
||||
>
|
||||
{name}
|
||||
<Chip>{`${items.reduce((currentSum, item) => {
|
||||
|
@ -173,8 +172,8 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
|||
}`}</Chip>
|
||||
</h2>
|
||||
)}
|
||||
|
||||
<div
|
||||
key={`items${name}`}
|
||||
className="grid grid-cols-2 items-end gap-8
|
||||
desktop:grid-cols-[repeat(auto-fill,_minmax(15rem,1fr))] mobile:gap-4"
|
||||
>
|
||||
|
@ -226,9 +225,8 @@ export default function Contents(props: Immutable<Props>): JSX.Element {
|
|||
))}
|
||||
</div>
|
||||
</Fragment>
|
||||
)
|
||||
)}
|
||||
</Fragment>
|
||||
))}
|
||||
</ContentPanel>
|
||||
);
|
||||
return (
|
||||
|
|
|
@ -21,7 +21,7 @@ export default function CheckupContents(props: Immutable<Props>): JSX.Element {
|
|||
const testReport = testingContent(contents);
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
{<h2 className="text-2xl">{testReport.title}</h2>}
|
||||
|
||||
<div className="my-4 grid grid-cols-[2em,3em,2fr,1fr,0.5fr,0.5fr,2fr] items-center gap-2">
|
||||
|
@ -37,8 +37,8 @@ export default function CheckupContents(props: Immutable<Props>): JSX.Element {
|
|||
{testReport.lines.map((line, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="mb-2 grid
|
||||
grid-cols-[2em,3em,2fr,1fr,0.5fr,0.5fr,2fr] items-center justify-items-start gap-2"
|
||||
className="mb-2 grid grid-cols-[2em,3em,2fr,1fr,0.5fr,0.5fr,2fr] items-center
|
||||
justify-items-start gap-2"
|
||||
>
|
||||
<Button
|
||||
href={line.frontendUrl}
|
||||
|
|
|
@ -26,7 +26,7 @@ export default function CheckupLibraryItems(
|
|||
const testReport = testingLibraryItem(libraryItems);
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
{<h2 className="text-2xl">{testReport.title}</h2>}
|
||||
|
||||
<div className="my-4 grid grid-cols-[2em,3em,2fr,1fr,0.5fr,0.5fr,2fr] items-center gap-2">
|
||||
|
|
|
@ -146,7 +146,7 @@ export default function Editor(props: Immutable<Props>): JSX.Element {
|
|||
}
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
<Popup setState={setConverterOpened} state={converterOpened}>
|
||||
<div className="text-center">
|
||||
<h2 className="mt-4">Convert HTML to markdown</h2>
|
||||
|
|
|
@ -16,9 +16,8 @@ export default function Home(props: Immutable<PostStaticProps>): JSX.Element {
|
|||
prependBody={
|
||||
<div className="grid w-full place-content-center place-items-center gap-5 text-center">
|
||||
<div
|
||||
className="aspect-square w-32
|
||||
bg-black [mask:url('/icons/accords.svg')] [mask-size:contain] [mask-repeat:no-repeat]
|
||||
[mask-position:center] mobile:w-[50vw]"
|
||||
className="aspect-square w-32 bg-black [mask:url('/icons/accords.svg')]
|
||||
[mask-size:contain] [mask-repeat:no-repeat] [mask-position:center] mobile:w-[50vw]"
|
||||
/>
|
||||
<h1 className="mb-0 text-5xl">Accord’s Library</h1>
|
||||
<h2 className="-mt-5 text-xl">
|
||||
|
|
|
@ -119,7 +119,7 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
|||
);
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
<LightBox />
|
||||
|
||||
<ReturnButton
|
||||
|
@ -444,6 +444,7 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
|||
subtitle={subitem.attributes.subtitle}
|
||||
thumbnail={subitem.attributes.thumbnail?.data?.attributes}
|
||||
thumbnailAspectRatio="21/29.7"
|
||||
thumbnailRounded={false}
|
||||
keepInfoVisible={keepInfoVisible}
|
||||
topChips={
|
||||
subitem.attributes.metadata &&
|
||||
|
|
|
@ -69,7 +69,7 @@ export default function LibrarySlug(props: Immutable<Props>): JSX.Element {
|
|||
);
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
<LightBox />
|
||||
|
||||
<ReturnButton
|
||||
|
|
|
@ -250,7 +250,7 @@ export default function Library(props: Immutable<Props>): JSX.Element {
|
|||
</SubPanel>
|
||||
);
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
{[...groups].map(([name, items]) => (
|
||||
<Fragment key={name}>
|
||||
{items.length > 0 && (
|
||||
|
|
|
@ -85,7 +85,7 @@ export default function News(props: Immutable<Props>): JSX.Element {
|
|||
);
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
<div
|
||||
className="grid grid-cols-1 items-end gap-8
|
||||
desktop:grid-cols-[repeat(auto-fill,_minmax(20rem,1fr))]"
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
import { AppLayout } from "components/AppLayout";
|
||||
import { ContentPanel } from "components/Panels/ContentPanel";
|
||||
import { Chip } from "components/Chip";
|
||||
import { HorizontalLine } from "components/HorizontalLine";
|
||||
import { Img } from "components/Img";
|
||||
import {
|
||||
ReturnButton,
|
||||
ReturnButtonType,
|
||||
} from "components/PanelComponents/ReturnButton";
|
||||
import {
|
||||
ContentPanel,
|
||||
ContentPanelWidthSizes,
|
||||
} from "components/Panels/ContentPanel";
|
||||
import { SubPanel } from "components/Panels/SubPanel";
|
||||
import { GetWikiPageQuery } from "graphql/generated";
|
||||
import DefinitionCard from "components/Wiki/DefinitionCard";
|
||||
import { AppStaticProps, getAppStaticProps } from "graphql/getAppStaticProps";
|
||||
import { getReadySdk } from "graphql/sdk";
|
||||
import { Immutable } from "helpers/types";
|
||||
import { Immutable, WikiPageWithTranslations } from "helpers/types";
|
||||
import { useSmartLanguage } from "hooks/useSmartLanguage";
|
||||
import {
|
||||
GetStaticPathsContext,
|
||||
GetStaticPathsResult,
|
||||
|
@ -12,16 +23,89 @@ import {
|
|||
} from "next";
|
||||
|
||||
interface Props extends AppStaticProps {
|
||||
page: NonNullable<
|
||||
NonNullable<GetWikiPageQuery["wikiPages"]>["data"][number]["attributes"]
|
||||
>;
|
||||
page: WikiPageWithTranslations;
|
||||
}
|
||||
|
||||
export default function WikiPage(props: Immutable<Props>): JSX.Element {
|
||||
const { page, langui } = props;
|
||||
const { page, langui, languages } = props;
|
||||
|
||||
const subPanel = <SubPanel>Hello</SubPanel>;
|
||||
const contentPanel = <ContentPanel>{page.slug}</ContentPanel>;
|
||||
const [selectedTranslation, LanguageSwitcher] = useSmartLanguage({
|
||||
items: page.translations,
|
||||
languages: languages,
|
||||
languageExtractor: (item) => item.language?.data?.attributes?.code,
|
||||
});
|
||||
|
||||
const subPanel = (
|
||||
<SubPanel>
|
||||
<ReturnButton
|
||||
href={`/wiki`}
|
||||
title={langui.wiki}
|
||||
langui={langui}
|
||||
displayOn={ReturnButtonType.Desktop}
|
||||
horizontalLine
|
||||
/>
|
||||
</SubPanel>
|
||||
);
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ReturnButton
|
||||
href={`/wiki`}
|
||||
title={langui.wiki}
|
||||
langui={langui}
|
||||
displayOn={ReturnButtonType.Mobile}
|
||||
className="mb-10"
|
||||
/>
|
||||
|
||||
<div className="flex place-content-center gap-4">
|
||||
<h1 className="text-center text-3xl">{selectedTranslation?.title}</h1>
|
||||
<LanguageSwitcher />
|
||||
</div>
|
||||
|
||||
<HorizontalLine />
|
||||
|
||||
{selectedTranslation && (
|
||||
<div className="text-justify">
|
||||
<div
|
||||
className="float-right ml-8 mb-8 w-[25rem] overflow-hidden rounded-lg bg-mid
|
||||
text-center"
|
||||
>
|
||||
{page.thumbnail?.data?.attributes && (
|
||||
<Img image={page.thumbnail.data.attributes} />
|
||||
)}
|
||||
<div className="my-4 grid gap-4 p-4">
|
||||
<p className="font-headers text-xl">{langui.categories}</p>
|
||||
<div className="flex flex-row flex-wrap place-content-center gap-2">
|
||||
{page.categories?.data.map((category) => (
|
||||
<Chip key={category.id}>{category.attributes?.name}</Chip>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{selectedTranslation.summary && (
|
||||
<div className="mb-6">
|
||||
<p className="font-headers text-lg">{langui.summary}</p>
|
||||
<p>{selectedTranslation.summary}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{page.definitions?.map((definition, index) => (
|
||||
<DefinitionCard
|
||||
key={index}
|
||||
source={definition?.source?.data?.attributes?.name}
|
||||
translations={definition?.translations?.map((translation) => ({
|
||||
language: translation?.language?.data?.attributes?.code,
|
||||
definition: translation?.definition,
|
||||
status: translation?.status,
|
||||
}))}
|
||||
index={index + 1}
|
||||
languages={languages}
|
||||
langui={langui}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</ContentPanel>
|
||||
);
|
||||
|
||||
return (
|
||||
<AppLayout
|
||||
|
@ -42,10 +126,11 @@ export async function getStaticProps(
|
|||
language_code: context.locale ?? "en",
|
||||
slug: slug,
|
||||
});
|
||||
if (!page.wikiPages?.data[0].attributes) return { notFound: true };
|
||||
if (!page.wikiPages?.data[0].attributes?.translations)
|
||||
return { notFound: true };
|
||||
const props: Props = {
|
||||
...(await getAppStaticProps(context)),
|
||||
page: page.wikiPages.data[0].attributes,
|
||||
page: page.wikiPages.data[0].attributes as WikiPageWithTranslations,
|
||||
};
|
||||
return {
|
||||
props: props,
|
||||
|
|
|
@ -92,7 +92,7 @@ export default function Wiki(props: Immutable<Props>): JSX.Element {
|
|||
);
|
||||
|
||||
const contentPanel = (
|
||||
<ContentPanel width={ContentPanelWidthSizes.Large}>
|
||||
<ContentPanel width={ContentPanelWidthSizes.Full}>
|
||||
<div
|
||||
className="grid grid-cols-2 items-end gap-8
|
||||
desktop:grid-cols-[repeat(auto-fill,_minmax(20rem,1fr))] mobile:gap-4"
|
||||
|
|
|
@ -172,6 +172,19 @@ input[type="submit"] {
|
|||
[background-blend-mode:var(--theme-texture-dots-blend)];
|
||||
}
|
||||
|
||||
/* DEBUGGING */
|
||||
.false {
|
||||
@apply border-2 border-[red] text-[red] outline-dotted outline-2 outline-[red];
|
||||
}
|
||||
|
||||
.undefined {
|
||||
@apply border-2 border-[green] text-[green] outline-dotted outline-2 outline-[green];
|
||||
}
|
||||
|
||||
.null {
|
||||
@apply border-2 border-[blue] text-[blue] outline-dotted outline-2 outline-[blue];
|
||||
}
|
||||
|
||||
/* TIPPY */
|
||||
|
||||
.tippy-box[data-animation="fade"][data-state="hidden"] {
|
||||
|
|
Loading…
Reference in New Issue