Skip to content

feat: add a padding option to element screenshots - #410

Open
gregberge wants to merge 2 commits into
mainfrom
claude/arg-515-element-screenshot-padding-f946b5
Open

gregberge wants to merge 2 commits into
mainfrom
claude/arg-515-element-screenshot-padding-f946b5

Conversation

@gregberge

@gregberge gregberge commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Description

Fixes ARG-515. Element screenshots can now capture the space around the element (shadows, focus rings, overflowing content) with a padding option. Before, only Storybook could do this (fitToContent.padding); the other SDKs clipped to the element's box.

padding is a number, or an array of 1 to 4 numbers in CSS shorthand order ([10, 20], [1, 2, 3, 4]), in CSS pixels. The captured area is clamped to the page. It's named padding because Cypress already has a native option with that name and meaning.

  • Playwright. New padding option. It requires element and throws if combined with clip or given an invalid value. The SDK scrolls the element into view, adds the padding to its bounding box, and takes a page.screenshot with a clip. Like an element screenshot, it only captures beyond the viewport when the area doesn't fit in it, which is much slower on long pages in Chromium. When the element is in an iframe, the area is also clamped to that iframe's visible content, so the frame border and the page around it stay out. This holds whatever the handler. @argos-ci/vitest captures through an iframe, so this matters there.
  • Puppeteer. Same option, following the steps of Puppeteer's own element screenshot. Puppeteer's element-relative clip only exists in recent versions, and the peer range is >=1, so the SDK passes an absolute clip to page.screenshot.
  • Cypress. padding already reached cy.screenshot, but Cypress doesn't clamp it: near the page edge it moves the area back inside the page. A 100px element in the corner with padding: 20 came out 140×140 with 40px of page on two sides. The SDK now reduces the padding to fit the page before calling Cypress. Screenshots of the page, not an element, still pass padding through, and Cypress ignores it.
  • Vitest. padding per-call option, forwarded to the Playwright SDK.
  • Locator as handler (Playwright). argosScreenshot(page.getByRole("dialog"), "dialog") now works as a shortcut for the element option. Before, a Locator was mistaken for a Frame (both have page()) and failed with an unrelated addScriptTag error. checkIsFrame now checks parentFrame, which only frames have. The SDK resolves the locator's frame, so a locator inside an iframe is stabilized in that iframe. Passing a Locator together with element throws.

The validation and padding math (resolvePaddingOption, getPaddedClip, clampPadding) live in @argos-ci/util. Puppeteer and Cypress measure the document with a new __ARGOS__.getDocumentMetrics() in @argos-ci/browser. padding: 0 takes the regular element screenshot path.

Type of changes

enhancement

Checklist

  • I have read the CONTRIBUTING doc (the repo has none)
  • The commits message follows the Conventional Commits' policy
  • Lint and unit tests pass locally
  • I have added tests if needed

Optional checks:

Further comments

  • Tests. The e2e tests check image sizes and pixel colors with an element whose box-shadow overflows its box. They cover padding, the CSS shorthand, an element below the fold, an area larger than the viewport, clamping to the page and to a frame (with a frame handler or a frame element), Locator handlers (including one inside an iframe), and the error cases. Locally: Playwright 43/43, Puppeteer 24/24, Cypress 16 11/11, Vitest e2e 22/22, plus unit tests for the util helpers.
  • Clamping. A box-shadow doesn't grow the document's scroll size, so a shadow at the very bottom of the page is cut at the document edge, as in a full-page screenshot.
  • Docs. The Playwright migration guide already shows argosScreenshot(page.getByRole("dialog"), …), which works once this ships. docs: document element screenshot padding and Playwright Locator handler docs#272 adds padding to the four SDK references and should merge after the release.

🤖 Generated with Claude Code

Capture the space around an element (shadows, focus rings, overflowing
content) with `padding`, a number or a CSS-shorthand array of up to 4
values. The captured area is clamped to the page, and to the frame for a
Playwright `Frame` handler.

- Playwright, Puppeteer: new `padding` option, requires `element`.
- Cypress: the native `padding` option is now clamped to the page;
  Cypress shifted the area back into the page instead.
- Vitest: `padding` per-call option.

Playwright's `argosScreenshot` also accepts a `Locator` as handler, a
shortcut for the `element` option. It used to be mistaken for a Frame
and failed with an unrelated error.

Fixes ARG-515

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
argos-js-sdk-reference Ready Ready Preview Nov 5, 2026 10:26am UTC

Request Review

@linear-code

linear-code Bot commented Nov 5, 2026

Copy link
Copy Markdown

ARG-515

- Validate the `padding` option once with `resolvePaddingOption`, and
  pass resolved sides to `getPaddedClip` and `clampPadding`. A zero
  padding takes the regular element screenshot path.
- Measure the document with `__ARGOS__.getDocumentMetrics()` in
  Puppeteer and Cypress instead of a copy in each SDK.
- Playwright: resolve the element once, clamp to the frame the element
  lives in whatever the handler, and only capture beyond the viewport
  when the area doesn't fit in it, like an element screenshot.
- Playwright: detect frames by `parentFrame`, so a Locator is never
  mistaken for one.
- Share test helpers instead of copy-pasted assertions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch was successfully deployed

1 active deployment
Preview — b460848e Deployed Nov 5, 2026 by vercel[bot]
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