Skip to content

feat(website): serve a theme-aware landing showreel - #1438

Open
Wassim Chegham (manekinekko) wants to merge 2 commits into
mainfrom
manekinekko-theme-aware-landing-showreel
Open

Wassim Chegham (manekinekko) wants to merge 2 commits into
mainfrom
manekinekko-theme-aware-landing-showreel

Conversation

@manekinekko

Copy link
Copy Markdown
Member

Summary

The landing-page showreel on https://microsoft.github.io/scope/ always played the dark cut, so light-mode visitors got a dark block in the middle of a light page. The page now serves a dark cut in dark mode and a light cut in light mode, both restyled with the landing design tokens (dark: bg #0e111b, brand #b1b4ff; light: bg #fafbfd, brand #5048bd).

  • Assets: adds scope-showreel-{dark,light}.mp4 and scope-showreel-poster-{dark,light}.jpg to website/public/ and removes the old single video and poster, which were referenced only from Home.astro and the README. Encoding is unchanged: H.264 High, 1920x1080, 30 fps, 29.97 s (half speed), no audio, faststart.
  • Theme selection: the cut follows Starlight's data-theme on <html>, which Starlight sets with a blocking script, including its resolution of Auto. There is no separate preference logic.
  • No wrong-theme flash: instead of a poster attribute, Home.astro passes both posters to CSS as base-aware custom properties. The frame paints the active theme's poster, and the video stays transparent until it has a frame. This also covers reduced-motion visitors, who only see the poster, and visitors without JavaScript.
  • Live theme switching: a MutationObserver on data-theme swaps a loaded player to the matching cut at the same position, playing or paused, including after an explicit user pause. It is disconnected in disconnectedCallback.
    • A paused player loads only the frame at its position.
    • A player that is off screen or less than 25% visible hides the old cut at once and swaps when it's visible again.
    • A player that hasn't loaded yet only changes its poster.
  • Unchanged behaviour: preload="none", lazy src assignment, the 25% IntersectionObserver gating, reduced motion, the blocked-autoplay message and error reporting.
  • Styling: the frame, overlay controls, status message and narrow-screen divider use --scope-* tokens instead of hard-coded dark colours, so they stay readable over either cut.

Demos

Both screenshots show the same frame (3.3 s) in light mode.

Before

The live site in light mode plays the dark cut:

Before: dark showreel on the light landing page

After

Light mode plays the light cut:

After: light showreel on the light landing page

Dark mode plays the dark cut:

After: dark showreel on the dark landing page

Testing

From website/:

  • pnpm test: 7/7 pass.
  • pnpm build: 203 pages, with both the local / base and SITE=https://microsoft.github.io BASE_PATH=/scope. Media URLs include the base correctly in both.
  • Strict tsc on src/scripts/showreel.ts passes, and the repo license-header check (scripts/license-headers.ts --check) passes.

In headless Google Chrome (puppeteer), 72 automated checks pass against the dev server, and an earlier version of the suite passed against the /scope production preview:

  • Dark and light each paint their own poster and request only their own mp4 and poster. Auto follows a system color-scheme change.
  • Switching the theme while playing keeps position and keeps playing (2.31 s → 2.39 s).
  • Switching while user-paused stays paused at the same time (3.289 s) and shows the frame.
  • Switching while off screen, or while 10% visible, requests no new mp4 and hides the old cut immediately. Switching back restores the frame, and the swap and resume happen once the player is back in view.
  • Reduced motion shows only the matching poster and requests zero mp4s, including across theme switches. Pressing Play loads only the active cut.
  • Narrow screens (375 px) put the controls below the video with the themed divider.
  • Without JavaScript, the matching poster shows and the button stays hidden.
  • Blocked autoplay shows the message and requests no mp4 until Play. A 404 on the video shows "The showreel is unavailable", disables the button and logs the error, and the poster keeps following the theme.

Documentation and compatibility

  • website/README.md: the "Showreel" section is updated to cover both cuts and posters, how the theme is chosen and swapped, and the new file links.
  • No breaking changes. This affects only the documentation site's landing page.

Checklist

  • If Portal features changed, keep CLI capabilities in sync. (N/A: website only)
  • If Portal components changed, update their Storybook stories. (N/A)
  • If database changes require a migration, include up() / down() and keep it CosmosDB-compatible. (N/A)
  • If dependencies changed, update the lockfile and regenerate NOTICE / NOTICE-REVIEW.txt with pnpm notice as needed. (N/A: no dependency changes)
  • Screenshot showing the behavior before the suggested change
  • Screenshots showing the behavior after the suggested change

Replace the single dark showreel with dark and light cuts restyled to
the landing tokens, and pick the one matching Starlight's data-theme.

- Home.astro: expose both video URLs as data-src-dark/-light and both
  posters as base-aware CSS custom properties instead of a poster
  attribute.
- landing.css: paint the active theme's poster as the frame background
  and keep the video transparent until it has a frame, so neither
  first paint (including reduced motion and no-JS) nor a theme change
  shows the other cut. Theme the frame, overlay controls, status and
  narrow-screen divider with --scope-* tokens.
- showreel.ts: observe data-theme and swap a loaded player to the
  matching cut at the same position, keeping it playing or paused.
  Paused players load only the frame at that position; off-screen or
  partly visible players hide the stale frame and defer the swap. Lazy
  src, preload="none", visibility gating, reduced motion, blocked
  autoplay and error reporting are unchanged.
- README: document both cuts, theme selection and swapping.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The visibility state treats any intersection as visible, so theme swaps can fetch media below the documented 25% threshold.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

if (sourceIsStale()) {
// Hide the other cut at once, even when a partly visible player defers the swap.
delete video.dataset.ready;
syncPlayback();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the visibility check to require an intersection ratio of at least 0.25. Commit: 1854d40.

@manekinekko Wassim Chegham (manekinekko) added the type: documentation Documentation additions, corrections, and improvements. label Sep 30, 2026
Co-authored-by: manekinekko <1699357+manekinekko@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: documentation Documentation additions, corrections, and improvements.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants