Skip to content

Add experimental composer toggle for image grid/carousel layout#11067

Draft
mozzius wants to merge 5 commits into
mainfrom
claude/composer-image-display-toggle-8e920d
Draft

Add experimental composer toggle for image grid/carousel layout#11067
mozzius wants to merge 5 commits into
mainfrom
claude/composer-image-display-toggle-8e920d

Conversation

@mozzius

@mozzius mozzius commented Jul 5, 2026

Copy link
Copy Markdown
Member

Adds a button to toggle between grid/carousel display for 2-4 images. Has an introductory tooltip, and persists to local storage.

Simulator.Screen.Recording.-.iPhone.17.-.2026-07-06.at.17.32.54.mov

It's behind a composer:image_layout_toggle:enable flag

### Test plan

  • Test posting a carousel and a grid posts
  • Confirm button only shows when 2-4 images are selected

claude added 2 commits July 5, 2026 10:11
Behind the new `composer:image_layout_toggle:enable` feature gate, show
a pill button in the composer toolbar (next to the labels button) when a
post has 2-4 images. The button switches the draft between the legacy
`app.bsky.embed.images` shape (grid) and the newer
`app.bsky.embed.gallery` shape (carousel, previously only used for 5+
images). Gallery embeds now always render with the carousel layout so
the choice is reflected for viewers.

The button is wrapped in a one-time tooltip nudge, following the same
pattern as the threadgate button, and emits a
`composer:imageLayout:toggle` metric.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SvDXhHEBCjAfokEFK8pHt8
The embed type now decides the image layout everywhere: gallery embeds
render as the carousel, legacy `app.bsky.embed.images` embeds render as
the grid. This also means legacy image embeds never need the gallery
offset styles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SvDXhHEBCjAfokEFK8pHt8
@claude

claude Bot commented Jul 5, 2026

Copy link
Copy Markdown

Claude finished @mozzius's task in 3m 9s —— View job


PR Review

  • Read review guidance and CLAUDE.md
  • Review the diff (origin/main...HEAD)
  • Examine composer state, toggle button, embed rendering, publish + draft paths
  • Post review

Reviewed the composer state machine, the toggle button, the two viewer render paths (ImageEmbed + PostFeed), the offset helper, and the publish + draft serialization paths. The refactor from a count/gate-based layout decision to a pure embed-type decision is clean and kept consistent across both render sites (ImageEmbed.tsx:45 and PostFeed.tsx:974), and the offset helper (maybeApplyGalleryOffsetStyles.ts) now matches that same rule. One non-blocking finding.

Non-blocking: carousel choice is lost on draft save/restore

canToggleImageLayout gates the toggle to 2-4 images, and picking "carousel" moves those images into gallery media. But the layout choice for 2-4 images is encoded only in the media type (images vs gallery), and the draft round-trip discards that distinction:

  • On save, both images and gallery media are serialized to the same embedGallery shape — drafts/state/api.ts:117-124.
  • On restore, the variant is re-derived purely from image count — drafts/state/api.ts:532-536: restoredImages.length <= LEGACY_IMAGES_EMBED_MAX ? {type: 'images'} : {type: 'gallery'}.

Scenario: a user with the gate on composes 3 images, switches to carousel, saves the draft, then reopens it. The draft restores as type: 'images' (grid), silently reverting their choice. Since the whole feature is about letting users make and keep that choice, losing it on a draft round-trip is a real UX regression within the experiment. It's scoped to gated users composing 2-4 images and using drafts, so non-blocking — but worth deciding whether to persist the layout in the draft schema. Fix this →

Things I checked that are fine

  • No lingering references to the removed PostGalleryEmbedEnable / post_gallery_embed gate anywhere in the tree.
  • Existing gallery posts in the wild only have 5+ images (old imagesToMediaVariant sent <=4 to images), so "gallery always renders carousel" doesn't reclassify any existing content — all pre-existing galleries already rendered carousel.
  • The reducer's embed_set_image_layout correctly re-guards with canToggleImageLayout and no-ops when the type already matches; the documented behavior that add/remove re-picks by count (dropping an explicit choice) is acceptable.
  • ax in PostFeed.tsx is still used by other metrics, so no dead variable from the refactor.
  • Publish path (lib/api/index.ts:350) already handles gallery media, so 2-4 image gallery drafts publish correctly.
  • Strings go through Lingui, ALF/#/components used throughout, tooltip nudge mirrors the threadgate pattern, imageLayoutNudged added to the device schema.

@mozzius mozzius marked this pull request as draft July 5, 2026 18:19
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor
Old size New size Diff
8.51 MB 8.51 MB 4.17 KB (0.05%)

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.

3 participants