Library looks much better and panel headers

This commit is contained in:
DrMint 2022-01-03 03:40:54 +01:00
parent cf00c2c6cb
commit 9fdd1ead6b
20 changed files with 252 additions and 130 deletions

View File

@ -17,5 +17,6 @@
- Markdown automatic formatting using [Tailwind/Typography](https://tailwindcss.com/docs/typography-plugin)
- Beside the theme declaration no CSS outside of Tailwind CSS
- Manually added support for scrollbar styling
- Support for [Material Icons](https://fonts.google.com/icons)
- Framework: [Next.js](https://nextjs.org/) (React)
- Multilanguage support

22
package-lock.json generated
View File

@ -5,6 +5,8 @@
"packages": {
"": {
"dependencies": {
"@fontsource/material-icons": "^4.5.0",
"@fontsource/material-icons-rounded": "^4.5.0",
"@fontsource/vollkorn": "^4.5.1",
"@fontsource/zen-maru-gothic": "^4.5.3",
"next": "^12.0.7",
@ -745,6 +747,16 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@fontsource/material-icons": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/@fontsource/material-icons/-/material-icons-4.5.0.tgz",
"integrity": "sha512-vFMpnkKwbtJLLHbUDI163QWX9Ox28A6i1vALfAKlpBh54yp8D0cu1/YGyrU5whvaXejLSBuyS7lRwr/TdRNmhA=="
},
"node_modules/@fontsource/material-icons-rounded": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/@fontsource/material-icons-rounded/-/material-icons-rounded-4.5.0.tgz",
"integrity": "sha512-5IqqgYjI2gs3zryb0UTk0US9deA+5J2R1A/G4jMRdlY0eopWoHtmcX9OLlssPkCrITcyj+bwpDbsFm9nrw65JA=="
},
"node_modules/@fontsource/vollkorn": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/@fontsource/vollkorn/-/vollkorn-4.5.1.tgz",
@ -6784,6 +6796,16 @@
}
}
},
"@fontsource/material-icons": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/@fontsource/material-icons/-/material-icons-4.5.0.tgz",
"integrity": "sha512-vFMpnkKwbtJLLHbUDI163QWX9Ox28A6i1vALfAKlpBh54yp8D0cu1/YGyrU5whvaXejLSBuyS7lRwr/TdRNmhA=="
},
"@fontsource/material-icons-rounded": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/@fontsource/material-icons-rounded/-/material-icons-rounded-4.5.0.tgz",
"integrity": "sha512-5IqqgYjI2gs3zryb0UTk0US9deA+5J2R1A/G4jMRdlY0eopWoHtmcX9OLlssPkCrITcyj+bwpDbsFm9nrw65JA=="
},
"@fontsource/vollkorn": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/@fontsource/vollkorn/-/vollkorn-4.5.1.tgz",

View File

@ -8,6 +8,8 @@
"lint": "next lint"
},
"dependencies": {
"@fontsource/material-icons": "^4.5.0",
"@fontsource/material-icons-rounded": "^4.5.0",
"@fontsource/vollkorn": "^4.5.1",
"@fontsource/zen-maru-gothic": "^4.5.3",
"next": "^12.0.7",

View File

@ -103,10 +103,10 @@ export default function ChronologyItemComponent(
</>
))}
<p className="text-dark text-xs">
<p className="text-dark text-xs inline-grid place-items-center grid-flow-col gap-1">
{event.source.data
? "(" + event.source.data.attributes.name + ")"
: "(WARNING: NO SOURCE!)"}
: <><span className="material-icons !text-sm">warning</span>No sources!</>}
</p>
</div>
))}

View File

@ -1,5 +1,4 @@
import Link from "next/link";
import Image from "next/image";
import { GetLibraryItemsPreviewQuery } from "graphql/operations-types";
import { getAssetURL } from "queries/helpers";
@ -10,12 +9,6 @@ export type LibraryItemComponentProps = {
export default function LibraryItemComponent(
props: LibraryItemComponentProps
): JSX.Element {
function prettyTitleSubtitle(title: string, subtitle: string): string {
let result = title;
if (subtitle !== null) result += " - " + subtitle;
return result;
}
function prettyDate(
date: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"]
): string {
@ -30,29 +23,43 @@ export default function LibraryItemComponent(
return (
<Link href={"/library/" + props.item.attributes.slug} passHref>
<div className="">
<h2>
{prettyTitleSubtitle(
props.item.attributes.title,
props.item.attributes.subtitle
)}
</h2>
<p>{prettyDate(props.item.attributes.release_date)}</p>
<div className="cursor-pointer grid items-end relative hover:rounded-3xl [--cover-opacity:0] hover:[--cover-opacity:1] hover:scale-[1.02] transition-transform">
<div className="bg-light absolute inset-1 rounded-lg shadow-dark shadow-xl"></div>
{props.item.attributes.thumbnail.data ? (
<Image
<img
className="z-10"
src={getAssetURL(
props.item.attributes.thumbnail.data.attributes.url
)}
alt={
props.item.attributes.thumbnail.data.attributes.alternativeText
}
width={props.item.attributes.thumbnail.data.attributes.width}
height={props.item.attributes.thumbnail.data.attributes.height}
/>
) : (
""
<div className="w-full aspect-[21/29.7]"></div>
)}
<div className="[background:linear-gradient(to_right,_#f0d1b3,_#ffedd8_3%,_#ffedd8_97%,_#f0d1b3)] shadow-[0_0_1em_rgb(0,0,0,0.2)] absolute bottom-0 left-0 right-0 h-auto opacity-[var(--cover-opacity)] transition-opacity z-20 grid p-4 gap-4 text-left">
<div>
<h2 className="text-lg leading-7">{props.item.attributes.title}</h2>
<h3 className="leading-3">{props.item.attributes.subtitle}</h3>
</div>
<div className="grid grid-flow-col">
<p className="text-sm">
<span className="material-icons !text-base translate-y-[.15em] mr-1">
event
</span>
{prettyDate(props.item.attributes.release_date)}
</p>
{props.item.attributes.price ? (
<p className="text-sm justify-self-end">
<span className="material-icons !text-base translate-y-[.15em] mr-1">
shopping_cart
</span>
{props.item.attributes.price.currency.data.attributes.symbol}
{props.item.attributes.price.amount}
</p>
) : (
""
)}
</div>
</div>
</div>
</Link>
);

View File

@ -14,13 +14,13 @@ export default function NavOption(props: NavOptionProps): JSX.Element {
const isActive = router.asPath.startsWith(props.url);
const divActive = "bg-mid"
const border = "border-2 border-mid";
const divCommon = `gap-x-4 w-full rounded-2xl cursor-pointer p-4 hover:bg-mid transition-colors ${props.border ? border: ""} ${isActive ? divActive : ""}`;
const divCommon = `gap-x-5 w-full rounded-2xl cursor-pointer p-4 hover:bg-mid transition-colors ${props.border ? border: ""} ${isActive ? divActive : ""}`;
if (props.icon) {
return (
<Link href={props.url} passHref>
<div className={`grid grid-cols-[auto_1fr] text-left ${divCommon}`}>
<img className="w-5" src={props.icon} alt="" />
<span className="material-icons mt-[.1em]">{props.icon}</span>
<h3 className="text-2xl">{props.title}</h3>
{props.subtitle && <p className="col-start-2">{props.subtitle}</p>}
</div>

View File

@ -0,0 +1,20 @@
type NavOptionProps = {
icon?: string;
title: string;
description?: string;
};
export default function NavOption(props: NavOptionProps): JSX.Element {
return (
<div className="w-full grid place-items-center">
{props.icon ? (
<span className="material-icons !text-4xl mb-3">{props.icon}</span>
) : (
""
)}
<h2 className="text-2xl">{props.title}</h2>
{props.description ? <p>{props.description}</p> : ""}
<hr />
</div>
);
}

View File

@ -15,7 +15,7 @@ export default function ContentPanel(props: ContentPanelProps): JSX.Element {
const prose = props.autoformat ? "prose" : "";
return (
<div className={`grid overflow-y-scroll max-h-screen py-20 px-10`}>
<div className={`grid overflow-y-scroll max-h-screen h-screen py-20 px-10`}>
<main className={`${prose} ${widthCSS} place-self-center text-justify`}>
{props.children}
</main>

View File

@ -1,19 +1,23 @@
import Link from "next/link";
import NavOption from "components/Panels/NavOption";
import NavOption from "components/PanelComponents/NavOption";
import SVG from "components/SVG";
export default function MainPanel(): JSX.Element {
return (
<div className="grid webkit-scrollbar:w-0 [scrollbar-width:none] overflow-y-scroll border-r-[1px] border-black w-80 h-full max-h-screen justify-center content-start p-8 gap-y-2 justify-items-center text-center">
<Link href="/" passHref>
<div className="grid place-items-center cursor-pointer">
<img
className="w-1/2 self-start justify-center"
src="/icons/accords.svg"
alt=""
/>
<h2 className="mt-4">Accord&apos;s Library</h2>
</div>
</Link>
<div className="grid webkit-scrollbar:w-0 [scrollbar-width:none] overflow-y-scroll border-r-[1px] border-black w-80 max-h-screen h-screen justify-center content-start p-8 gap-y-2 justify-items-center text-center">
<div className="transition-[filter] hover:colorize-dark">
<Link href="/" passHref>
<div className="grid place-items-center cursor-pointer">
<div className="w-1/2">
<SVG
src={"/icons/accords.svg"}
alt={"Logo of Accord's Library"}
/>
</div>
<h2 className="my-5 text-3xl">Accord&apos;s Library</h2>
</div>
</Link>
</div>
<button>Change language</button>
@ -21,46 +25,32 @@ export default function MainPanel(): JSX.Element {
<NavOption
url="/library"
icon="/icons/book-solid.svg"
icon="library_books"
title="Library"
subtitle="Browse all physical and digital media"
/>
<NavOption
url="/hubs"
icon="/icons/hubs.svg"
icon="workspaces"
title="Hubs"
subtitle="Explore all content of a specific game/series"
/>
<NavOption
url="/chronology"
icon="/icons/timeline-solid.svg"
icon="watch_later"
title="Chronology"
subtitle="Follow all events in chronological order"
/>
<hr />
<NavOption
url="/archive"
icon="/icons/box-archive-solid.svg"
title="Archive"
/>
<NavOption url="/news" icon="/icons/newspaper-solid.svg" title="News" />
<NavOption
url="/gallery"
icon="/icons/images-solid.svg"
title="Gallery"
/>
<NavOption
url="/about-us"
icon="/icons/circle-info-solid.svg"
title="About us"
/>
<NavOption url="/news" icon="feed" title="News" />
<NavOption url="/data" icon="travel_explore" title="Data" />
<NavOption url="/gallery" icon="collections" title="Gallery" />
<NavOption url="/archive" icon="inventory" title="Archive" />
<NavOption url="/about-us" icon="info" title="About us" />
<hr />
@ -70,22 +60,25 @@ export default function MainPanel(): JSX.Element {
<a href="https://creativecommons.org/licenses/by-sa/4.0/">CC-BY-SA</a>{" "}
unless otherwise noted.
</p>
<a href="https://creativecommons.org/licenses/by-sa/4.0/">
<div className="mt-4 mb-8 grid h-4 grid-flow-col place-content-center gap-1">
<img
className="h-6"
src="/icons/creative-commons-brands.svg"
alt=""
<a
className="transition-[filter] hover:colorize-dark"
href="https://creativecommons.org/licenses/by-sa/4.0/"
>
<div className="mt-4 mb-8 grid grid-flow-col place-content-center gap-1">
<SVG
className="w-6"
src={"/icons/creative-commons-brands.svg"}
alt={""}
/>
<img
className="h-6"
src="/icons/creative-commons-by-brands.svg"
alt=""
<SVG
className="w-6"
src={"/icons/creative-commons-by-brands.svg"}
alt={""}
/>
<img
className="h-6"
src="/icons/creative-commons-sa-brands.svg"
alt=""
<SVG
className="w-6"
src={"/icons/creative-commons-sa-brands.svg"}
alt={""}
/>
</div>
</a>
@ -95,11 +88,17 @@ export default function MainPanel(): JSX.Element {
SQUARE ENIX CO. LTD.
</p>
<div className="mt-12 mb-4 grid h-4 grid-flow-col place-content-center gap-8">
<a href="https://github.com/Accords-Library">
<img className="h-8" src="/icons/github-brands.svg" alt="" />
<a
className="transition-[filter] hover:colorize-dark"
href="https://github.com/Accords-Library"
>
<SVG className="w-10" src={"/icons/github-brands.svg"} alt={""} />
</a>
<a href="https://accords-library.com/discord">
<img className="h-8" src="/icons/discord-brands.svg" alt="" />
<a
className="transition-[filter] hover:colorize-dark"
href="https://accords-library.com/discord"
>
<SVG className="w-10" src={"/icons/discord-brands.svg"} alt={""} />
</a>
</div>
</div>

View File

@ -4,7 +4,7 @@ type SubPanelProps = {
export default function SubPanel(props: SubPanelProps): JSX.Element {
return (
<div className="grid webkit-scrollbar:w-0 [scrollbar-width:none] border-r-[1px] overflow-y-scroll border-black w-80 h-full max-h-screen justify-center content-start p-8 gap-y-2 justify-items-center text-center">
<div className="grid webkit-scrollbar:w-0 [scrollbar-width:none] border-r-[1px] overflow-y-scroll border-black w-80 max-h-screen h-screen justify-center content-start p-8 gap-y-2 justify-items-center text-center">
{props.children}
</div>
);

20
src/components/SVG.tsx Normal file
View File

@ -0,0 +1,20 @@
import Image from "next/image";
export type SVGProps = {
src: string;
alt: string;
className?: string;
};
export default function SVG(props: SVGProps): JSX.Element {
return (
<div className={props.className}>
<Image
src={props.src}
alt={props.src}
height={1000}
width={1000}
/>
</div>
);
}

View File

@ -3,6 +3,7 @@ import MainPanel from "components/Panels/MainPanel";
import "tailwind.css";
import "@fontsource/zen-maru-gothic/500.css";
import "@fontsource/vollkorn/700.css";
import "@fontsource/material-icons";
export type CustomAppProps = {
useSubPanel: boolean;

View File

@ -1,6 +1,7 @@
import SubPanel from "components/Panels/SubPanel";
import NavOption from "components/Panels/NavOption";
import NavOption from "components/PanelComponents/NavOption";
import { applyCustomAppProps } from "pages/_app";
import PanelHeader from "components/PanelComponents/PanelHeader";
applyCustomAppProps(Chronology, {
useSubPanel: true,
@ -11,13 +12,11 @@ export default function Chronology(): JSX.Element {
return (
<>
<SubPanel>
<h2>Chronology</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut vulputate
facilisis blandit. Aliquam blandit neque sem, ac pulvinar leo
ultricies sit amet.
</p>
<hr />
<PanelHeader
icon="watch_later"
title="Chronology"
description="Follow all events in chronological order. Here we can write more about this section of the website, whatever we like in fact."
/>
<NavOption
url="/chronology/timelines"

View File

@ -1,8 +1,6 @@
import { GetStaticProps } from "next";
import ContentPanel from "components/Panels/ContentPanel";
import SubPanel from "components/Panels/SubPanel";
import ReturnButton from "components/Panels/ReturnButton";
import NavOption from "components/Panels/NavOption";
import ChronologyYearComponent from "components/Chronology/ChronologyYearComponent";
import { applyCustomAppProps } from "pages/_app";
import {
@ -10,6 +8,8 @@ import {
GetErasQuery,
} from "graphql/operations-types";
import { getEras, getChronologyItems } from "graphql/operations";
import NavOption from "components/PanelComponents/NavOption";
import ReturnButton from "components/PanelComponents/ReturnButton";
interface Props {
chronologyItems: GetChronologyItemsQuery;

22
src/pages/hubs/index.tsx Normal file
View File

@ -0,0 +1,22 @@
import SubPanel from "components/Panels/SubPanel";
import { applyCustomAppProps } from "pages/_app";
import PanelHeader from "components/PanelComponents/PanelHeader";
applyCustomAppProps(Hubs, {
useSubPanel: true,
useContentPanel: false,
});
export default function Hubs(): JSX.Element {
return (
<>
<SubPanel>
<PanelHeader
icon="workspaces"
title="Hubs"
description="Explore all content of a specific game/series. Here we can write more about this section of the website, whatever we like in fact."
/>
</SubPanel>
</>
);
}

View File

@ -4,10 +4,7 @@ import Image from "next/image";
import Link from "next/link";
import { GetStaticPaths, GetStaticProps } from "next";
import { applyCustomAppProps } from "pages/_app";
import {
getLibraryItem,
getLibraryItemsSkeleton,
} from "graphql/operations";
import { getLibraryItem, getLibraryItemsSkeleton } from "graphql/operations";
import { GetLibraryItemQuery } from "graphql/operations-types";
import { getAssetURL } from "queries/helpers";
@ -28,14 +25,20 @@ export default function Library(props: Props): JSX.Element {
<ContentPanel>
<h1>{libraryItem.attributes.title}</h1>
<h2>{libraryItem.attributes.subtitle}</h2>
<Image
src={getAssetURL(
libraryItem.attributes.thumbnail.data.attributes.url
)}
alt={libraryItem.attributes.thumbnail.data.attributes.alternativeText}
width={libraryItem.attributes.thumbnail.data.attributes.width}
height={libraryItem.attributes.thumbnail.data.attributes.height}
/>
{libraryItem.attributes.thumbnail.data ? (
<Image
src={getAssetURL(
libraryItem.attributes.thumbnail.data.attributes.url
)}
alt={
libraryItem.attributes.thumbnail.data.attributes.alternativeText
}
width={libraryItem.attributes.thumbnail.data.attributes.width}
height={libraryItem.attributes.thumbnail.data.attributes.height}
/>
) : (
""
)}
{libraryItem.attributes.subitems.data.map((subitem) => (
<Link
@ -90,7 +93,7 @@ export const getStaticPaths: GetStaticPaths = async () => {
paths,
fallback: false,
};
}
};
async function getAllSlugs() {
type Path = {

View File

@ -1,10 +1,13 @@
import { GetStaticProps } from "next";
import SubPanel from "components/Panels/SubPanel";
import ContentPanel, { ContentPanelWidthSizes } from "components/Panels/ContentPanel";
import ContentPanel, {
ContentPanelWidthSizes,
} from "components/Panels/ContentPanel";
import LibraryItemComponent from "components/Library/LibraryItemComponent";
import { applyCustomAppProps } from "pages/_app";
import { GetLibraryItemsPreviewQuery } from "graphql/operations-types";
import { getLibraryItemsPreview } from "graphql/operations";
import PanelHeader from "components/PanelComponents/PanelHeader";
type Props = {
libraryItems: GetLibraryItemsPreviewQuery;
@ -20,20 +23,19 @@ export default function Library(props: Props): JSX.Element {
return (
<>
<SubPanel>
<h2>Library</h2>
<p>
A comprehensive list of all Yokoverse&rsquo;s side materials (books,
novellas, artbooks, stage plays, manga, drama CDs, and comics). For
each, we provide photos and/or scans of the content, information about
what it is, when and how it was released, size, initial price
</p>
<hr />
<PanelHeader
icon="library_books"
title="Library"
description="A comprehensive list of all Yokoverse&rsquo;s side materials (books, novellas, artbooks, stage plays, manga, drama CDs, and comics). For each, we provide photos and/or scans of the content, information about what it is, when and how it was released, size, initial price…"
/>
</SubPanel>
<ContentPanel width={ContentPanelWidthSizes.large}>
{props.libraryItems.libraryItems.data.map((item) => (
<LibraryItemComponent key={item.id} item={item} />
))}
<div className="grid gap-8 items-end grid-cols-[repeat(auto-fit,_minmax(15rem,1fr))]">
{props.libraryItems.libraryItems.data.map((item) => (
<LibraryItemComponent key={item.id} item={item} />
))}
</div>
</ContentPanel>
</>
);

View File

@ -12,15 +12,17 @@
}
/* HORIZONTAL LINE */
hr {
height: 0;
width: 100%;
border: none;
border-top: 0.3rem dotted black;
border-top: 0.3rem dotted theme("colors.black");;
margin: 2rem;
}
/* MATERIAL ICONS */
/* BUTTONS */
button {
@ -82,7 +84,6 @@
*::selection {
background-color: theme("colors.dark");
color: theme("colors.light");
border-radius: 1em;
}
*:target {
@ -102,6 +103,4 @@
border-radius: 100vmax; /* roundness of the scroll thumb */
border: 3px solid theme("colors.light"); /* creates padding around scroll thumb */
}
}
}

View File

@ -1,23 +1,48 @@
const plugin = require('tailwindcss/plugin');
const plugin = require("tailwindcss/plugin");
module.exports = {
content: ["./src/**/*.{tsx,ts}"],
theme: {
colors: {
light: "#ffedd8",
mid: "#e6ccb2",
mid: "#f0d1b3",
dark: "#9c6644",
black: "#1B1811",
},
},
plugins: [
require("@tailwindcss/typography"),
plugin(function({ addVariant, e }) {
addVariant('webkit-scrollbar', ({ modifySelectors, separator }) => {
plugin(function ({ addVariant, e }) {
addVariant("webkit-scrollbar", ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `.${e(`webkit-scrollbar${separator}${className}`)}::-webkit-scrollbar`
})
})
})
return `.${e(
`webkit-scrollbar${separator}${className}`
)}::-webkit-scrollbar`;
});
});
}),
// Colorization thanks to https://codepen.io/sosuke/pen/Pjoqqp
plugin(function ({ addUtilities }) {
addUtilities({
".colorize-light": {
filter:
"brightness(0) saturate(100%) invert(98%) sepia(3%) saturate(5426%) hue-rotate(303deg) brightness(108%) contrast(100%)",
},
".colorize-mid": {
filter:
"brightness(0) saturate(100%) invert(89%) sepia(16%) saturate(829%) hue-rotate(322deg) brightness(103%) contrast(88%)",
},
".colorize-dark": {
filter:
"brightness(0) saturate(100%) invert(43%) sepia(5%) saturate(4120%) hue-rotate(339deg) brightness(98%) contrast(90%)",
},
".colorize-black": {
filter:
"brightness(0) saturate(100%) invert(7%) sepia(13%) saturate(1156%) hue-rotate(4deg) brightness(103%) contrast(95%)",
},
});
}),
],
};