Skip to content

feat(gallery): photo credits on galleries and carousels - #154

Closed
RonanHevenor wants to merge 1 commit into
mainfrom
wip/new-task
Closed

RonanHevenor wants to merge 1 commit into
mainfrom
wip/new-task

Conversation

@RonanHevenor

@RonanHevenor RonanHevenor commented Sep 9, 2026 •

Copy link
Copy Markdown
Member

What

Photo galleries and carousels carried no credit at all, and the caption field their blocks already declared was never rendered. Both blocks now take a credit relationship, mirroring the one the inline upload node has had since 20260322 — "Overrides the photographer set on the media record."

Credit resolves per photo in the same order the upload node uses: an explicit block credit → the media record's photographer → its writeInPhotographer free text.

credit is hasMany, so a co-shot frame credits everyone at once on one line — "A, B, C/The Polytechnic" — with a single suffix, each staff name linking to its profile. Write-ins render bare, since they aren't staff.

The two blocks diverge

block treatment
carousel caption + credit beneath the frame, muted — styling unchanged
photo gallery credit only, laid over the photo — no captions

Galleries no longer take a caption at all; the field is gone from the block, so it can't be entered.

Important

Captions already stored in published gallery blocks stop rendering, and Payload drops them the next time an editor saves that article. PhotoGallery strips caption rather than merely ignoring it, so text saved before the field was removed can't resurface, and the sampled area matches exactly what's drawn.

Placing a credit on a photograph

Because a gallery credit sits on the image, lib/imageLuminance.ts decides both where it goes and what colour it is from the pixels it will actually cover.

It reconstructs the caption's own box — the same 12px/18px/px-4 pt-2 pb-3 geometry the component renders with, wrapped to an estimated line count — in each bottom corner, and samples only those two rectangles.

  • Corner: lower luminance standard deviation wins. Text over an even area stays legible where the same text over high-contrast detail does not, whatever colour it is. Left takes ties by a 3-point margin, so near-identical photos in one gallery don't flip corners.
  • Colour: the winning corner's mean luminance picks white or black, with a matching text-shadow to hold an edge.

Measured on seed images at 3 columns:

photo left dev right dev wins text
swe-day 10.3 33.1 left white
winter-carnival 34.4 35.6 left (margin) white
bsa-fashion 45.9 26.6 right white
playhouse 48.8 27.3 right black (mean 212)
freakout-fans 53.5 48.0 right white

Sampling the text's own rectangle rather than the whole image changes the answer in practice: playhouse averages 129 across the frame but 212 in the corner the credit lands in, so it's the one that reads black.

Column width is viewport-relative, so sampling assumes a 1280px reference. Narrower viewports wrap to more lines and cover more of the photo, which only ever makes the measured rectangle a subset of the real one. Legacy-archive rows have no local file to sample and fall back to white, bottom-left.

Migration

None, and that was verified rather than assumed.

Lexical block fields serialize into the existing jsonb richText columns — there are no photo_gallery or carousel tables and no new column. Confirmed by applying migrations/ to a fresh database with PAYLOAD_DISABLE_PUSH=1 and NODE_ENV=production, then writing and reading back a multi-credit gallery. pnpm generate:types is likewise a no-op, since lexical blocks don't surface in payload-types.ts.

Scope

Both block definitions are mirrored in payload.config.ts and collections/LiveArticles.ts, so live-article updates get the same treatment — they already render through the same SerializeLexical path.

Checks

pnpm typecheck clean. pnpm lint 0 errors (53 pre-existing migrations/ warnings, unchanged).

🤖 Generated with Claude Code

Empty placeholder commit so a pull request can be opened before any code
exists. Will be replaced or built on as the actual change lands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@RonanHevenor
RonanHevenor deleted the wip/new-task branch September 9, 2026 20:02
@RonanHevenor RonanHevenor changed the title WIP: placeholder feat(gallery): photo credits on galleries and carousels Sep 9, 2026
@RonanHevenor

Copy link
Copy Markdown
Member Author

Superseded by #155 — this PR was auto-closed when its head branch wip/new-task was renamed to feat/gallery-photo-credits. Same work, same commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant