GalleryItem

apps/www/src/sections/GalleryItem.astro · 47 lines · group Gallery & files

GalleryItem — one item of <Gallery>: a picture with a caption, or a file (`href` + `linkText`, no image) rendered as an attachment row.

In the fleet

Used on 1 site built with this engine.

Samples 1

sampleshown inside <Gallery>

Where the stations stand

Orchards, greenhouses and open fields, in the season they were photographed.

  • In the orchard

    In the orchard

  • Under glass

    Under glass

  • Open field

    Open field

MDX of this sample
<Gallery title="Where the stations stand" description="Orchards, greenhouses and open fields, in the season they were photographed.">
  <GalleryItem title="In the orchard" image="photo-01.jpg" photo />
  <GalleryItem title="Under glass" image="photo-02.jpg" photo />
  <GalleryItem title="Open field" image="photo-03.jpg" photo />
</Gallery>

Props

NameTypeRequiredDefaultDescription
titlestringyes
imagestring
descriptionstring
hrefstring
linkTextstring
photobooleanfalsea photo fills the card at its own proportions; icons and product shots sit in a fixed box so a row of them lines up. Never crop a photo to a fixed height — that is what turns portrait shots into letterbox slices (fixed once for ImageCardItem, 2026-08-22).

Source apps/www/src/sections/GalleryItem.astro @ gitt.one

---
/**
 * GalleryItem — one item of <Gallery>: a picture with a caption, or a file
 * (`href` + `linkText`, no image) rendered as an attachment row.
 */
import { Image } from 'astro:assets';
import PaperClip from 'astro-heroicons/outline/PaperClip.astro';
import { resolveImage } from '../lib/images';

interface Props {
  title: string;
  image?: string;
  description?: string;
  href?: string;
  linkText?: string;
  /** a photo fills the card at its own proportions; icons and product shots
   *  sit in a fixed box so a row of them lines up. Never crop a photo to a
   *  fixed height — that is what turns portrait shots into
   *  letterbox slices (fixed once for ImageCardItem, 2026-08-22). */
  photo?: boolean;
}
const { title, image, description, href, linkText, photo = false } = Astro.props;
const img = image ? await resolveImage(image) : undefined;
---

{img ? (
  <li class="text-center">
    {href ? (
      <a href={href} class="group block">
        <Image src={img} alt={title} widths={[400, 800]} class:list={['mx-auto w-full rounded-lg', photo ? 'h-auto' : 'h-48 object-contain']} />
        <p class="mt-4 text-lg font-medium text-gray-900 group-hover:text-primary-700">{title}</p>
      </a>
    ) : (
      <>
        <Image src={img} alt={title} widths={[400, 800]} class:list={['mx-auto w-full rounded-lg', photo ? 'h-auto' : 'h-48 object-contain']} />
        <p class="mt-4 text-lg font-medium text-gray-900">{title}</p>
      </>
    )}
    {description && <p class="mt-2 text-base text-gray-500">{description}</p>}
  </li>
) : (
  <li class="flex items-center justify-between rounded-md border border-gray-200 py-3 pl-3 pr-4 text-sm text-gray-900">
    <span class="flex w-0 flex-1 items-center"><PaperClip class="h-5 w-5 flex-shrink-0 text-gray-400" aria-hidden="true" /><span class="ml-2 w-0 flex-1 truncate">{title}</span></span>
    {href && <a href={href} download class="ml-4 flex-shrink-0 font-medium text-primary-600 hover:text-primary-500">{linkText ?? 'Download'}</a>}
  </li>
)}

Source links point to engine-astro@38c294d9. Samples are demo content: the components are the real ones, the copy and the pictures are made up.