Files
libretro/website/src/components/InstallDemo.astro
T
Abdessamad Derraz 77fef7289f feat: show the handheld demo and steps per tab
make_demo.py records a second variant: the full-screen interface at the
640x480 screen of an R36S, on an ArkOS root made with bwrap, started as
the Tools menu launcher starts it (RETROBIOS_PAD=gptokeyb), driven by the
keys gptokeyb sends for the buttons. demo.json holds one entry per
variant with its alt text. No Windows variant: under pwsh on Linux the
installer's summary gives --dest /mnt/e/bios back.

The quick install box of Get your files gets an "On the device" tab with
the handheld recording, the terminal recording under the others but
Windows, and, under the text of each computer tab, a drawing of opening
the terminal and pasting (sitesteps.py, inline SVG in the theme's
colours, title and desc). The terminal steps name the physical action.
2026-11-09 07:35:03 +01:00

127 lines
3.6 KiB
Plaintext

---
// The installer demo, recorded by scripts/make_demo.py and served from
// public/assets/demo/. Nothing of it loads before it is on screen: the
// poster and the sources are set by the script below once the video is in
// view (preload="none", no src in the HTML). With reduced motion or Save-Data
// the poster stays, and the button plays it. The button pauses it otherwise.
// variant names the recording (default, handheld), name the tab a demo sits
// in when a page holds several: a demo in a closed tab is not on screen, so
// it loads nothing until its tab is chosen.
interface Props {
description: string;
width: string;
height: string;
variant?: 'default' | 'handheld';
name?: string;
}
const { description, width, height, variant = 'default', name = '' } = Astro.props;
const base = import.meta.env.BASE_URL.replace(/\/?$/, '/');
const stem = variant === 'default' ? 'install' : `install-${variant}`;
const asset = (ext: string) => `${base}assets/demo/${stem}.${ext}`;
const textId = name ? `rb-demo-text-${name}` : 'rb-demo-text';
---
<figure class="rb-demo" data-demo data-variant={variant} data-pagefind-ignore>
<video
width={width}
height={height}
muted
loop
playsinline
preload="none"
disablepictureinpicture
data-poster={asset('png')}
aria-describedby={textId}
>
<source data-src={asset('webm')} type="video/webm" />
<source data-src={asset('mp4')} type="video/mp4" />
</video>
<button type="button" class="rb-demo-toggle" hidden>Play</button>
<figcaption id={textId} class="sr-only">{description}</figcaption>
</figure>
<script>
const still = () =>
matchMedia('(prefers-reduced-motion: reduce)').matches ||
Boolean((navigator as Navigator & { connection?: { saveData?: boolean } }).connection?.saveData);
for (const figure of document.querySelectorAll<HTMLElement>('[data-demo]')) {
const video = figure.querySelector('video');
const toggle = figure.querySelector<HTMLButtonElement>('.rb-demo-toggle');
if (!video || !toggle) continue;
let wanted = !still();
let visible = false;
let loaded = false;
const sync = () => {
if (wanted && visible) {
if (!loaded) {
loaded = true;
for (const source of video.querySelectorAll('source')) source.src = source.dataset.src ?? '';
video.load();
}
video.play().catch(() => {
wanted = false;
toggle.textContent = 'Play';
});
} else {
video.pause();
}
toggle.textContent = wanted ? 'Pause' : 'Play';
};
toggle.hidden = false;
toggle.addEventListener('click', () => {
wanted = !wanted;
sync();
});
new IntersectionObserver(
(entries) => {
visible = entries.some((entry) => entry.isIntersecting);
if (visible && !video.poster) video.poster = video.dataset.poster ?? '';
sync();
},
{ threshold: 0.25 },
).observe(video);
}
</script>
<style>
.rb-demo {
position: relative;
margin-inline: 0;
}
.rb-demo video {
display: block;
width: 100%;
height: auto;
background: #12131c;
border: 1px solid var(--rb-border);
border-radius: 0.5rem;
}
/* A handheld's 4:3 screen, no taller than the terminal recording. */
.rb-demo[data-variant='handheld'] {
max-inline-size: 32rem;
}
.rb-demo-toggle {
position: absolute;
inset-inline-end: 0.5rem;
inset-block-end: 0.5rem;
min-height: 2.75rem;
padding: 0.4rem 1rem;
font: inherit;
font-size: var(--sl-text-sm);
color: var(--sl-color-white);
background: var(--rb-surface);
border: 1px solid var(--rb-border-strong);
border-radius: 0.4rem;
cursor: pointer;
}
.rb-demo-toggle:hover {
background: var(--sl-color-accent-low);
}
.rb-demo-toggle:focus-visible {
outline: 2px solid var(--sl-color-accent);
outline-offset: 2px;
}
</style>