Skip to content

feat: reposition document cover images - #1094

Open
ion-lion wants to merge 2 commits into
seed-hypermedia:mainfrom
ion-lion:ion/issue-906-cover-position
Open

feat: reposition document cover images#1094
ion-lion wants to merge 2 commits into
seed-hypermedia:mainfrom
ion-lion:ion/issue-906-cover-position

Conversation

@ion-lion

@ion-lion ion-lion commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Why now

Issue #906 reports that editors can change, remove, and download document covers but cannot choose the visible crop. The shared desktop/web DocumentCover always used centered object-fit: cover, so portraits and off-center subjects could remain cropped after draft reload and publish.

What changed

  • Adds a Notion-style Reposition mode to the shared cover: pointer/touch drag with pointer capture, safe clamping, Save/Cancel, and keyboard arrows (Shift = 10), Enter, and Escape.
  • Stores a backward-compatible coverPosition: {x, y} focal point as integer percentages. Missing or partial metadata defaults to center.
  • Stages the position through the existing document draft metadata path and renders it through CSS object-position in both desktop and web.
  • Clears stale positioning when a cover is replaced or removed.
  • Declares the metadata field, preserves it in canonical Markdown and CLI frontmatter merges, and verifies nested publish/removal operations. CLI cover replacement/removal compares against published metadata, resets an omitted focal point, and expands object removal into per-coordinate tombstones so a new image cannot inherit the old crop.

Why this approach

object-position already guarantees safe cover bounds, so the UI only needs to convert pointer movement into percentages of the rendered image overflow. Two coordinates remain correct across different viewport aspect ratios; a pixel offset or vertical-only scalar would not. Integer 0…100 values are required because document SetAttribute supports integer numbers but not floats. Older clients ignore the extra metadata and older documents remain centered.

The interaction previews locally and writes once on Save rather than autosaving every pointer move. Replacing/removing uses a null tombstone so the existing recursive UI attribute diff clears both nested coordinates. The CLI update path applies the same rule against the published metadata and expands the object tombstone into leaf operations; a parent-only null is not reliable for multi-child attributes.

Validation

  • DocumentCover focused tests: 9/9 passed (existing actions, position rendering, drag/clamp, keyboard Save, Escape cancel, focus entry).
  • Client metadata and lossless Markdown suites: 74/74 passed.
  • Shared document-change suite: 24/24 passed, including nested integer publication and per-leaf clearing.
  • Client and shared package typechecks passed.
  • Focused CLI metadata regression tests: 5/5 passed (replacement, removal, explicit-position preservation, unrelated update preservation, and leaf tombstones); the CLI entry bundle compiled successfully.
  • Prettier on all touched files and git diff --check passed.
  • The UI package typecheck exceeded this executor's memory limit and was killed without a diagnostic; targeted UI compilation/tests passed.

Follow-up

This slice intentionally covers the issue's document-header behavior on desktop and web. Native mobile does not currently render/edit document covers. Newspaper thumbnails and generated social images still center-crop and can adopt the same focal metadata separately if product acceptance expands beyond document covers.

@ion-lion
ion-lion marked this pull request as ready for review September 11, 2026 04:44
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