www/src/pages/[...locale]/release-notes/index.astro
2025-05-28 13:50:37 +12:00

139 lines
4.6 KiB
Text

---
import { Modal, ModalBody, ModalHeader } from 'free-astro-components'
import Button from '~/components/Button.astro'
import Description from '~/components/Description.astro'
import ReleaseNoteItem from '~/components/ReleaseNoteItem.astro'
import ArrowUpIcon from '~/icons/ArrowUp.astro'
import Layout from '~/layouts/Layout.astro'
import { releaseNotes as releaseNotesData, releaseNotesTwilight } from '~/release-notes'
import { getLocale, getUI } from '~/utils/i18n'
export { getStaticPaths } from '~/utils/i18n'
const locale = getLocale(Astro)
const {
routes: { releaseNotes },
layout,
} = getUI(locale)
---
<Layout title={layout.releaseNotes.title}>
<main
class="container flex h-full min-h-[1000px] flex-1 flex-col items-center justify-center py-4"
>
<div id="release-notes" class="py-42 flex min-h-screen w-full flex-col justify-center gap-8">
<Description class="mt-48 text-6xl font-bold">Changelog</Description>
<p
class="text-base opacity-55"
set:html={releaseNotes.topSection.description.replaceAll(
'{latestVersion}',
releaseNotesData[0].version
)}
/>
<div class="mt-8 flex w-fit flex-col gap-4 sm:mr-0 sm:flex-row sm:items-center">
<Button class="flex" isPrimary href="/donate">
{releaseNotes.list.support}
</Button>
<Button id="navigate-to-version" href="#" class="flex">
{releaseNotes.list.navigateToVersion}
</Button>
</div>
{
releaseNotesTwilight.features.length || releaseNotesTwilight.fixes.length ? (
<ReleaseNoteItem {...releaseNotesTwilight} isTwilight />
) : null
}
{releaseNotesData.map(notes => <ReleaseNoteItem {...notes} />)}
</div>
</main>
<Button href="#" id="scroll-top" isPrimary class="fixed bottom-8 right-8">
<p class="hidden items-center gap-2 sm:flex">
{releaseNotes.backToTop}
<ArrowUpIcon aria-hidden="true" class="size-4" />
</p>
<ArrowUpIcon aria-label="Back to the top" class="size-4 sm:hidden" />
</Button>
</Layout>
<Modal id="version-modal" class="m-auto border border-[--zen-dark] !bg-paper">
<ModalHeader class="border-b border-[--zen-dark]">
<p class="text-4xl font-bold text-dark">{releaseNotes.chooseVersion}</p>
</ModalHeader>
<ModalBody>
<div id="version-list" class="flex flex-col gap-2 text-xl text-dark">
{
releaseNotesData.map(note => (
<button
aria-label={`Navigate to version ${note.version}`}
class="w-full text-left transition-colors duration-150 hover:text-coral"
data-version={note.version}
>
{note.version}
</button>
))
}
</div>
</ModalBody>
</Modal>
<script>
import { closeModal, openModal } from 'free-astro-components'
const scrollTopButton = document.getElementById('scroll-top')
const versionButton = document.getElementById('navigate-to-version')
const container = document.getElementById('release-notes')
const modal = document.getElementById('version-modal')
const versionList = document.getElementById('version-list')
const toggleScrollButton = () => {
if (!scrollTopButton || !versionButton) return
const descriptionPosition = versionButton.getBoundingClientRect().bottom
if (descriptionPosition < 0) {
scrollTopButton.classList.remove('hidden')
scrollTopButton.classList.add('block')
} else {
scrollTopButton.classList.remove('block')
scrollTopButton.classList.add('hidden')
}
}
const navigateToVersion = (e: MouseEvent) => {
const target = e.target as HTMLElement
if (!container || !target?.closest('[data-version]')) return
const version = target.getAttribute('data-version')
if (!version) return
window.location.hash = version
const versionDetails = document.getElementById(version)?.getElementsByTagName('details')
if (versionDetails && versionDetails.length > 0) {
Array.from(versionDetails).forEach(accordion => {
accordion.setAttribute('open', '')
})
}
closeModal(modal)
}
const openVersionModal = () => {
if (!modal) return
openModal(modal)
}
window.addEventListener('scroll', toggleScrollButton)
versionButton?.addEventListener('click', openVersionModal)
versionList?.addEventListener('click', navigateToVersion)
document.addEventListener('keydown', e => {
if (e.key === 'Escape' && modal?.hasAttribute('open')) {
closeModal(modal)
// Remove scroll lock if present
document.body.style.overflow = ''
}
})
</script>
<style is:global>
#version-modal > * {
font-family: 'Bricolage Grotesque', sans-serif !important;
}
</style>