diff --git a/.vscode/settings.json b/.vscode/settings.json
index ce0dc93..3747951 100755
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,5 @@
{
"css.lint.unknownAtRules": "ignore",
- "editor.rulers": [100]
+ "editor.rulers": [100],
+ "typescript.preferences.importModuleSpecifier": "non-relative"
}
diff --git a/package-lock.json b/package-lock.json
index 2ff4a58..343de73 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,7 +16,7 @@
"cuid": "^2.1.8",
"intl-messageformat": "^10.3.0",
"isomorphic-dompurify": "^0.26.0",
- "jotai": "^2.0.0",
+ "jotai": "^2.0.1",
"markdown-to-jsx": "^7.1.9",
"marked": "^4.2.12",
"material-symbols": "^0.4.4",
@@ -35,7 +35,7 @@
"turndown": "^7.1.1",
"ua-parser-js": "^1.0.33",
"usehooks-ts": "^2.9.1",
- "zod": "^3.20.5"
+ "zod": "^3.20.6"
},
"devDependencies": {
"@digitak/esrun": "^3.2.19",
@@ -60,7 +60,7 @@
"eslint-plugin-import": "^2.27.5",
"graphql": "^16.6.0",
"graphql-request": "^5.1.0",
- "next-sitemap": "^3.1.50",
+ "next-sitemap": "^3.1.52",
"prettier": "^2.8.4",
"prettier-plugin-tailwindcss": "^0.2.2",
"tailwindcss": "^3.2.6",
@@ -7496,9 +7496,9 @@
}
},
"node_modules/jotai": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.0.0.tgz",
- "integrity": "sha512-04G0CRZQgp3xrFAezd6X14psZ2TRGekHeYMBcbDJ/BR8ZJQPS+j0YkMTxUxyG58HJnN2+adfj5sWQWoqgtp1XQ==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.0.1.tgz",
+ "integrity": "sha512-b/BpBFkv3nq8HgT6YX5h5/y9VfKIn9OL1dO6gd9bWTgKt6LLe24VIMURTDwSYS888XfubuRQlbepb5IQGAtmcQ==",
"engines": {
"node": ">=12.20.0"
},
@@ -8150,9 +8150,9 @@
}
},
"node_modules/next-sitemap": {
- "version": "3.1.50",
- "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-3.1.50.tgz",
- "integrity": "sha512-BnxAbjOK1zVcYvpZ4sYfhPXcL3ajLh/AIJLR39YKrhFxrD92KkiAGuVaKhfpoQLUf+ldsGBkGpdml2N5Qdd1KA==",
+ "version": "3.1.52",
+ "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-3.1.52.tgz",
+ "integrity": "sha512-tY469i4QRV1PwM9BoL+HdKYBCJ83IQl3PmUNapG/Hxp0MIYIw1hINU8E+Edf5Kr8vHXfVzPqDoul/Abu2P0vkw==",
"dev": true,
"funding": [
{
@@ -10741,9 +10741,9 @@
}
},
"node_modules/zod": {
- "version": "3.20.5",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.20.5.tgz",
- "integrity": "sha512-BTAAliwfoB9dWf2hC+TXlyWKk/YTqRGZjHQR0WLC2A2pzierWo7KuQ1ebjS4SNaFaxg/lDItzl9/QTgLjcHbgw==",
+ "version": "3.20.6",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.20.6.tgz",
+ "integrity": "sha512-oyu0m54SGCtzh6EClBVqDDlAYRz4jrVtKwQ7ZnsEmMI9HnzuZFj8QFwAY1M5uniIYACdGvv0PBWPF2kO0aNofA==",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
@@ -16385,9 +16385,9 @@
"requires": {}
},
"jotai": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.0.0.tgz",
- "integrity": "sha512-04G0CRZQgp3xrFAezd6X14psZ2TRGekHeYMBcbDJ/BR8ZJQPS+j0YkMTxUxyG58HJnN2+adfj5sWQWoqgtp1XQ==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.0.1.tgz",
+ "integrity": "sha512-b/BpBFkv3nq8HgT6YX5h5/y9VfKIn9OL1dO6gd9bWTgKt6LLe24VIMURTDwSYS888XfubuRQlbepb5IQGAtmcQ==",
"requires": {}
},
"js-sdsl": {
@@ -16871,9 +16871,9 @@
}
},
"next-sitemap": {
- "version": "3.1.50",
- "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-3.1.50.tgz",
- "integrity": "sha512-BnxAbjOK1zVcYvpZ4sYfhPXcL3ajLh/AIJLR39YKrhFxrD92KkiAGuVaKhfpoQLUf+ldsGBkGpdml2N5Qdd1KA==",
+ "version": "3.1.52",
+ "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-3.1.52.tgz",
+ "integrity": "sha512-tY469i4QRV1PwM9BoL+HdKYBCJ83IQl3PmUNapG/Hxp0MIYIw1hINU8E+Edf5Kr8vHXfVzPqDoul/Abu2P0vkw==",
"dev": true,
"requires": {
"@corex/deepmerge": "^4.0.29",
@@ -18719,9 +18719,9 @@
"dev": true
},
"zod": {
- "version": "3.20.5",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.20.5.tgz",
- "integrity": "sha512-BTAAliwfoB9dWf2hC+TXlyWKk/YTqRGZjHQR0WLC2A2pzierWo7KuQ1ebjS4SNaFaxg/lDItzl9/QTgLjcHbgw=="
+ "version": "3.20.6",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.20.6.tgz",
+ "integrity": "sha512-oyu0m54SGCtzh6EClBVqDDlAYRz4jrVtKwQ7ZnsEmMI9HnzuZFj8QFwAY1M5uniIYACdGvv0PBWPF2kO0aNofA=="
}
}
}
diff --git a/package.json b/package.json
index 9ba26d9..eb2b0ea 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,7 @@
"cuid": "^2.1.8",
"intl-messageformat": "^10.3.0",
"isomorphic-dompurify": "^0.26.0",
- "jotai": "^2.0.0",
+ "jotai": "^2.0.1",
"markdown-to-jsx": "^7.1.9",
"marked": "^4.2.12",
"material-symbols": "^0.4.4",
@@ -47,7 +47,7 @@
"turndown": "^7.1.1",
"ua-parser-js": "^1.0.33",
"usehooks-ts": "^2.9.1",
- "zod": "^3.20.5"
+ "zod": "^3.20.6"
},
"devDependencies": {
"@digitak/esrun": "^3.2.19",
@@ -72,7 +72,7 @@
"eslint-plugin-import": "^2.27.5",
"graphql": "^16.6.0",
"graphql-request": "^5.1.0",
- "next-sitemap": "^3.1.50",
+ "next-sitemap": "^3.1.52",
"prettier": "^2.8.4",
"prettier-plugin-tailwindcss": "^0.2.2",
"tailwindcss": "^3.2.6",
diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx
index 1dc8dc0..318ee8f 100644
--- a/src/components/AppLayout.tsx
+++ b/src/components/AppLayout.tsx
@@ -77,15 +77,19 @@ export const AppLayout = ({
},
});
- const turnSubIntoContent = isDefined(subPanel) && isUndefined(contentPanel);
+ const turnSubIntoContent = isDefined(subPanel) && isUndefined(contentPanel) && is1ColumnLayout;
return (
+ {/* Content panel */}
+
+ {isDefined(contentPanel) ? (
+ contentPanel
+ ) : turnSubIntoContent ? (
+ subPanel
+ ) : (
+
+ )}
+
+
{/* Background when navbar is opened */}
@@ -140,57 +160,11 @@ export const AppLayout = ({
/>
- {/* Content panel */}
-
- {isDefined(contentPanel) ? (
- contentPanel
- ) : (
-
- )}
-
-
- {/* Sub panel */}
- {isDefined(subPanel) && (
-
- {subPanel}
-
- )}
-
- {/* Main panel */}
-
-
-
-
{/* Navbar */}
)}
+
+ {/* Sub panel */}
+ {isDefined(subPanel) && !turnSubIntoContent && (
+
+ {subPanel}
+
+ )}
+
+ {/* Main panel */}
+
+
+
);
};
diff --git a/src/components/Chronicles/ChroniclePreview.tsx b/src/components/Chronicles/ChroniclePreview.tsx
index f718b55..aaea763 100644
--- a/src/components/Chronicles/ChroniclePreview.tsx
+++ b/src/components/Chronicles/ChroniclePreview.tsx
@@ -1,4 +1,4 @@
-import { useCallback } from "react";
+import { MouseEventHandler, useCallback } from "react";
import { DatePickerFragment } from "graphql/generated";
import { TranslatedProps } from "types/TranslatedProps";
import { useSmartLanguage } from "hooks/useSmartLanguage";
@@ -17,12 +17,21 @@ interface Props {
url: string;
active?: boolean;
disabled?: boolean;
+ onClick?: MouseEventHandler;
}
-export const ChroniclePreview = ({ date, url, title, active, disabled }: Props): JSX.Element => (
+export const ChroniclePreview = ({
+ date,
+ url,
+ title,
+ active,
+ disabled,
+ onClick,
+}: Props): JSX.Element => (
diff --git a/src/components/Chronicles/ChroniclesList.tsx b/src/components/Chronicles/ChroniclesList.tsx
index 963083d..fbb6c47 100644
--- a/src/components/Chronicles/ChroniclesList.tsx
+++ b/src/components/Chronicles/ChroniclesList.tsx
@@ -8,6 +8,8 @@ import { Ico } from "components/Ico";
import { compareDate } from "helpers/date";
import { TranslatedProps } from "types/TranslatedProps";
import { useSmartLanguage } from "hooks/useSmartLanguage";
+import { useAtomSetter } from "helpers/atoms";
+import { atoms } from "contexts/atoms";
/*
* ╭─────────────╮
@@ -25,6 +27,7 @@ interface Props {
}
const ChroniclesList = ({ chronicles, currentSlug, title }: Props): JSX.Element => {
+ const setSubPanelOpened = useAtomSetter(atoms.layout.subPanelOpened);
const { value: isOpen, toggle: toggleOpen } = useBoolean(
chronicles.some((chronicle) => chronicle.attributes?.slug === currentSlug)
);
@@ -75,6 +78,7 @@ const ChroniclesList = ({ chronicles, currentSlug, title }: Props): JSX.Element
"/#chronicle-",
chronicle.attributes.slug
)}
+ onClick={() => setSubPanelOpened(false)}
/>
))
: chronicle.attributes.translations.length > 0 && (
diff --git a/src/components/Containers/ContentPanel.tsx b/src/components/Containers/ContentPanel.tsx
index add70a4..f46e805 100644
--- a/src/components/Containers/ContentPanel.tsx
+++ b/src/components/Containers/ContentPanel.tsx
@@ -19,6 +19,12 @@ export enum ContentPanelWidthSizes {
Full = "full",
}
+const contentPanelWidthSizesToClassName: Record = {
+ default: "max-w-2xl",
+ large: "max-w-4xl",
+ full: "w-full",
+};
+
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
export const ContentPanel = ({
@@ -31,13 +37,9 @@ export const ContentPanel = ({
{children}
diff --git a/src/components/Containers/DownPressable.tsx b/src/components/Containers/DownPressable.tsx
index 7852ffc..2c93946 100644
--- a/src/components/Containers/DownPressable.tsx
+++ b/src/components/Containers/DownPressable.tsx
@@ -14,7 +14,7 @@ interface Props {
children: React.ReactNode;
className?: string;
onFocusChanged?: (isFocused: boolean) => void;
- onClick?: MouseEventHandler;
+ onClick?: MouseEventHandler;
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
diff --git a/src/components/Containers/UpPressable.tsx b/src/components/Containers/UpPressable.tsx
index 75b6d5a..a9be0a9 100644
--- a/src/components/Containers/UpPressable.tsx
+++ b/src/components/Containers/UpPressable.tsx
@@ -1,4 +1,4 @@
-import { useState } from "react";
+import { MouseEventHandler, useState } from "react";
import { Link } from "components/Inputs/Link";
import { cIf, cJoin } from "helpers/className";
@@ -8,6 +8,7 @@ interface Props {
className?: string;
noBackground?: boolean;
disabled?: boolean;
+ onClick?: MouseEventHandler;
}
export const UpPressable = ({
@@ -16,12 +17,14 @@ export const UpPressable = ({
className,
disabled = false,
noBackground = false,
+ onClick,
}: Props): JSX.Element => {
const [isFocused, setFocused] = useState(false);
return (
event.target.blur()}
className={cJoin(
`group grid cursor-pointer select-none grid-flow-col place-content-center
- place-items-center gap-2 rounded-full border border-dark py-3 px-4
+ place-items-center gap-2 rounded-full border border-dark
leading-none text-dark transition-all`,
- cIf(size === "small", "px-3 py-1 text-xs"),
+ cIf(size === "small", "px-3 py-1 text-xs", "py-3 px-4"),
cIf(active, "!border-black bg-black !text-light drop-shadow-lg shadow-black"),
cIf(
disabled,
@@ -74,16 +74,16 @@ export const Button = ({
{isDefined(badgeNumber) && (
)}
{isDefinedAndNotEmpty(icon) && (
;
+ onClick?: MouseEventHandler;
onFocusChanged?: (isFocused: boolean) => void;
disabled?: boolean;
linkStyled?: boolean;
@@ -22,6 +22,7 @@ export const Link = ({
alwaysNewTab,
disabled,
linkStyled = false,
+ onClick,
onFocusChanged,
}: Props): JSX.Element => (
void;
+ onClick?: MouseEventHandler;
}
const LinkWrapper = ({
children,
className,
onFocusChanged,
+ onClick,
alwaysNewTab = false,
href,
}: LinkWrapperProps & Wrapper) => (
@@ -65,6 +69,7 @@ const LinkWrapper = ({
className={className}
target={alwaysNewTab ? "_blank" : "_self"}
replace={href.startsWith("#")}
+ onClick={onClick}
onMouseLeave={() => onFocusChanged?.(false)}
onMouseDown={() => onFocusChanged?.(true)}
onMouseUp={() => onFocusChanged?.(false)}>
diff --git a/src/components/Inputs/Select.tsx b/src/components/Inputs/Select.tsx
index 2c84120..fd61c54 100644
--- a/src/components/Inputs/Select.tsx
+++ b/src/components/Inputs/Select.tsx
@@ -58,13 +58,12 @@ export const Select = ({
diff --git a/src/components/Inputs/Switch.tsx b/src/components/Inputs/Switch.tsx
index f7b1a7f..fd3a74d 100644
--- a/src/components/Inputs/Switch.tsx
+++ b/src/components/Inputs/Switch.tsx
@@ -21,10 +21,14 @@ export const Switch = ({ value, onClick, className, disabled = false }: Props):
{
diff --git a/src/components/Markdown/Markdawn.tsx b/src/components/Markdown/Markdawn.tsx
index ca9ddea..67d85ce 100644
--- a/src/components/Markdown/Markdawn.tsx
+++ b/src/components/Markdown/Markdawn.tsx
@@ -1,5 +1,5 @@
import Markdown from "markdown-to-jsx";
-import React, { Fragment, useMemo } from "react";
+import React, { Fragment, MouseEventHandler, useMemo } from "react";
import ReactDOMServer from "react-dom/server";
import { HorizontalLine } from "components/HorizontalLine";
import { Img } from "components/Img";
@@ -218,13 +218,13 @@ export const Markdawn = ({ className, text: rawText }: MarkdawnProps): JSX.Eleme
interface TableOfContentsProps {
text: string;
title?: string;
- horizontalLine?: boolean;
+ onContentClicked?: MouseEventHandler
;
}
export const TableOfContents = ({
text,
title,
- horizontalLine = false,
+ onContentClicked,
}: TableOfContentsProps): JSX.Element => {
const { format } = useFormat();
const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title);
@@ -233,17 +233,20 @@ export const TableOfContents = ({
<>
{toc.children.length > 0 && (
<>
- {horizontalLine && }
{format("table_of_contents")}
>
)}
@@ -334,12 +337,14 @@ interface LevelProps {
tocchildren: TocInterface[];
parentNumbering: string;
allowIntersection?: boolean;
+ onContentClicked?: MouseEventHandler;
}
const TocLevel = ({
tocchildren,
parentNumbering,
allowIntersection = true,
+ onContentClicked,
}: LevelProps): JSX.Element => {
const ids = useMemo(() => tocchildren.map((child) => child.slug), [tocchildren]);
const currentIntersection = useIntersectionList(ids);
@@ -354,7 +359,7 @@ const TocLevel = ({
cIf(allowIntersection && currentIntersection === childIndex, "text-dark")
)}>
{`${parentNumbering}${childIndex + 1}.`}{" "}
-
+
{{child.title}}
@@ -362,6 +367,7 @@ const TocLevel = ({
tocchildren={child.children}
parentNumbering={`${parentNumbering}${childIndex + 1}.`}
allowIntersection={allowIntersection && currentIntersection === childIndex}
+ onContentClicked={onContentClicked}
/>
))}
diff --git a/src/components/PanelComponents/NavOption.tsx b/src/components/PanelComponents/NavOption.tsx
index 7c582d0..e8d20f3 100644
--- a/src/components/PanelComponents/NavOption.tsx
+++ b/src/components/PanelComponents/NavOption.tsx
@@ -23,7 +23,7 @@ interface Props {
reduced?: boolean;
active?: boolean;
disabled?: boolean;
- onClick?: MouseEventHandler;
+ onClick?: MouseEventHandler;
}
// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
diff --git a/src/components/Panels/MainPanel.tsx b/src/components/Panels/MainPanel.tsx
index 6d15879..bacb85a 100644
--- a/src/components/Panels/MainPanel.tsx
+++ b/src/components/Panels/MainPanel.tsx
@@ -1,3 +1,4 @@
+import { useCallback } from "react";
import { HorizontalLine } from "components/HorizontalLine";
import { Button } from "components/Inputs/Button";
import { NavOption } from "components/PanelComponents/NavOption";
@@ -21,6 +22,8 @@ export const MainPanel = (): JSX.Element => {
const is3ColumnsLayout = useAtomGetter(atoms.containerQueries.is3ColumnsLayout);
const { format } = useFormat();
const [isMainPanelReduced, setMainPanelReduced] = useAtomPair(atoms.layout.mainPanelReduced);
+ const setMainPanelOpened = useAtomSetter(atoms.layout.mainPanelOpened);
+ const closeMainPanel = useCallback(() => setMainPanelOpened(false), [setMainPanelOpened]);
const setSettingsOpened = useAtomSetter(atoms.layout.settingsOpened);
const setSearchOpened = useAtomSetter(atoms.layout.searchOpened);
@@ -53,7 +56,10 @@ export const MainPanel = (): JSX.Element => {
)}
-
+
{
placement={isMainPanelReduced ? "right" : "top"}>