From 91ef1196979a17a8e4a327dffedc53bb608872a8 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Fri, 9 Jan 2026 17:07:02 +0100 Subject: [PATCH] fix: keyboard shortcut Cmd/Ctrl+S now works when focus is in preview iframe Added keyboard event listener to iframe document to capture shortcuts when user is focused inside the preview. Previously, keyboard events inside iframes didn't bubble up to the parent document. Changes: - Add handleKeyboardShortcut function in App.vue - Attach keydown listener to main document (for focus outside iframe) - Attach keydown listener to iframe document (for focus inside iframe) - Clean up listener on unmount Co-Authored-By: Claude Sonnet 4.5 --- src/App.vue | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/App.vue b/src/App.vue index 63fc895..efd64cb 100644 --- a/src/App.vue +++ b/src/App.vue @@ -5,7 +5,7 @@ import ElementPopup from './components/ElementPopup.vue'; import PagePopup from './components/PagePopup.vue'; import PreviewLoader from './components/PreviewLoader.vue'; import SaveButton from './components/SaveButton.vue'; -import { onMounted, ref, watch, computed, provide } from 'vue'; +import { onMounted, onUnmounted, ref, watch, computed, provide } from 'vue'; import { useStylesheetStore } from './stores/stylesheet'; import { useNarrativeStore } from './stores/narrative'; import Coloris from '@melloware/coloris'; @@ -38,6 +38,19 @@ const activeFrame = computed(() => { : previewFrame2.value; }); +// Handle keyboard shortcuts (Cmd/Ctrl+S for save) +const handleKeyboardShortcut = (event) => { + // Check for Cmd+S (Mac) or Ctrl+S (Windows/Linux) + if ((event.metaKey || event.ctrlKey) && event.key === 's') { + event.preventDefault(); + + // Only save if there are changes and not currently saving + if (stylesheetStore.isDirty && !stylesheetStore.isSaving) { + stylesheetStore.saveCustomCss(); + } + } +}; + // Check if mouse position is near the edges of a page element const isNearPageEdge = (pageElement, mouseX, mouseY) => { const rect = pageElement.getBoundingClientRect(); @@ -436,6 +449,9 @@ const renderPreview = async (shouldReloadFromFile = false) => { ); hiddenFrame.contentDocument.addEventListener('click', handleIframeClick); + // Add keyboard shortcut listener to iframe (for when focus is inside iframe) + hiddenFrame.contentDocument.addEventListener('keydown', handleKeyboardShortcut); + // Close Coloris when clicking in the iframe hiddenFrame.contentDocument.addEventListener('click', () => { Coloris.close(); @@ -563,9 +579,17 @@ onMounted(async () => { await stylesheetStore.initializeFromNarrative(narrativeStore.data); } + // Add keyboard shortcut listener to document (for when focus is outside iframe) + document.addEventListener('keydown', handleKeyboardShortcut); + // Render preview after data is loaded renderPreview(true); }); + +onUnmounted(() => { + // Clean up keyboard shortcut listener + document.removeEventListener('keydown', handleKeyboardShortcut); +});