feat(gallery): grid title, subtle download icon, full i18n
Deploy / verify (push) Successful in 38s
Deploy / deploy (push) Successful in 59s

- Render block.title as <h3> above the grid when set; the carousel
  variant is unchanged.
- Download CTA in the modal shrunk to a 9×9 icon-only button with
  text-white/80 hover-tint instead of the dark green link colour the
  app's `main a` rule was forcing in. Adds `no-underline` so the
  global underline doesn't sneak back in.
- All previously hardcoded German strings (Download, Schließen,
  modal aria, open aria) now go through translations.ts → CMS
  translation_bundle. Cms_content app.json5 ships the matching keys.

Open follow-up: per-image title/alt/caption is empty on the existing
windwiderstand mediathek gallery → editor needs to fill those if
hover labels are wanted.
This commit is contained in:
Peter Meier
2026-04-25 10:44:30 +02:00
parent 9946061105
commit 998fba8904
2 changed files with 14 additions and 7 deletions
@@ -167,6 +167,9 @@
{#if withUrl.length === 0} {#if withUrl.length === 0}
<p class="text-sm text-stein-500">{t(T.image_gallery_empty)}</p> <p class="text-sm text-stein-500">{t(T.image_gallery_empty)}</p>
{:else if block.variant === "grid"} {:else if block.variant === "grid"}
{#if block.title}
<h3 class="text-lg font-semibold text-stein-900 mb-3">{block.title}</h3>
{/if}
<ul class="not-prose grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4"> <ul class="not-prose grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-4">
{#each withUrl as item, i} {#each withUrl as item, i}
{@const label = imageLabel(item.img)} {@const label = imageLabel(item.img)}
@@ -175,7 +178,7 @@
type="button" type="button"
class="group relative block w-full aspect-square overflow-hidden rounded-sm bg-stein-100 cursor-zoom-in focus:outline-none focus:ring-2 focus:ring-wald-500" class="group relative block w-full aspect-square overflow-hidden rounded-sm bg-stein-100 cursor-zoom-in focus:outline-none focus:ring-2 focus:ring-wald-500"
onclick={() => openModal(i)} onclick={() => openModal(i)}
aria-label={label || `Bild ${i + 1}`} aria-label={label || t(T.image_gallery_open_aria)}
> >
<RustyImage <RustyImage
src={item.url} src={item.url}
@@ -207,7 +210,7 @@
class="fixed inset-0 z-[100] flex items-center justify-center bg-black/85 p-4" class="fixed inset-0 z-[100] flex items-center justify-center bg-black/85 p-4"
role="dialog" role="dialog"
aria-modal="true" aria-modal="true"
aria-label={curLabel || "Bild-Vorschau"} aria-label={curLabel || t(T.image_gallery_modal_aria)}
onclick={closeModal} onclick={closeModal}
transition:fade={{ duration: 150 }} transition:fade={{ duration: 150 }}
> >
@@ -216,7 +219,6 @@
onclick={(e) => e.stopPropagation()} onclick={(e) => e.stopPropagation()}
role="presentation" role="presentation"
> >
<!-- eslint-disable-next-line @typescript-eslint/no-unused-expressions -->
<img <img
src={cur.url} src={cur.url}
alt={curLabel} alt={curLabel}
@@ -235,10 +237,11 @@
<a <a
href={cur.url} href={cur.url}
download={downloadFilename(cur.url)} download={downloadFilename(cur.url)}
class="inline-flex items-center gap-1.5 rounded-md bg-white/10 px-3 py-1.5 text-sm font-medium text-white hover:bg-white/20 focus:outline-none focus:ring-2 focus:ring-white/50" class="no-underline inline-flex h-9 w-9 items-center justify-center rounded-full text-white/80 hover:text-white hover:bg-white/10 focus:outline-none focus:ring-2 focus:ring-white/40"
title={t(T.image_gallery_download)}
aria-label={t(T.image_gallery_download)}
> >
<Icon icon="mdi:download-outline" class="text-base" aria-hidden="true" /> <Icon icon="mdi:download-outline" class="text-xl" aria-hidden="true" />
Download
</a> </a>
</div> </div>
{#if withUrl.length > 1} {#if withUrl.length > 1}
@@ -263,7 +266,7 @@
type="button" type="button"
class="absolute -top-2 -right-2 inline-flex h-8 w-8 items-center justify-center rounded-full bg-white text-stein-900 shadow-md hover:bg-stein-100 focus:outline-none focus:ring-2 focus:ring-white/50" class="absolute -top-2 -right-2 inline-flex h-8 w-8 items-center justify-center rounded-full bg-white text-stein-900 shadow-md hover:bg-stein-100 focus:outline-none focus:ring-2 focus:ring-white/50"
onclick={closeModal} onclick={closeModal}
aria-label="Schließen" aria-label={t(T.image_gallery_close)}
> >
<Icon icon="mdi:close" class="text-lg" aria-hidden="true" /> <Icon icon="mdi:close" class="text-lg" aria-hidden="true" />
</button> </button>
+4
View File
@@ -94,6 +94,10 @@ const TRANSLATION_KEYS = [
"image_gallery_position_aria", "image_gallery_position_aria",
"image_gallery_slide_aria", "image_gallery_slide_aria",
"image_gallery_empty", "image_gallery_empty",
"image_gallery_download",
"image_gallery_close",
"image_gallery_open_aria",
"image_gallery_modal_aria",
"youtube_missing", "youtube_missing",
"youtube_title_fallback", "youtube_title_fallback",
"calendar_prev_month", "calendar_prev_month",