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
<Gallery>Where the stations stand
Orchards, greenhouses and open fields, in the season they were photographed.

In the orchard

Under glass

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
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| title | string | yes | ||
| image | string | |||
| description | string | |||
| href | string | |||
| linkText | string | |||
| photo | boolean | false | 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). |
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.