diff --git a/configurator/src/components/Preview.svelte b/configurator/src/components/Preview.svelte index 26620180..6715c1e8 100644 --- a/configurator/src/components/Preview.svelte +++ b/configurator/src/components/Preview.svelte @@ -4,6 +4,9 @@ /** @type {HTMLButtonElement | undefined} */ let closeBtn; + /** @type {HTMLElement | undefined} */ + let previewEl; + let isFullscreen = $state(false); $effect(() => { if (!window.matchMedia('(max-width: 1100px)').matches) return; @@ -13,6 +16,25 @@ }; }); + $effect(() => { + const handler = () => { isFullscreen = document.fullscreenElement === previewEl; }; + document.addEventListener('fullscreenchange', handler); + return () => document.removeEventListener('fullscreenchange', handler); + }); + + async function toggleFullscreen() { + if (!previewEl) return; + try { + if (document.fullscreenElement === previewEl) { + await document.exitFullscreen?.(); + } else { + await previewEl.requestFullscreen?.(); + } + } catch { + // keep UI stable if fullscreen is denied or unavailable + } + } + const VIEWPORTS = [ { id: 'mobile', emoji: 'πŸ“±', label: 'Mobile', width: 360, hint: '360 px' }, { id: 'tablet', emoji: 'πŸ“±', label: 'Tablet', width: 768, hint: '768 px' }, @@ -84,7 +106,7 @@ const preventDemoNav = (e) => e.preventDefault(); -
+
@@ -107,6 +129,7 @@
{ui.previewTheme}{ui.previewMotion === 'reduced' ? ' Β· reduced motion' : ''}{activeViewport.width ? ` Β· ${activeViewport.width} px` : ''} +
@@ -1028,6 +1051,10 @@ .preview__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--cfg-ok); box-shadow: 0 0 0 3px rgba(90,210,122,.18); } .preview__hint { font-size: 11px; color: var(--cfg-text-faint); text-transform: capitalize; } .preview__modes :global(.cfg-seg__btn) { padding: 4px 9px; font-size: 12px; } + .preview__fullscreen { width: 26px; height: 26px; padding: 0; font-size: 14px; line-height: 1; color: var(--cfg-text-muted); background: var(--cfg-surface-2); border: 1px solid var(--cfg-border-strong); border-radius: var(--cfg-radius-s); cursor: pointer; flex-shrink: 0; display: inline-grid; place-items: center; } + .preview__fullscreen:hover { color: var(--cfg-text); border-color: var(--cfg-accent-strong); } + .preview:fullscreen { background: var(--cfg-bg); } + .preview:fullscreen .preview__close { display: none; } .preview__close { display: none; margin-left: auto; width: 26px; height: 26px; padding: 0; font-size: 13px; line-height: 1; color: var(--cfg-text-muted); background: var(--cfg-surface-2); border: 1px solid var(--cfg-border-strong); border-radius: var(--cfg-radius-s); cursor: pointer; flex-shrink: 0; } .preview__close:hover { color: var(--cfg-text); border-color: var(--cfg-accent-strong); } @media (max-width: 1100px) { diff --git a/configurator/src/components/ScaleGenerator.svelte b/configurator/src/components/ScaleGenerator.svelte index c676d482..9611bd47 100644 --- a/configurator/src/components/ScaleGenerator.svelte +++ b/configurator/src/components/ScaleGenerator.svelte @@ -136,6 +136,8 @@ const applicable = $derived(computed.filter((s) => tokenByName.has(s.token))); const missing = $derived(computed.length - applicable.length); + let isOpen = $state(false); + let applied = $state(false); function apply() { if (engineLive) { @@ -167,6 +169,15 @@
+ + + {#if isOpen} +
{#if kinds.length > 1}
{#each kinds as k (k)} @@ -228,16 +239,41 @@ {missing} step(s) not in this catalogue β€” skipped. {/if}
+
+ {/if}