mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-20 12:29:39 +00:00
*PR Created by the Glary-Bot Agent* --- ## Summary The illustration in the `HeroSection` of `/cloud/enterprise` was getting cut off at the top — the topmost ripple ring was clipped by the section's `overflow-y-clip`/`overflow-hidden`. **Root cause:** the SVG wrapper has `scale-150`, which makes the rendered illustration 50% larger than its layout box and overflows symmetrically (~25% above, ~25% below). The section only had `lg:pb-[min(8vw,10rem)]` — bottom padding — and on lg the wrapper had `lg:translate-y-[40px]` to nudge it down, but that wasn't enough room for the top to escape clipping. On mobile there was no padding at all, so the same issue occurred. **Fix:** add symmetric vertical padding (`pt-16` on mobile, `lg:pt-[min(8vw,10rem)]` mirroring the existing bottom value on lg) so the scaled illustration has room above and below. Removed the now-unnecessary `lg:translate-y-[40px]` since symmetric padding keeps the illustration vertically centered within the flex row. Verified at 375px (mobile), 1024px (lg), and 1440px (xl) viewports — all four ripple rings render fully without clipping at the top. ## Verification - `pnpm typecheck:website` ✅ - `pnpm exec oxfmt --check` on edited file ✅ - `pnpm exec oxlint` on edited file ✅ - `pnpm --filter @comfyorg/website build` ✅ - Pre-commit hooks (stylelint, oxfmt, oxlint, eslint, typecheck, typecheck:website) ✅ - Visual verification with Playwright at mobile / lg / xl ## Before vs After **Desktop (1440px) — before:** the topmost ripple ring is clipped at the top of the section. **Desktop (1440px) — after:** all four ripple rings are fully visible. **Mobile (375px) — before:** the top of the outermost ring is cut off by the section's top edge. **Mobile (375px) — after:** the full illustration (rings + blocks) is visible. ## Screenshots     ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11973-fix-website-prevent-illustration-cutoff-in-enterprise-hero-section-3576d73d3650813f9f04c3f93b9b42d6) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> Co-authored-by: Alexander Brown <drjkl@comfy.org>
147 lines
4.5 KiB
TypeScript
147 lines
4.5 KiB
TypeScript
import type { Page } from '@playwright/test'
|
|
|
|
import { expect } from '@playwright/test'
|
|
|
|
import { test } from './fixtures/blockExternalMedia'
|
|
import { VIEWPORTS } from './viewports'
|
|
|
|
test.describe.configure({ timeout: 60_000 })
|
|
|
|
const SMALL_VIEWPORTS = VIEWPORTS.filter(
|
|
(v) => v.name === '1-sm' || v.name === '2-md'
|
|
)
|
|
|
|
async function assertNoOverflow(page: Page) {
|
|
await expect
|
|
.poll(
|
|
() =>
|
|
page.evaluate(
|
|
() =>
|
|
document.documentElement.scrollWidth >
|
|
document.documentElement.clientWidth
|
|
),
|
|
{ message: 'page has horizontal overflow', timeout: 5_000 }
|
|
)
|
|
.toBe(false)
|
|
}
|
|
|
|
async function navigateAndSettle(page: Page, url: string) {
|
|
await page.goto(url)
|
|
await page.waitForLoadState('networkidle')
|
|
}
|
|
|
|
test.describe('Home', { tag: '@visual' }, () => {
|
|
for (const vp of VIEWPORTS) {
|
|
test.describe(vp.name, () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.setViewportSize({ width: vp.width, height: vp.height })
|
|
await navigateAndSettle(page, '/')
|
|
})
|
|
|
|
test('product-cards screenshot', async ({ page }) => {
|
|
const section = page.locator('section', {
|
|
has: page.getByRole('heading', { name: /The AI creation/i })
|
|
})
|
|
await expect(section).toBeVisible()
|
|
await section.scrollIntoViewIfNeeded()
|
|
await expect(page).toHaveScreenshot(`home-product-cards-${vp.name}.png`)
|
|
})
|
|
|
|
test('get-started screenshot', async ({ page }) => {
|
|
const section = page.locator('section', {
|
|
has: page.getByRole('heading', { name: /Get started/i })
|
|
})
|
|
await expect(section).toBeVisible()
|
|
await section.scrollIntoViewIfNeeded()
|
|
await expect(page).toHaveScreenshot(`home-get-started-${vp.name}.png`)
|
|
})
|
|
})
|
|
}
|
|
})
|
|
|
|
test.describe('Pricing', { tag: '@visual' }, () => {
|
|
for (const vp of VIEWPORTS) {
|
|
test(`pricing-tiers-${vp.name}`, async ({ page }) => {
|
|
await page.setViewportSize({ width: vp.width, height: vp.height })
|
|
await navigateAndSettle(page, '/cloud/pricing')
|
|
await assertNoOverflow(page)
|
|
|
|
const section = page.locator('section', {
|
|
has: page.getByRole('heading', { name: /Pricing/i })
|
|
})
|
|
await expect(section).toBeVisible()
|
|
await section.scrollIntoViewIfNeeded()
|
|
await expect(page).toHaveScreenshot(`pricing-tiers-${vp.name}.png`)
|
|
})
|
|
}
|
|
})
|
|
|
|
test.describe('Contact', { tag: '@visual' }, () => {
|
|
for (const vp of SMALL_VIEWPORTS) {
|
|
test(`form-${vp.name}`, async ({ page }) => {
|
|
await page.setViewportSize({ width: vp.width, height: vp.height })
|
|
await navigateAndSettle(page, '/contact')
|
|
|
|
const section = page.locator('section', {
|
|
has: page.getByRole('heading', { name: /Create powerful workflows/i })
|
|
})
|
|
await expect(section).toBeVisible()
|
|
await section.scrollIntoViewIfNeeded()
|
|
await expect(page).toHaveScreenshot(`contact-form-${vp.name}.png`)
|
|
})
|
|
}
|
|
})
|
|
|
|
test.describe('Gallery', { tag: '@visual' }, () => {
|
|
for (const vp of SMALL_VIEWPORTS) {
|
|
test(`gallery-grid-${vp.name}`, async ({ page }) => {
|
|
await page.setViewportSize({ width: vp.width, height: vp.height })
|
|
await navigateAndSettle(page, '/gallery')
|
|
|
|
const section = page.getByTestId('gallery-grid')
|
|
await expect(section).toBeVisible()
|
|
await section.scrollIntoViewIfNeeded()
|
|
await expect(page).toHaveScreenshot(`gallery-grid-${vp.name}.png`)
|
|
})
|
|
}
|
|
})
|
|
|
|
test.describe('About', { tag: '@visual' }, () => {
|
|
for (const vp of SMALL_VIEWPORTS) {
|
|
test(`hero-${vp.name}`, async ({ page }) => {
|
|
await page.setViewportSize({ width: vp.width, height: vp.height })
|
|
await navigateAndSettle(page, '/about')
|
|
|
|
const hero = page.locator('section', {
|
|
has: page.getByRole('heading', { name: /Build the tools/i })
|
|
})
|
|
await expect(hero).toBeVisible()
|
|
await hero.scrollIntoViewIfNeeded()
|
|
await expect(page).toHaveScreenshot(`about-hero-${vp.name}.png`)
|
|
})
|
|
}
|
|
})
|
|
|
|
test.describe('Overflow guards', { tag: '@visual' }, () => {
|
|
const pages = [
|
|
'/',
|
|
'/cloud',
|
|
'/cloud/enterprise',
|
|
'/cloud/pricing',
|
|
'/contact',
|
|
'/download',
|
|
'/gallery',
|
|
'/about',
|
|
'/careers'
|
|
]
|
|
for (const url of pages) {
|
|
for (const vp of VIEWPORTS) {
|
|
test(`${url} ${vp.name} no overflow`, async ({ page }) => {
|
|
await page.setViewportSize({ width: vp.width, height: vp.height })
|
|
await page.goto(url)
|
|
await assertNoOverflow(page)
|
|
})
|
|
}
|
|
}
|
|
})
|