-
Notifications
You must be signed in to change notification settings - Fork 429
Scale homepage hero slides correctly on mobile #38740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6a89b76
e21cf92
6fc4a83
3c76496
6ea4e1a
0a0d597
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -76,6 +76,8 @@ function unmountFromHero() { | |
| let renderVersion = 0; | ||
| /** @type {number | undefined} */ | ||
| let autoplayTimer; | ||
| const MINIMUM_STAGE_DIMENSION = 1; | ||
| const MINIMUM_RENDER_SCALE = 0.1; | ||
|
|
||
| function stopCarousel() { | ||
| window.clearInterval(autoplayTimer); | ||
|
|
@@ -103,8 +105,16 @@ function unmountFromHero() { | |
|
|
||
| const devicePixelRatio = window.devicePixelRatio || 1; | ||
| const baseViewport = page.getViewport({ scale: 1 }); | ||
| const availableWidth = stage.clientWidth - 16; | ||
| const scale = Math.max(availableWidth / baseViewport.width, 0.5); | ||
| const stageStyles = window.getComputedStyle(stage); | ||
| const parseInset = (value) => Number.parseFloat(value) || 0; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
💡 Suggested fix
const MINIMUM_STAGE_DIMENSION = 1;
const MINIMUM_RENDER_SCALE = 0.1;
const parseInset = (value) => Number.parseFloat(value) || 0;Then remove the definition from inside |
||
| const horizontalInset = parseInset(stageStyles.paddingLeft) + parseInset(stageStyles.paddingRight); | ||
| const verticalInset = parseInset(stageStyles.paddingTop) + parseInset(stageStyles.paddingBottom); | ||
| const availableWidth = Math.max(stage.clientWidth - horizontalInset, MINIMUM_STAGE_DIMENSION); | ||
| const availableHeight = Math.max(stage.clientHeight - verticalInset, MINIMUM_STAGE_DIMENSION); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If 💡 DetailsWhen The old code only used Suggested mitigations (pick one or combine):
if (availableWidth <= MINIMUM_STAGE_DIMENSION || availableHeight <= MINIMUM_STAGE_DIMENSION) {
// Layout not ready; retry next frame
requestAnimationFrame(() => void renderPage(pageNumber));
return;
} |
||
| const scale = Math.max( | ||
| Math.min(availableWidth / baseViewport.width, availableHeight / baseViewport.height), | ||
| MINIMUM_RENDER_SCALE, | ||
| ); | ||
| const viewport = page.getViewport({ scale }); | ||
|
|
||
| bufferCanvas.width = Math.floor(viewport.width * devicePixelRatio); | ||
|
|
@@ -130,7 +140,10 @@ function unmountFromHero() { | |
| canvasContext.drawImage(bufferCanvas, 0, 0); | ||
|
|
||
| activePage = pageNumber; | ||
| loading?.setAttribute('hidden', 'hidden'); | ||
| if (loading) { | ||
| loading.setAttribute('hidden', 'hidden'); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/diagnose] The root cause here is that The JS workaround works, but fixing it in CSS is more idiomatic and removes the coupling between the JS and the display implementation: .workflow-hero__loading[hidden] { display: none; }That would make the |
||
| loading.style.display = 'none'; | ||
| } | ||
| root.classList.add('is-ready'); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,6 +38,26 @@ test.describe('Slide Preview on Homepage', () => { | |
| await expect(slideHero).toHaveClass(/is-ready/); | ||
| }); | ||
|
|
||
| test('should keep the rendered slide within the frame on mobile screens', async ({ page }) => { | ||
| await page.setViewportSize({ width: 390, height: 844 }); | ||
| await page.goto('/gh-aw/'); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/tdd] This test calls Consider extracting the mobile scenario into its own |
||
| await page.waitForLoadState('networkidle'); | ||
|
|
||
| const loading = page.locator('[data-slide-loading]'); | ||
| await expect(loading).toBeHidden({ timeout: 10000 }); | ||
|
|
||
| const stage = page.locator('[data-slide-stage]'); | ||
| const canvas = page.locator('[data-slide-canvas]'); | ||
| const stageBox = await stage.boundingBox(); | ||
| const canvasBox = await canvas.boundingBox(); | ||
|
|
||
| expect(stageBox).not.toBeNull(); | ||
| expect(canvasBox).not.toBeNull(); | ||
|
|
||
| expect(canvasBox!.width).toBeLessThanOrEqual(stageBox!.width); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [/tdd] The assertion compares against For a tighter regression guard, compare against the inner slides container ( |
||
| expect(canvasBox!.height).toBeLessThanOrEqual(stageBox!.height); | ||
|
Comment on lines
+49
to
+58
|
||
| }); | ||
|
|
||
| test('should be keyboard accessible', async ({ page }) => { | ||
| // Wait for slides to load | ||
| const loading = page.locator('[data-slide-loading]'); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[/diagnose]
MINIMUM_STAGE_DIMENSION = 1is used to guard the division in the scale formula against a zero-or-negative clientWidth/Height, but that purpose isn't immediately obvious from the name or value.A brief inline comment would help future readers (and avoid someone bumping it to
0thinking it's a threshold):