feat: improve page highlight with orange color and template grouping

- Add --color-page-highlight CSS variable (#ff8a50)
- Change page edge highlight from blue to orange
- Keep border visible while PagePopup is open
- Highlight all pages using the same template (data-page-type)
- Display dynamic page count in PagePopup header
- Emit close event from PagePopup for proper cleanup

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
isUnknown 2025-12-08 12:29:55 +01:00
parent ee849dab8e
commit 7647aadb63
3 changed files with 57 additions and 19 deletions

View file

@ -19,7 +19,9 @@ provide('activeTab', activeTab);
// Page interaction state
const hoveredPage = ref(null);
const selectedPages = ref([]); // Pages with active border (when popup is open)
const EDGE_THRESHOLD = 30; // px from edge to trigger hover
const PAGE_HIGHLIGHT_COLOR = '#ff8a50';
let savedScrollPercentage = 0;
const currentFrameIndex = ref(1); // 1 or 2, which iframe is currently visible
@ -51,6 +53,15 @@ const isNearPageEdge = (pageElement, mouseX, mouseY) => {
);
};
// Get all pages using the same template as the given page
const getPagesWithSameTemplate = (page, doc) => {
const pageType = page.getAttribute('data-page-type') || 'default';
const allPages = doc.querySelectorAll('.pagedjs_page');
return Array.from(allPages).filter(
(p) => (p.getAttribute('data-page-type') || 'default') === pageType
);
};
// Handle mouse movement in iframe
const handleIframeMouseMove = (event) => {
const pages = event.target.ownerDocument.querySelectorAll('.pagedjs_page');
@ -65,20 +76,28 @@ const handleIframeMouseMove = (event) => {
// Update hover state
if (foundPage !== hoveredPage.value) {
// Remove highlight from previous page
if (hoveredPage.value) {
// Remove highlight from previous page (only if not in selectedPages)
if (hoveredPage.value && !selectedPages.value.includes(hoveredPage.value)) {
hoveredPage.value.style.outline = '';
}
// Add highlight to new page
if (foundPage) {
foundPage.style.outline = '2px solid rgba(97, 175, 239, 0.3)';
// Add highlight to new page (only if not already selected)
if (foundPage && !selectedPages.value.includes(foundPage)) {
foundPage.style.outline = `2px solid ${PAGE_HIGHLIGHT_COLOR}50`;
}
hoveredPage.value = foundPage;
}
};
// Clear selection highlight from all selected pages
const clearSelectedPages = () => {
selectedPages.value.forEach((page) => {
page.style.outline = '';
});
selectedPages.value = [];
};
// Handle click in iframe
const handleIframeClick = (event) => {
const element = event.target;
@ -86,7 +105,19 @@ const handleIframeClick = (event) => {
// Check if clicking near a page edge
if (hoveredPage.value) {
event.stopPropagation();
pagePopup.value.open(hoveredPage.value, event);
// Clear previous selection
clearSelectedPages();
// Get all pages with same template and highlight them
const doc = event.target.ownerDocument;
const sameTemplatePages = getPagesWithSameTemplate(hoveredPage.value, doc);
sameTemplatePages.forEach((page) => {
page.style.outline = `2px solid ${PAGE_HIGHLIGHT_COLOR}`;
});
selectedPages.value = sameTemplatePages;
pagePopup.value.open(hoveredPage.value, event, sameTemplatePages.length);
elementPopup.value.close();
return;
}
@ -94,15 +125,22 @@ const handleIframeClick = (event) => {
// Only show popup for elements inside the page template
const isInsidePage = element.closest('.pagedjs_page');
if (!isInsidePage) {
clearSelectedPages();
elementPopup.value.close();
pagePopup.value.close();
return;
}
clearSelectedPages();
elementPopup.value.handleIframeClick(event);
pagePopup.value.close();
};
// Expose clearSelectedPages for PagePopup to call when closing
const handlePagePopupClose = () => {
clearSelectedPages();
};
const renderPreview = async (shouldReloadFromFile = false) => {
if (isTransitioning.value) return;
isTransitioning.value = true;
@ -228,7 +266,7 @@ onMounted(() => renderPreview(true));
<PreviewLoader :isLoading="isTransitioning" :shifted="activeTab.length > 0" />
<ElementPopup ref="elementPopup" :iframeRef="activeFrame" />
<PagePopup ref="pagePopup" :iframeRef="activeFrame" />
<PagePopup ref="pagePopup" :iframeRef="activeFrame" @close="handlePagePopupClose" />
</template>
<style>