feat: embed canonical presentation on homepage
Build and publish Eldorado documentation / build (pull_request) Successful in 42s

This commit is contained in:
jarvis-at-skic committed 2026-10-08 18:33:31 +00:00
1 parent 432370473d
commit 8a9363ccb2
10 files changed
+171 -10

No files matched your search

@@ -0,0 +1,39 @@
import React, {useEffect, useRef, useState} from 'react';
import useBaseUrl from '@docusaurus/useBaseUrl';
import styles from './styles.module.css';
/** One canonical deck document, with chrome and URL ownership isolated from the portal. */
export default function PresentationEmbed({title, path}: {title: string; path: string}): React.ReactElement {
const url = useBaseUrl(path);
const stage = useRef<HTMLDivElement>(null);
const button = useRef<HTMLButtonElement>(null);
const [fullscreen, setFullscreen] = useState(false);
const [error, setError] = useState('');
useEffect(() => {
const changed = () => {
const active = document.fullscreenElement === stage.current;
setFullscreen(active);
if (!active) button.current?.focus({preventScroll: true});
};
document.addEventListener('fullscreenchange', changed);
return () => document.removeEventListener('fullscreenchange', changed);
}, []);
async function toggleFullscreen() {
setError('');
try {
if (document.fullscreenElement === stage.current) await document.exitFullscreen();
else if (stage.current?.requestFullscreen) await stage.current.requestFullscreen();
else setError('Fullscreen is unavailable. Open presentation for a larger view.');
} catch {
setError('Fullscreen is unavailable. Open presentation for a larger view.');
}
}
return <div className={styles.stage} ref={stage}>
<iframe className={styles.frame} src={`${url}?embed`} title={`${title} — interactive presentation`} loading="lazy" allowFullScreen/>
<div className={styles.actions}>
<a href={url}>Open presentation <span aria-hidden="true">↗</span></a>
<button ref={button} type="button" onClick={toggleFullscreen} aria-pressed={fullscreen}>{fullscreen ? 'Exit fullscreen' : 'Fullscreen'}</button>
</div>
{error && <p role="status" className={styles.error}>{error}</p>}
</div>;
}
@@ -0,0 +1,12 @@
.stage {border: 1px solid var(--ifm-color-emphasis-300); background: #1f1f29;}
.frame {display: block; width: 100%; aspect-ratio: 1200 / 720; border: 0; background: #1f1f29;}
.actions {display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 16px; background: #101014; color: #fff; font-size: .875rem;}
.actions a {color: #ffc950;}
.actions button {font: inherit; color: #fff; background: transparent; border: 1px solid #62616b; padding: 8px 12px; cursor: pointer;}
.actions :focus-visible, .frame:focus-visible {outline: 3px solid #ffc950; outline-offset: -3px;}
.error {padding: 12px; margin: 0; color: #fff;}
/* Reuse the deck's portrait composition on phones; don't shrink its landscape text. */
@media (max-width: 600px) {.frame {aspect-ratio: 600 / 1100;}}
.stage:fullscreen {width: 100%; height: 100%; display: flex; flex-direction: column; border: 0;}
.stage:fullscreen .frame {flex: 1; min-height: 0; aspect-ratio: auto;}
.stage:fullscreen .actions {flex: none;}