Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion apps/docs-tests/docs/favorites-hover.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import type { Locator, Page } from '@playwright/test';
/**
* The homepage favorites come alive on hover (SHA-183): the scene mounts under
* its poster on hover or focus, pauses when the visitor leaves, stays paused
* when another favorite plays, and never mounts on touch. The no-WebGPU case
* when another favorite plays, and never mounts on touch. At the mock's
* width, the scene renders at its window's size (SHA-220). The no-WebGPU case
* is in homepage.spec.ts, which runs without the adapter this file turns on.
*/

Expand Down Expand Up @@ -133,6 +134,38 @@ test('focusing a favorite mounts its scene behind the poster until the first fra
await expect(poster(favorite)).toHaveCSS('opacity', '0');
});

// ---------------------------------------------
// The scene's size
// ---------------------------------------------

// At the mock's 1728px the grid is at its full 1440px, and a card's window
// is 320 by 233. The scene renders at that size, so useCoverScale
// (favorites-list.tsx) leaves it at a scale of 1. A larger scene, scaled
// down to fit, draws pixels the window never shows, and shrinks the cells
// that Dither and LED Wall size in CSS pixels.
test.describe('at the mock’s 1728px width', () => {
test.use({ viewport: { width: 1728, height: 1117 } });

test('a favorite’s scene renders at its window’s size, with no scale', async ({ page }) => {
await open(page);

const favorite = favorites(page).first();

await favorite.hover();
// useCoverScale writes the scale once it learns the window's size.
await expect(scene(favorite)).toHaveCSS('scale', '1');
expect(
await scene(favorite).evaluate((sceneLayer: HTMLElement) => ({
scene: [sceneLayer.offsetWidth, sceneLayer.offsetHeight],
sceneWindow: [
sceneLayer.parentElement!.clientWidth,
sceneLayer.parentElement!.clientHeight,
],
})),
).toEqual({ scene: [320, 233], sceneWindow: [320, 233] });
});
});

// ---------------------------------------------
// Pausing when the visitor leaves
// ---------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions apps/docs-tests/docs/homepage.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ test('a favorite is named for its component', async ({ page }) => {

// Each favorite shows its card poster, not the small square the components
// index uses, and every one has loaded. A card poster is captured at the live
// scene's shape, 376 by 275, so the spec checks the file's shape too.
// scene's shape, 320 by 233, so the spec checks the file's shape too.
test('each favorite shows its poster', async ({ page }) => {
await open(page);
await expect(favorites(page)).toHaveCount(FAVORITES.length);
Expand Down Expand Up @@ -174,7 +174,7 @@ test('each favorite shows its poster', async ({ page }) => {
expect(image.src, image.href).toMatch(
new RegExp(`/posters/${FAVORITES[index]}-card\\.(jpg|png)`),
);
expect(image.shape, image.href).toBeCloseTo(376 / 275, 2);
expect(image.shape, image.href).toBeCloseTo(320 / 233, 2);
}
});

Expand Down
Binary file modified apps/docs/public/posters/dither-card.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/docs/public/posters/god-rays-card.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/docs/public/posters/led-wall-card.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/docs/public/posters/mesh-gradient-card.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/docs/public/posters/simplex-noise-card.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/docs/public/posters/voronoi-card.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified apps/docs/public/posters/wave-lines-card.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 10 additions & 8 deletions apps/docs/src/components/favorites/favorites-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,16 @@ function LiveScene({ slug, paused }: { slug: FavoriteSlug; paused: boolean }) {

// The size every favorite renders at, in CSS pixels, and the size
// scripts/build-posters.sh captures every favorite's card poster at. It is
// the card window's size on a 1664px grid, 17.5% larger than the 320 by 233
// window at the grid's full 1440px, so useCoverScale scales the scene down
// to cover the window, as it does at every narrower width. Larger draws
// more pixels than the window shows, and shrinks patterns sized in CSS
// pixels, such as Dither's and LED Wall's cells. Smaller than the window
// makes useCoverScale scale the scene up, which blurs it. SHA-220 sets it
// to the window's size.
const SCENE_SIZE = { width: 376, height: 275 };
// the card window's size at the grid's full 1440px, where useCoverScale
// leaves the scene at a scale of 1, so Dither's and LED Wall's cells, which
// are sized in CSS pixels, show at their real size. Four narrower columns
// scale it down. Larger would draw more pixels than the window shows, and
// smaller would scale the scene up, which softens it. The two-column and
// one-column grids already scale it up at their wider widths, as far as
// about 1.8 times for the 579 by 427 window at 639px. A change to the
// grid's width or the card's padding moves the window, so change this with
// it and recapture the card posters.
const SCENE_SIZE = { width: 320, height: 233 };

/**
* Scales the scene to cover its window, the way `object-fit: cover` scales
Expand Down
9 changes: 5 additions & 4 deletions scripts/build-posters.sh
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ $CLI \
--height 696 \
--background "#0b0f1a"

# The homepage favorites render every live scene at 376 by 275 (SCENE_SIZE in
# The homepage favorites render every live scene at 320 by 233, the card
# window's size at the grid's full 1440px (SCENE_SIZE in
# apps/docs/src/components/favorites/favorites-list.tsx), and scale it with
# the card. Each favorite's card poster is captured at that size, over the
# ground its scene sits on there, so the poster frames and crops the scene
Expand All @@ -140,13 +141,13 @@ for pair in \
"god-rays:jpg:linear-gradient(to top, #131b31, #0b0f1a)" \
"led-wall:jpg:#0b0f0d"; do
IFS=':' read -r name format background <<< "$pair"
echo "==> ${name}-card ($format, 376x275)"
echo "==> ${name}-card ($format, 320x233)"
card_args=(
--source "${COMPONENTS_DIR}/${name}/scene.tsx"
--output "${OUT_DIR}/${name}-card.${format}"
--format "$format"
--width 376
--height 275
--width 320
--height 233
)
if [ -n "$background" ]; then
card_args+=(--background "$background")
Expand Down
Loading