From 9e02813d1997a0e1aeeb42943318de19c2633744 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Fri, 5 Dec 2025 16:41:07 +0100 Subject: [PATCH 1/3] feat: add animated CSS loader during preview reload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Displays a spinning loader in the top-right corner of the iframe while PagedJS is rendering. The loader automatically adjusts position when the editor panel is open. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/App.vue | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/src/App.vue b/src/App.vue index 4441e9d..24f9cc7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -16,7 +16,7 @@ provide('activeTab', activeTab); let savedScrollPercentage = 0; const currentFrameIndex = ref(1); // 1 or 2, which iframe is currently visible -let isTransitioning = false; +const isTransitioning = ref(false); const activeFrame = computed(() => { return currentFrameIndex.value === 1 @@ -25,8 +25,8 @@ const activeFrame = computed(() => { }); const renderPreview = async (shouldReloadFromFile = false) => { - if (isTransitioning) return; - isTransitioning = true; + if (isTransitioning.value) return; + isTransitioning.value = true; // Determine which iframe is currently visible and which to render to const visibleFrame = @@ -35,7 +35,7 @@ const renderPreview = async (shouldReloadFromFile = false) => { currentFrameIndex.value === 1 ? previewFrame2.value : previewFrame1.value; if (!hiddenFrame) { - isTransitioning = false; + isTransitioning.value = false; return; } @@ -112,7 +112,7 @@ const renderPreview = async (shouldReloadFromFile = false) => { // Swap current frame currentFrameIndex.value = currentFrameIndex.value === 1 ? 2 : 1; - isTransitioning = false; + isTransitioning.value = false; }, 200); // Match CSS transition duration }, 50); // Small delay to ensure scroll is set }, 200); // Wait for PagedJS @@ -147,6 +147,10 @@ onMounted(() => renderPreview(true)); :class="{ shifted: activeTab.length > 0 }" > +
+
+
+ @@ -179,4 +183,39 @@ onMounted(() => renderPreview(true)); z-index: 0; opacity: 0; } + +.preview-loader { + position: fixed; + top: 2rem; + right: 2rem; + z-index: 1000; + pointer-events: none; + transition: all 0.2s ease-in-out var(--curve); +} + +.preview-loader.shifted { + right: calc(2rem + 19rem * 0.7); + top: calc(2rem - 30vh * 0.7); + transform: scale(0.7); +} + +.spinner { + width: 48px; + height: 48px; + border-radius: 50%; + display: inline-block; + border-top: 3px solid #fff; + border-right: 3px solid transparent; + box-sizing: border-box; + animation: rotation 1s linear infinite; +} + +@keyframes rotation { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} From c08426068860e1577a7c56d446c4340bef2ebfb0 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Fri, 5 Dec 2025 16:45:57 +0100 Subject: [PATCH 2/3] refactor: extract PreviewLoader into separate component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves loader HTML and CSS from App.vue to dedicated PreviewLoader component for better code organization. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/App.vue | 40 ++--------------------- src/components/PreviewLoader.vue | 55 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 38 deletions(-) create mode 100644 src/components/PreviewLoader.vue diff --git a/src/App.vue b/src/App.vue index 24f9cc7..1b8746a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,6 +2,7 @@ import PagedJsWrapper from './components/PagedJsWrapper.vue'; import EditorPanel from './components/editor/EditorPanel.vue'; import ElementPopup from './components/ElementPopup.vue'; +import PreviewLoader from './components/PreviewLoader.vue'; import { onMounted, ref, watch, computed, provide } from 'vue'; import { useStylesheetStore } from './stores/stylesheet'; import Coloris from '@melloware/coloris'; @@ -147,9 +148,7 @@ onMounted(() => renderPreview(true)); :class="{ shifted: activeTab.length > 0 }" > -
-
-
+ @@ -183,39 +182,4 @@ onMounted(() => renderPreview(true)); z-index: 0; opacity: 0; } - -.preview-loader { - position: fixed; - top: 2rem; - right: 2rem; - z-index: 1000; - pointer-events: none; - transition: all 0.2s ease-in-out var(--curve); -} - -.preview-loader.shifted { - right: calc(2rem + 19rem * 0.7); - top: calc(2rem - 30vh * 0.7); - transform: scale(0.7); -} - -.spinner { - width: 48px; - height: 48px; - border-radius: 50%; - display: inline-block; - border-top: 3px solid #fff; - border-right: 3px solid transparent; - box-sizing: border-box; - animation: rotation 1s linear infinite; -} - -@keyframes rotation { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -} diff --git a/src/components/PreviewLoader.vue b/src/components/PreviewLoader.vue new file mode 100644 index 0000000..a1c43d8 --- /dev/null +++ b/src/components/PreviewLoader.vue @@ -0,0 +1,55 @@ + + + + + From de5d12c0fa052151d041edadc2e2a41dba0e7ccb Mon Sep 17 00:00:00 2001 From: isUnknown Date: Fri, 5 Dec 2025 16:49:47 +0100 Subject: [PATCH 3/3] preview loader : reduce size --- src/components/PreviewLoader.vue | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/components/PreviewLoader.vue b/src/components/PreviewLoader.vue index a1c43d8..cabc52b 100644 --- a/src/components/PreviewLoader.vue +++ b/src/components/PreviewLoader.vue @@ -8,12 +8,12 @@ defineProps({ isLoading: { type: Boolean, - required: true + required: true, }, shifted: { type: Boolean, - default: false - } + default: false, + }, }); @@ -27,15 +27,9 @@ defineProps({ transition: all 0.2s ease-in-out var(--curve); } -.preview-loader.shifted { - right: calc(2rem + 19rem * 0.7); - top: calc(2rem - 30vh * 0.7); - transform: scale(0.7); -} - .spinner { - width: 48px; - height: 48px; + width: 2rem; + height: 2rem; border-radius: 50%; display: inline-block; border-top: 3px solid #000;