feat/generator: add tags navigation

This commit is contained in:
Kentai Radiquum 2025-02-21 23:59:22 +05:00
parent c275a6fa63
commit 1ec05d89e3
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
8 changed files with 202 additions and 178 deletions

View file

@ -8,6 +8,7 @@ import exec from "child_process";
import Base from "./templates/Base";
import Header from "./templates/Header";
import YearPhotos from "./templates/YearPhotos";
import Tags from "./templates/Tags";
const log = new Log();
@ -123,6 +124,7 @@ Object.keys(items).forEach((year) => {
const html = renderToString(
<Base isDev={ENVIRONMENT == "dev"}>
<Header />
<Tags tags={tags} />
<div className="container mx-auto p-4 flex flex-col gap-4">
{Object.keys(items).sort().reverse().map((year) => (
<YearPhotos

View file

@ -15,6 +15,7 @@
"picocolors": "^1.1.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-scrollbar": "^4.0.0",
"tailwindcss": "^4.0.7",
"ws": "^8.18.0",
},
@ -167,6 +168,8 @@
"@types/node": ["@types/node@22.13.4", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg=="],
"@types/prismjs": ["@types/prismjs@1.26.5", "", {}, "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ=="],
"@types/qs": ["@types/qs@6.9.18", "", {}, "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA=="],
"@types/range-parser": ["@types/range-parser@1.2.7", "", {}, "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="],
@ -225,6 +228,8 @@
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
@ -475,6 +480,8 @@
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"prism-react-renderer": ["prism-react-renderer@2.4.1", "", { "dependencies": { "@types/prismjs": "^1.26.0", "clsx": "^2.0.0" }, "peerDependencies": { "react": ">=16.0.0" } }, "sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig=="],
"proto3-json-serializer": ["proto3-json-serializer@2.0.2", "", { "dependencies": { "protobufjs": "^7.2.5" } }, "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ=="],
"protobufjs": ["protobufjs@7.4.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw=="],
@ -539,6 +546,8 @@
"stubs": ["stubs@3.0.0", "", {}, "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw=="],
"tailwind-scrollbar": ["tailwind-scrollbar@4.0.0", "", { "dependencies": { "prism-react-renderer": "^2.4.1" }, "peerDependencies": { "tailwindcss": "4.x" } }, "sha512-elqx9m09VHY8gkrMiyimFO09JlS3AyLFXT0eaLaWPi7ImwHlbZj1ce/AxSis2LtR+ewBGEyUV7URNEMcjP1Z2w=="],
"tailwindcss": ["tailwindcss@4.0.7", "", {}, "sha512-yH5bPPyapavo7L+547h3c4jcBXcrKwybQRjwdEIVAd9iXRvy/3T1CC6XSQEgZtRySjKfqvo3Cc0ZF1DTheuIdA=="],
"tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="],

View file

@ -20,6 +20,7 @@
"picocolors": "^1.1.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-scrollbar": "^4.0.0",
"tailwindcss": "^4.0.7",
"ws": "^8.18.0"
}

View file

@ -521,11 +521,8 @@
.collapse {
visibility: collapse;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
.invisible {
visibility: hidden;
}
.relative {
position: relative;
@ -533,12 +530,6 @@
.static {
position: static;
}
.\[grid-column\:span_2\] {
grid-column: span 2;
}
.\[grid-row\:span_2\] {
grid-row: span 2;
}
.container {
width: 100%;
@media (width >= 40rem) {
@ -563,6 +554,27 @@
.mb-4 {
margin-bottom: calc(var(--spacing) * 4);
}
.scrollbar-thin {
&::-webkit-scrollbar-track {
background-color: var(--scrollbar-track);
border-radius: var(--scrollbar-track-radius);
}
&::-webkit-scrollbar-thumb {
background-color: var(--scrollbar-thumb);
border-radius: var(--scrollbar-thumb-radius);
}
&::-webkit-scrollbar-corner {
background-color: var(--scrollbar-corner);
border-radius: var(--scrollbar-corner-radius);
}
scrollbar-width: thin;
scrollbar-color: var(--scrollbar-thumb, initial) var(--scrollbar-track, initial);
&::-webkit-scrollbar {
display: block;
width: 8px;
height: 8px;
}
}
.block {
display: block;
}
@ -575,9 +587,6 @@
.hidden {
display: none;
}
.inline-block {
display: inline-block;
}
.inline-flex {
display: inline-flex;
}
@ -587,12 +596,6 @@
.table {
display: table;
}
.aspect-\[1\/2\] {
aspect-ratio: 1/2;
}
.aspect-\[2\/1\] {
aspect-ratio: 2/1;
}
.aspect-square {
aspect-ratio: 1 / 1;
}
@ -620,33 +623,9 @@
.grid-flow-row-dense {
grid-auto-flow: row dense;
}
.\[grid-template-columns\:repeat\(auto-fill\,minmax\(256px\,1fr\)\)\] {
grid-template-columns: repeat(auto-fill,minmax(256px,1fr));
}
.grid-cols-1 {
grid-template-columns: repeat(1, minmax(0, 1fr));
}
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid-cols-4 {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.grid-cols-5 {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
.grid-cols-6 {
grid-template-columns: repeat(6, minmax(0, 1fr));
}
.grid-cols-7 {
grid-template-columns: repeat(7, minmax(0, 1fr));
}
.grid-cols-8 {
grid-template-columns: repeat(8, minmax(0, 1fr));
}
.flex-col {
flex-direction: column;
}
@ -659,8 +638,11 @@
.gap-4 {
gap: calc(var(--spacing) * 4);
}
.gap-8 {
gap: calc(var(--spacing) * 8);
.overflow-x-auto {
overflow-x: auto;
}
.rounded-full {
border-radius: calc(infinity * 1px);
}
.rounded-lg {
border-radius: var(--radius-lg);
@ -682,16 +664,38 @@
.bg-\[\#FF478B\] {
background-color: #FF478B;
}
.bg-gray-600 {
background-color: var(--color-gray-600);
}
.bg-gray-800 {
background-color: var(--color-gray-800);
}
.object-cover {
object-fit: cover;
}
.p-4 {
padding: calc(var(--spacing) * 4);
}
.px-3 {
padding-inline: calc(var(--spacing) * 3);
}
.px-8 {
padding-inline: calc(var(--spacing) * 8);
}
.py-1 {
padding-block: calc(var(--spacing) * 1);
}
.py-2 {
padding-block: calc(var(--spacing) * 2);
}
.text-2xl {
font-size: var(--text-2xl);
line-height: var(--tw-leading, var(--text-2xl--line-height));
}
.text-sm {
font-size: var(--text-sm);
line-height: var(--tw-leading, var(--text-sm--line-height));
}
.font-bold {
--tw-font-weight: var(--font-weight-bold);
font-weight: var(--font-weight-bold);
@ -702,107 +706,34 @@
.underline {
text-decoration-line: underline;
}
.antialiased {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.outline {
outline-style: var(--tw-outline-style);
outline-width: 1px;
}
.blur {
--tw-blur: blur(8px);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
.grayscale {
--tw-grayscale: grayscale(100%);
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
.filter {
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
.backdrop-filter {
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
.scrollbar-thumb-gray-700 {
--scrollbar-thumb: oklch(0.373 0.034 259.733);
}
.transition {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
.ease-in {
--tw-ease: var(--ease-in);
transition-timing-function: var(--ease-in);
}
.ease-out {
--tw-ease: var(--ease-out);
transition-timing-function: var(--ease-out);
}
.sm\:\[grid-column\:span_2\] {
@media (width >= 40rem) {
grid-column: span 2;
}
}
.sm\:\[grid-template-columns\:repeat\(auto-fill\,minmax\(256px\,1fr\)\)\] {
@media (width >= 40rem) {
grid-template-columns: repeat(auto-fill,minmax(256px,1fr));
}
}
.md\:\[grid-column\:span_2\] {
@media (width >= 48rem) {
grid-column: span 2;
}
.scrollbar-track-gray-900 {
--scrollbar-track: oklch(0.21 0.034 264.665);
}
.lg\:\[grid-column\:span_2\] {
@media (width >= 64rem) {
grid-column: span 2;
}
}
.lg\:grid-cols-3 {
@media (width >= 64rem) {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
.lg\:grid-cols-4 {
@media (width >= 64rem) {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
}
.lg\:grid-cols-5 {
@media (width >= 64rem) {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
}
.xl\:\[grid-column\:span_2\] {
@media (width >= 80rem) {
grid-column: span 2;
}
}
.xl\:\[grid-template-columns\:repeat\(auto-fill\,minmax\(128px\,1fr\)\)\] {
@media (width >= 80rem) {
grid-template-columns: repeat(auto-fill,minmax(128px,1fr));
}
}
.xl\:\[grid-template-columns\:repeat\(auto-fill\,minmax\(200px\,1fr\)\)\] {
@media (width >= 80rem) {
grid-template-columns: repeat(auto-fill,minmax(200px,1fr));
}
}
.xl\:\[grid-template-columns\:repeat\(auto-fill\,minmax\(512px\,1fr\)\)\] {
@media (width >= 80rem) {
grid-template-columns: repeat(auto-fill,minmax(512px,1fr));
}
}
.xl\:grid-cols-7 {
@media (width >= 80rem) {
grid-template-columns: repeat(7, minmax(0, 1fr));
}
}
.xl\:grid-cols-8 {
@media (width >= 80rem) {
grid-template-columns: repeat(8, minmax(0, 1fr));
}
}
.xl\:text-3xl {
@media (width >= 80rem) {
font-size: var(--text-3xl);
@ -822,6 +753,12 @@
font-weight: 600;
font-style: normal;
}
@layer base {
* {
scrollbar-color: initial;
scrollbar-width: initial;
}
}
@keyframes spin {
to {
transform: rotate(360deg);
@ -927,43 +864,3 @@
syntax: "*";
inherits: false;
}
@property --tw-backdrop-blur {
syntax: "*";
inherits: false;
}
@property --tw-backdrop-brightness {
syntax: "*";
inherits: false;
}
@property --tw-backdrop-contrast {
syntax: "*";
inherits: false;
}
@property --tw-backdrop-grayscale {
syntax: "*";
inherits: false;
}
@property --tw-backdrop-hue-rotate {
syntax: "*";
inherits: false;
}
@property --tw-backdrop-invert {
syntax: "*";
inherits: false;
}
@property --tw-backdrop-opacity {
syntax: "*";
inherits: false;
}
@property --tw-backdrop-saturate {
syntax: "*";
inherits: false;
}
@property --tw-backdrop-sepia {
syntax: "*";
inherits: false;
}
@property --tw-ease {
syntax: "*";
inherits: false;
}

View file

@ -1,17 +1,103 @@
const url = new URL(window.location.href);
let tags = url.searchParams.get("tag") || "";
if (tags.length > 0) {
tags = tags.split(",");
} else {
tags = [];
}
let availableTags = [];
const galleries = document.querySelectorAll('[data-type="gallery"]');
let tagsButtons = document.querySelectorAll('[data-type="tag"]');
let allTagsButton = document.querySelector('[data-type="tag"][data-tag="all"]');
let Images = document.querySelectorAll('[data-type="image"]');
Images.forEach((item) => {
const imTags = item.dataset.tags.split(",") || [];
const foundTags = [];
for (let i = 0; i < imTags.length; i++) {
if (tags.includes(imTags[i]) || tags.length == 0) {
foundTags.push(imTags[i]);
}
}
if (foundTags.length == 0 || foundTags.length < tags.length) {
item.remove();
} else {
item.classList.remove("hidden");
for (let i = 0; i < imTags.length; i++) {
if (!availableTags.includes(imTags[i])) {
availableTags.push(imTags[i]);
}
}
}
});
allTagsButton.addEventListener("click", () => {
removeTags();
});
if (tags.length == 0) {
allTagsButton.classList.remove("bg-gray-800");
allTagsButton.classList.add("bg-gray-600");
}
tagsButtons.forEach((item) => {
if (item.dataset.tag != "all") {
item.addEventListener("click", () => {
toggleTag(item.dataset.tag);
});
}
if (tags.includes(item.dataset.tag)) {
item.classList.remove("bg-gray-800");
item.classList.add("bg-gray-600");
}
if (!availableTags.includes(item.dataset.tag) && item.dataset.tag != "all") {
item.remove();
} else {
item.classList.remove("hidden");
}
});
function removeTags() {
const url = new URL(window.location.href);
url.searchParams.delete("tag");
window.history.pushState({}, "", url);
window.location.reload();
}
function toggleTag(tag) {
if (tags.includes(tag)) {
tags = tags.filter((item) => item !== tag);
} else {
tags.push(tag);
}
tags = tags.join(",");
url.searchParams.set("tag", tags);
window.history.pushState({}, "", url);
window.location.reload();
}
galleries.forEach((item, idx) => {
lightGallery(item, {
plugins: [lgThumbnail, lgHash, lgShare, lgFullscreen, lgZoom],
speed: 500,
thumbnail: true,
download: true,
animateThumb: true,
zoomFromOrigin: false,
toggleThumb: false,
galleryId: Number(item.getAttribute('data-year')),
hash: true,
customSlideName: true,
mobileSettings: { controls: true, showCloseIcon: true, download: true }
});
if (item.children.length == 0) {
item.parentElement.remove();
} else {
item.parentElement.classList.remove("hidden");
lightGallery(item, {
plugins: [lgThumbnail, lgHash, lgShare, lgFullscreen, lgZoom],
speed: 500,
thumbnail: true,
download: true,
animateThumb: true,
zoomFromOrigin: false,
toggleThumb: false,
galleryId: Number(item.getAttribute("data-year")),
hash: true,
customSlideName: true,
mobileSettings: { controls: true, showCloseIcon: true, download: true },
});
}
});

View file

@ -1,4 +1,5 @@
@import "tailwindcss";
@plugin 'tailwind-scrollbar';
.inter-semibold {
font-family: "Inter", serif;

View file

@ -0,0 +1,26 @@
export default function Tags({ tags }: { tags: string[] }) {
return (
<div className="container mx-auto">
<div className="flex overflow-x-auto px-8 py-2 gap-2 scrollbar-thin scrollbar-corner-rounded-sm scrollbar-thumb-gray-700 scrollbar-track-gray-900">
<button
className="bg-gray-800 rounded-full px-3 py-1 text-sm"
key="all"
data-type="tag"
data-tag="all"
>
all
</button>
{tags.map((tag) => (
<button
className="bg-gray-800 rounded-full px-3 py-1 text-sm hidden"
key={tag}
data-type="tag"
data-tag={tag}
>
{tag}
</button>
))}
</div>
</div>
);
}

View file

@ -7,7 +7,7 @@ interface YearPhotosProps {
export default function YearPhotos({ year, images }: YearPhotosProps) {
return (
<div>
<div className="hidden">
<h2 className="text-2xl font-bold xl:text-3xl 2xl:text-4xl inter-semibold mb-4">
{year}
</h2>
@ -23,7 +23,7 @@ export default function YearPhotos({ year, images }: YearPhotosProps) {
return (
<a
href={image.image}
className={`w-full h-full ${
className={`w-full h-full hidden ${
aspectRatio < 0.95 ? "" : aspectRatio > 1.05 ? "lg:[grid-column:span_2]" : "aspect-square"
}`}
key={`${year}-${image.id}`}
@ -34,6 +34,8 @@ export default function YearPhotos({ year, images }: YearPhotosProps) {
(max-width: 2000px) 1440px,
2001px"
data-download-url={image.image}
data-type="image"
data-tags={image.tags.join(",")}
>
<img
src={image.thumbnail[512]}