diff --git a/src/app/java/changelog/layout.tsx b/src/app/java/changelog/layout.tsx index 430bbb5..230db52 100644 --- a/src/app/java/changelog/layout.tsx +++ b/src/app/java/changelog/layout.tsx @@ -3,7 +3,6 @@ import { getVersionManifest, type VersionManifest, } from "~/server/java/versions"; -import VersionLink from "~/components/java/version-link"; import { Alert, AlertDescription, AlertTitle } from "~/components/ui/alert"; import { ActivityLogIcon, @@ -19,6 +18,9 @@ import { SheetTrigger, } from "~/components/ui/sheet"; import { Button } from "~/components/ui/button"; +import ReleaseVersionLinkSet from "~/components/java/release-version-link-set"; +import "~/styles/game-versions.css"; +import { type ReleaseVersionEntry } from "~/components/java/version-link"; export default async function ChangelogLayout({ children, @@ -64,12 +66,9 @@ export default async function ChangelogLayout({ - +
+ +
@@ -79,12 +78,10 @@ export default async function ChangelogLayout({ className="h-page rounded-md border" viewportClassName="overscroll-contain" > - +

Versions

+
+ +
{children}
@@ -95,32 +92,44 @@ export default async function ChangelogLayout({ function VersionLinks({ versions, - className = "", + type, + className = "" }: { versions: VersionManifest["entries"]; + type: string; className?: string; }) { - return ( - <> -
  • - -
  • - {versions.map((v) => { - return ( -
  • - -
  • - ); - })} - - ); + const orderedVersions: ReleaseVersionEntry[] = [ + { + name: "Latest", + url: "", + title: versions[0].title, + description: versions[0].shortText, + image: versions[0].image, + nonReleaseVersions: [], + isLatest: true + } + ]; + for (const version of versions) { + if (version.type === "release") { + orderedVersions.push({ + name: version.version, + url: version.version, + title: version.title, + description: version.shortText, + image: version.image, + nonReleaseVersions: [], + isLatest: false + }); + continue; + } + orderedVersions.at(-1)!.nonReleaseVersions.push({ + name: version.version, + url: version.version, + title: version.title, + description: version.shortText, + image: version.image + }); + } + return orderedVersions.map(version => ); } diff --git a/src/components/java/release-version-link-set.tsx b/src/components/java/release-version-link-set.tsx new file mode 100644 index 0000000..5c25106 --- /dev/null +++ b/src/components/java/release-version-link-set.tsx @@ -0,0 +1,53 @@ +"use client"; + +import { usePathname } from "next/navigation"; +import VersionLink, { type ReleaseVersionEntry } from "./version-link"; + +export default function ReleaseVersionLinkSet({ + release, + type, + className, +}: { + release: ReleaseVersionEntry; + type: string; + className: string; +}) { + const selectedVersion = useVersion(); + return ( +
    + + { + release.nonReleaseVersions.length > 0 && <> + + +
    + {release.nonReleaseVersions.map(nonReleaseVersion => )} +
    + + } +
    + ); +} + +function useVersion(): string { + const prefix = "java/changelog/"; + const pathname = usePathname(); + if (pathname === prefix) { + return ""; + } + const probableVersion = pathname.substring(prefix.length); + if (probableVersion.startsWith("/")) { + return probableVersion.substring(1); + } + return probableVersion; +} + +function containsVersion(release: ReleaseVersionEntry, version: string): boolean { + if (release.isLatest && version === "") { + return true; + } + if (release.name === version) { + return true; + } + return release.nonReleaseVersions.some(nonRelease => nonRelease.name === version); +} diff --git a/src/components/java/version-link.tsx b/src/components/java/version-link.tsx index eb38c55..24f0e95 100644 --- a/src/components/java/version-link.tsx +++ b/src/components/java/version-link.tsx @@ -8,41 +8,34 @@ import { } from "~/components/ui/hover-card"; import Link from "next/link"; import { cn } from "~/lib/utils"; -import { usePathname } from "next/navigation"; import { BASE_ASSET_URL, - type VersionManifestEntry, } from "~/server/java/versions"; import type { ClassValue } from "clsx"; export default function VersionLink({ - versionName, - versionLink = versionName, - data: { shortText, title, image }, + version, className = "px-3 py-1", + selected, }: { - versionName: string; - versionLink?: string; - data: VersionManifestEntry; + version: VersionEntry; className?: ClassValue; + selected: boolean; }) { - const url = `/java/changelog/${versionLink}`; - const pathname = usePathname(); - const selected = url === pathname || url === pathname + "/"; - + const url = `/java/changelog/${version.url}`; return ( - {versionName} + {version.name} @@ -53,13 +46,26 @@ export default function VersionLink({
    -

    {title}

    -

    {shortText}…

    +

    {version.title}

    +

    {version.description}…

    ); } + +export interface VersionEntry { + name: string; + url: string; + title: string; + description: string; + image: { title: string; url: string; }; +} + +export interface ReleaseVersionEntry extends VersionEntry { + nonReleaseVersions: VersionEntry[]; + isLatest: boolean; +} diff --git a/src/styles/arrow_down.svg b/src/styles/arrow_down.svg new file mode 100644 index 0000000..349e67e --- /dev/null +++ b/src/styles/arrow_down.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/styles/arrow_up.svg b/src/styles/arrow_up.svg new file mode 100644 index 0000000..f58a950 --- /dev/null +++ b/src/styles/arrow_up.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/styles/game-versions.css b/src/styles/game-versions.css new file mode 100644 index 0000000..c1d72ef --- /dev/null +++ b/src/styles/game-versions.css @@ -0,0 +1,47 @@ +.versions { + display: flex; + flex-direction: column; + margin-left: 0.5em; + user-select: none; +} + +.versions input { + display: none; +} + +.major-version { + display: grid; + gap: 0 0.5em; + grid-template-rows: auto 1fr; + grid-template-columns: 1em 1fr; + grid-template-areas: + "button title" + ". body"; +} + +.major-version > .version-label { + grid-area: title; + font-weight: bold; +} + +.major-version-button { + aspect-ratio: 1 / 1; + align-self: center; + grid-area: button; + mask-image: url("arrow_down.svg"); + background-color: rgb(var(--ctp-subtext1)); +} + +input:checked + .major-version-button { + mask-image: url("arrow_up.svg"); +} + +.major-version-body { + grid-area: body; + display: none; +} + +input:checked ~ .major-version-body { + display: flex; + flex-direction: column; +}