From 5291c8637760a681fd06a5ebedf098b3816ee5e6 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 19 Apr 2026 22:04:08 +0530 Subject: [PATCH 01/22] fix: revert background color transparent fix --- src/extensionsIntegrated/Phoenix-live-preview/live-preview.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index ecb403319d..aab21a981a 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -27,7 +27,7 @@ #panel-live-preview-frame, #panel-md-preview-frame { - background-color: transparent; + background-color: white; position: relative; } From 2b3201b15e14b11ef9881875890c7507ebef2def Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 19 Apr 2026 22:43:26 +0530 Subject: [PATCH 02/22] refactor: better resize ruler dialog string --- src/nls/root/strings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 0bc4d69f2b..5536c86cc0 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -523,7 +523,7 @@ define({ "LIVE_DEV_IMAGE_FOLDER_DIALOG_HELP": "💡 Type folder path or leave empty to download in 'images' folder.", "LIVE_DEV_IMAGE_FOLDER_DIALOG_REMEMBER": "Don't ask again for this project", "AVAILABLE_IN_PRO_TITLE": "Available in Phoenix Pro", - "DEVICE_SIZE_LIMIT_MESSAGE": "Phoenix Pro lets you preview your page at the screen sizes defined in your CSS.", + "DEVICE_SIZE_LIMIT_MESSAGE": "See how your page looks on phones, tablets, desktops, and your CSS breakpoints. Upgrade to Phoenix Pro.", "MD_EDIT_UPSELL_MESSAGE": "Write Markdown like a document. {APP_NAME} handles the formatting so you can stay focused on writing.", "IMAGE_UPLOADING": "Uploading", "IMAGE_UPLOAD_FAILED": "Failed to upload image", From 12fa2683bee183fff1eace8917b4003abf3f1e55 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 19 Apr 2026 23:27:28 +0530 Subject: [PATCH 03/22] feat: add tooltip for disabled options in resize ruler --- .../Phoenix-live-preview/live-preview.css | 4 ---- src/nls/root/strings.js | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index aab21a981a..9f82ec84a2 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -155,10 +155,6 @@ opacity: 0.5; } -.device-size-item-disabled { - opacity: 0.35; -} - .device-size-item-breakpoint-icon { margin-right: 6px; width: 12px; diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 5536c86cc0..f8214966b8 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -524,6 +524,7 @@ define({ "LIVE_DEV_IMAGE_FOLDER_DIALOG_REMEMBER": "Don't ask again for this project", "AVAILABLE_IN_PRO_TITLE": "Available in Phoenix Pro", "DEVICE_SIZE_LIMIT_MESSAGE": "See how your page looks on phones, tablets, desktops, and your CSS breakpoints. Upgrade to Phoenix Pro.", + "DEVICE_SIZE_NOT_ENOUGH_SPACE": "Not enough space in the editor window for this screen size. Try zooming out.", "MD_EDIT_UPSELL_MESSAGE": "Write Markdown like a document. {APP_NAME} handles the formatting so you can stay focused on writing.", "IMAGE_UPLOADING": "Uploading", "IMAGE_UPLOAD_FAILED": "Failed to upload image", From 516e3423841cb043eb889f2c78767501464b24e9 Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 20 Apr 2026 17:58:52 +0530 Subject: [PATCH 04/22] feat: add toggle support in the live preview resize ruler feature --- .../Phoenix-live-preview/live-preview.css | 55 ++++++++++++++++--- src/nls/root/strings.js | 2 + 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index 9f82ec84a2..a8b8352256 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -109,31 +109,68 @@ margin-top: 0; } +.lp-device-size-btn-group { + display: flex; + align-items: center; + flex-shrink: 0; + margin: 0 4px 0 3px; + border: 1px solid transparent; + border-radius: 3px; + box-sizing: border-box; +} + +.lp-device-size-btn-group:hover { + border-color: rgba(255, 255, 255, 0.1); +} + .lp-device-size-icon { min-width: fit-content; display: flex; align-items: center; - margin: 0 4px 0 3px; cursor: pointer; background: transparent; - box-shadow: none; - border: 1px solid transparent; - box-sizing: border-box; + box-shadow: none !important; + border: none; color: #a0a0a0; padding: 0 0.35em; + margin: 0; } .lp-device-size-icon:hover, .lp-device-size-icon:focus, .lp-device-size-icon:active { - background: transparent !important; - border: 1px solid rgba(255, 255, 255, 0.1) !important; + background: rgba(255, 255, 255, 0.06) !important; + border: none !important; box-shadow: none !important; } -#deviceSizeBtn.btn-dropdown::after { - position: static; - margin-left: 5px; +.lp-device-size-dropdown-chevron { + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + background: transparent; + box-shadow: none !important; + border: none; + border-left: 1px solid transparent; + color: #a0a0a0; + padding: 0 4px; + margin: 0; + height: 22px; + font-size: 10px; +} + +.lp-device-size-btn-group:hover .lp-device-size-dropdown-chevron { + border-left-color: rgba(255, 255, 255, 0.1); +} + +.lp-device-size-dropdown-chevron:hover, +.lp-device-size-dropdown-chevron:focus, +.lp-device-size-dropdown-chevron:active { + background: rgba(255, 255, 255, 0.06) !important; + border: none !important; + border-left: 1px solid rgba(255, 255, 255, 0.1) !important; + box-shadow: none !important; } .device-size-item-icon { diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index f8214966b8..2d6221ddb3 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -525,6 +525,8 @@ define({ "AVAILABLE_IN_PRO_TITLE": "Available in Phoenix Pro", "DEVICE_SIZE_LIMIT_MESSAGE": "See how your page looks on phones, tablets, desktops, and your CSS breakpoints. Upgrade to Phoenix Pro.", "DEVICE_SIZE_NOT_ENOUGH_SPACE": "Not enough space in the editor window for this screen size. Try zooming out.", + "DEVICE_SIZE_CYCLE_TOOLTIP": "Switch between mobile, tablet, and desktop", + "DEVICE_SIZE_DROPDOWN_TOOLTIP": "All device sizes", "MD_EDIT_UPSELL_MESSAGE": "Write Markdown like a document. {APP_NAME} handles the formatting so you can stay focused on writing.", "IMAGE_UPLOADING": "Uploading", "IMAGE_UPLOAD_FAILED": "Failed to upload image", From e5e3e01a130550d99e2bbd86d3fe09a141680ada Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 20 Apr 2026 18:39:34 +0530 Subject: [PATCH 05/22] fix: better styling for the resize ruler button in the toolbar --- .../Phoenix-live-preview/live-preview.css | 10 +++++----- src/nls/root/strings.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index a8b8352256..563bc37873 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -5,7 +5,7 @@ .live-preview-browser-btn { opacity: 0; visibility: hidden; - transition: opacity 1s, visibility 0s linear 1s; /* Fade-out effect */ + transition: opacity 1s, visibility 0s linear 1s; } #live-preview-plugin-toolbar { @@ -101,7 +101,7 @@ opacity: 0; color: #a0a0a0; visibility: hidden; - transition: opacity 1s, visibility 0s linear 1s; /* Fade-out effect */ + transition: opacity 1s, visibility 0s linear 1s; width: 30px; height: 22px; padding: 1px 6px; @@ -124,15 +124,16 @@ } .lp-device-size-icon { - min-width: fit-content; display: flex; align-items: center; + justify-content: center; + width: 20px; cursor: pointer; background: transparent; box-shadow: none !important; border: none; color: #a0a0a0; - padding: 0 0.35em; + padding: 0; margin: 0; } @@ -292,7 +293,6 @@ color: #fff; } -/* Persistent cursor-sync highlight on CM line corresponding to md viewer cursor */ .cm-cursor-sync-highlight { background-color: rgba(100, 150, 255, 0.18) !important; } diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 2d6221ddb3..a862b37621 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -524,7 +524,7 @@ define({ "LIVE_DEV_IMAGE_FOLDER_DIALOG_REMEMBER": "Don't ask again for this project", "AVAILABLE_IN_PRO_TITLE": "Available in Phoenix Pro", "DEVICE_SIZE_LIMIT_MESSAGE": "See how your page looks on phones, tablets, desktops, and your CSS breakpoints. Upgrade to Phoenix Pro.", - "DEVICE_SIZE_NOT_ENOUGH_SPACE": "Not enough space in the editor window for this screen size. Try zooming out.", + "DEVICE_SIZE_NOT_ENOUGH_SPACE": "Not enough space for this screen size - try zooming out", "DEVICE_SIZE_CYCLE_TOOLTIP": "Switch between mobile, tablet, and desktop", "DEVICE_SIZE_DROPDOWN_TOOLTIP": "All device sizes", "MD_EDIT_UPSELL_MESSAGE": "Write Markdown like a document. {APP_NAME} handles the formatting so you can stay focused on writing.", From 55a249bfb0e458c6596bef424017f99948e12d73 Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 20 Apr 2026 23:18:51 +0530 Subject: [PATCH 06/22] feat: auto collapse sidebar if needed to fit live preview --- src/view/WorkspaceManager.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/view/WorkspaceManager.js b/src/view/WorkspaceManager.js index 77b2239975..1743d32f5b 100644 --- a/src/view/WorkspaceManager.js +++ b/src/view/WorkspaceManager.js @@ -204,7 +204,7 @@ define(function (require, exports, module) { // Floor the toolbar's maxsize at its minimum width. Without the floor, a narrow // window with a wide sidebar can drive the cap below 10px, and Resizer's drag // logic would then squeeze the toolbar to zero and hide it. - var rawMax = Math.min(window.innerWidth * 0.75, window.innerWidth - sidebarWidth - 100); + var rawMax = window.innerWidth - sidebarWidth - 100; $mainToolbar.data("maxsize", Math.max(minToolbarWidth, rawMax)); } @@ -570,7 +570,7 @@ define(function (require, exports, module) { let minToolbarWidth = (panelBeingShown.minWidth || 0) + pluginIconsBarWidth; let maxToolbarWidth = Math.max( minToolbarWidth, - Math.min(window.innerWidth * 0.75, window.innerWidth - sidebarWidth - 100) + window.innerWidth - sidebarWidth - 100 ); let currentWidth = $mainToolbar.width(); if (currentWidth > maxToolbarWidth || currentWidth < minToolbarWidth) { @@ -675,7 +675,8 @@ define(function (require, exports, module) { /** * Programmatically sets the plugin panel content width to the given value in pixels. * The total toolbar width is adjusted to account for the plugin icons bar. - * Width is clamped to respect panel minWidth and max size (75% of window). + * If the requested width doesn't fit, the sidebar is progressively shrunk + * (and collapsed if necessary) before clamping. * No-op if no panel is currently visible. * @param {number} width Desired content width in pixels */ @@ -686,11 +687,31 @@ define(function (require, exports, module) { var pluginIconsBarWidth = $pluginIconsBar.outerWidth(); var newToolbarWidth = width + pluginIconsBarWidth; - // Respect min/max constraints var minSize = currentlyShownPanel.minWidth || 0; var minToolbarWidth = minSize + pluginIconsBarWidth; var sidebarWidth = _getSidebarWidth(); - var maxToolbarWidth = Math.min(window.innerWidth * 0.75, window.innerWidth - sidebarWidth - 100); + var maxToolbarWidth = window.innerWidth - sidebarWidth - MIN_EDITOR_WIDTH; + + if (newToolbarWidth > maxToolbarWidth && sidebarWidth > 0) { + var $sb = $("#sidebar"); + var deficit = newToolbarWidth - maxToolbarWidth; + var newSidebarWidth = sidebarWidth - deficit; + + if (newSidebarWidth >= MIN_SIDEBAR_WIDTH) { + $sb.width(newSidebarWidth); + var resync = $sb.data("resyncSizer"); + if (typeof resync === "function") { + resync(); + } + $sb.trigger("panelResizeUpdate", [newSidebarWidth]); + $sb.trigger("panelResizeEnd", [newSidebarWidth]); + } else { + Resizer.hide($sb[0]); + } + sidebarWidth = _getSidebarWidth(); + maxToolbarWidth = window.innerWidth - sidebarWidth - MIN_EDITOR_WIDTH; + } + newToolbarWidth = Math.max(newToolbarWidth, minToolbarWidth); newToolbarWidth = Math.min(newToolbarWidth, maxToolbarWidth); From 9b3847fcaebda5c0934996ac328b34e31712f831 Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 20 Apr 2026 23:39:51 +0530 Subject: [PATCH 07/22] feat: add responsive handles live preview css --- .../Phoenix-live-preview/live-preview.css | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index 563bc37873..f8661c024b 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -50,6 +50,48 @@ height: calc(100% - var(--toolbar-height)); } +.frame-container.responsive-viewport { + justify-content: center; + align-items: stretch; + background: #1a1a1e; +} + +.frame-container.responsive-viewport > div:first-child:not(.responsive-handle) { + display: none; +} + +.responsive-handle { + width: 6px; + cursor: ew-resize; + background: transparent; + flex-shrink: 0; + position: relative; + z-index: 5; + transition: background 0.15s; +} + +.responsive-handle:hover, +.responsive-handle.dragging { + background: rgba(66, 133, 244, 0.5); +} + +.responsive-handle::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 2px; + height: 24px; + border-radius: 1px; + background: rgba(255, 255, 255, 0.25); +} + +.responsive-handle:hover::after, +.responsive-handle.dragging::after { + background: rgba(255, 255, 255, 0.6); +} + .plugin-toolbar { height: var(--toolbar-height); color: #a0a0a0; From 05b42651ae200e3d63fcb8030b6736f24d525b2b Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 21 Apr 2026 00:16:35 +0530 Subject: [PATCH 08/22] feat: add support for vertical resizing in design mode --- .../Phoenix-live-preview/live-preview.css | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index f8661c024b..27080882f3 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -51,6 +51,7 @@ } .frame-container.responsive-viewport { + position: relative; justify-content: center; align-items: stretch; background: #1a1a1e; @@ -61,11 +62,8 @@ } .responsive-handle { - width: 6px; - cursor: ew-resize; background: transparent; flex-shrink: 0; - position: relative; z-index: 5; transition: background 0.15s; } @@ -75,7 +73,13 @@ background: rgba(66, 133, 244, 0.5); } -.responsive-handle::after { +.responsive-handle-horizontal { + width: 6px; + cursor: ew-resize; + position: relative; +} + +.responsive-handle-horizontal::after { content: ''; position: absolute; top: 50%; @@ -87,8 +91,31 @@ background: rgba(255, 255, 255, 0.25); } -.responsive-handle:hover::after, -.responsive-handle.dragging::after { +.responsive-handle-horizontal:hover::after, +.responsive-handle-horizontal.dragging::after { + background: rgba(255, 255, 255, 0.6); +} + +.responsive-handle-vertical { + position: absolute; + height: 6px; + cursor: ns-resize; +} + +.responsive-handle-vertical::after { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 24px; + height: 2px; + border-radius: 1px; + background: rgba(255, 255, 255, 0.25); +} + +.responsive-handle-vertical:hover::after, +.responsive-handle-vertical.dragging::after { background: rgba(255, 255, 255, 0.6); } From 012c9cde36e760f605c8c8c46c724120d74e3e7c Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 21 Apr 2026 01:20:18 +0530 Subject: [PATCH 09/22] feat: add fit to panel button after resizing in design mode --- .../Phoenix-live-preview/live-preview.css | 18 ++++++++++++++++++ src/nls/root/strings.js | 1 + 2 files changed, 19 insertions(+) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index 27080882f3..f7f703f73a 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -178,6 +178,24 @@ margin-top: 0; } +.lp-fit-to-panel-btn { + color: #a0a0a0; + flex-shrink: 0; + margin: 0 2px; + background: transparent; + border: 1px solid transparent; + box-shadow: none; + font-size: 12px; +} + +.lp-fit-to-panel-btn:hover, +.lp-fit-to-panel-btn:focus, +.lp-fit-to-panel-btn:active { + background: transparent !important; + border: 1px solid rgba(255, 255, 255, 0.1) !important; + box-shadow: none !important; +} + .lp-device-size-btn-group { display: flex; align-items: center; diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index a862b37621..603fa3fc09 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -527,6 +527,7 @@ define({ "DEVICE_SIZE_NOT_ENOUGH_SPACE": "Not enough space for this screen size - try zooming out", "DEVICE_SIZE_CYCLE_TOOLTIP": "Switch between mobile, tablet, and desktop", "DEVICE_SIZE_DROPDOWN_TOOLTIP": "All device sizes", + "DEVICE_SIZE_FIT_TO_PANEL": "Fit to panel", "MD_EDIT_UPSELL_MESSAGE": "Write Markdown like a document. {APP_NAME} handles the formatting so you can stay focused on writing.", "IMAGE_UPLOADING": "Uploading", "IMAGE_UPLOAD_FAILED": "Failed to upload image", From 20ebe6b380d5ce69a70273023151180273b3f9e5 Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 21 Apr 2026 12:36:01 +0530 Subject: [PATCH 10/22] chore: auto update API docs --- docs/API-Reference/view/WorkspaceManager.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/API-Reference/view/WorkspaceManager.md b/docs/API-Reference/view/WorkspaceManager.md index 98a49cc6f5..bb0c11ed12 100644 --- a/docs/API-Reference/view/WorkspaceManager.md +++ b/docs/API-Reference/view/WorkspaceManager.md @@ -190,7 +190,8 @@ Returns true if visible else false. ### view/WorkspaceManager.setPluginPanelWidth(width) Programmatically sets the plugin panel content width to the given value in pixels. The total toolbar width is adjusted to account for the plugin icons bar. -Width is clamped to respect panel minWidth and max size (75% of window). +If the requested width doesn't fit, the sidebar is progressively shrunk +(and collapsed if necessary) before clamping. No-op if no panel is currently visible. **Kind**: inner method of [view/WorkspaceManager](#module_view/WorkspaceManager) From 8d08085095ceb23122651ef22f29ec835a0ffa42 Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 21 Apr 2026 13:35:50 +0530 Subject: [PATCH 11/22] feat: show pixel values when resizing the webpage --- .../Phoenix-live-preview/live-preview.css | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index f7f703f73a..ea53d5e1f8 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -119,6 +119,27 @@ background: rgba(255, 255, 255, 0.6); } +.responsive-dimension-label { + position: absolute; + transform: translateX(-50%); + z-index: 10; + display: none; + padding: 4px 12px; + border-radius: 4px; + background: rgba(0, 0, 0, 0.82); + border: 1px solid rgba(255, 255, 255, 0.15); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + color: #fff; + font-size: 13px; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; + white-space: nowrap; + pointer-events: none; + letter-spacing: 0.4px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5); +} + .plugin-toolbar { height: var(--toolbar-height); color: #a0a0a0; From d97299b6e63afe468522e4357c7512a660a4f3d9 Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 21 Apr 2026 15:29:04 +0530 Subject: [PATCH 12/22] feat: better resize handles styling --- .../Phoenix-live-preview/live-preview.css | 63 ++++++++++++++----- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index ea53d5e1f8..af278eebad 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -62,61 +62,92 @@ } .responsive-handle { - background: transparent; flex-shrink: 0; z-index: 5; + background: transparent; transition: background 0.15s; } .responsive-handle:hover, .responsive-handle.dragging { - background: rgba(66, 133, 244, 0.5); + background: rgba(255, 255, 255, 0.08); } .responsive-handle-horizontal { - width: 6px; + width: 10px; cursor: ew-resize; position: relative; } +.responsive-handle-horizontal::before, .responsive-handle-horizontal::after { content: ''; position: absolute; top: 50%; left: 50%; - transform: translate(-50%, -50%); - width: 2px; - height: 24px; - border-radius: 1px; - background: rgba(255, 255, 255, 0.25); + width: 1px; + height: 16px; + border-radius: 0.5px; + background: rgba(255, 255, 255, 0.3); +} + +.responsive-handle-horizontal::before { + transform: translate(calc(-50% - 2px), -50%); +} + +.responsive-handle-horizontal::after { + transform: translate(calc(-50% + 2px), -50%); } +.responsive-handle-horizontal:hover::before, .responsive-handle-horizontal:hover::after, +.responsive-handle-horizontal.dragging::before, .responsive-handle-horizontal.dragging::after { - background: rgba(255, 255, 255, 0.6); + background: rgba(255, 255, 255, 0.7); +} + +.responsive-handle-left { + opacity: 0; + transition: opacity 0.2s; +} + +.responsive-handle-left:hover, +.responsive-handle-left.dragging { + opacity: 1; } .responsive-handle-vertical { position: absolute; - height: 6px; + height: 10px; cursor: ns-resize; + box-sizing: border-box; } +.responsive-handle-vertical::before, .responsive-handle-vertical::after { content: ''; position: absolute; top: 50%; left: 50%; - transform: translate(-50%, -50%); - width: 24px; - height: 2px; - border-radius: 1px; - background: rgba(255, 255, 255, 0.25); + width: 16px; + height: 1px; + border-radius: 0.5px; + background: rgba(255, 255, 255, 0.3); +} + +.responsive-handle-vertical::before { + transform: translate(-50%, calc(-50% - 2px)); +} + +.responsive-handle-vertical::after { + transform: translate(-50%, calc(-50% + 2px)); } +.responsive-handle-vertical:hover::before, .responsive-handle-vertical:hover::after, +.responsive-handle-vertical.dragging::before, .responsive-handle-vertical.dragging::after { - background: rgba(255, 255, 255, 0.6); + background: rgba(255, 255, 255, 0.7); } .responsive-dimension-label { From b80f1da7efb2996e360195dc03373849ce6e6e9b Mon Sep 17 00:00:00 2001 From: Pluto Date: Tue, 21 Apr 2026 15:32:44 +0530 Subject: [PATCH 13/22] build: update pro deps --- tracking-repos.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracking-repos.json b/tracking-repos.json index e555dba242..2f81c3ed31 100644 --- a/tracking-repos.json +++ b/tracking-repos.json @@ -1,5 +1,5 @@ { "phoenixPro": { - "commitID": "59e1d73841f94f546ad9b62a76217eb0a1e450e8" + "commitID": "0bb0ed293e70501363fa3cd9916319ea1dbf38bb" } } From 5b1519be8f4838ff2f99203e790d462010f35df8 Mon Sep 17 00:00:00 2001 From: Pluto Date: Wed, 22 Apr 2026 12:33:25 +0530 Subject: [PATCH 14/22] feat: better live preview toolbar buttons styling --- .../Phoenix-live-preview/live-preview.css | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index af278eebad..29e831d0b5 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -182,10 +182,30 @@ .toolbar-button { background-color: transparent; - width:28px; + width: 28px; height: 22px; } +#live-preview-plugin-toolbar .btn-alt-quiet:hover, +#live-preview-plugin-toolbar .btn-alt-quiet:focus, +#live-preview-plugin-toolbar .btn-alt-quiet:active { + border-color: rgba(255, 255, 255, 0.1) !important; + box-shadow: none !important; +} + +#live-preview-plugin-toolbar .lp-device-size-icon:hover, +#live-preview-plugin-toolbar .lp-device-size-icon:focus, +#live-preview-plugin-toolbar .lp-device-size-icon:active { + border: none !important; +} + +#live-preview-plugin-toolbar .lp-device-size-dropdown-chevron:hover, +#live-preview-plugin-toolbar .lp-device-size-dropdown-chevron:focus, +#live-preview-plugin-toolbar .lp-device-size-dropdown-chevron:active { + border: none !important; + border-left: 1px solid rgba(255, 255, 255, 0.1) !important; +} + .open-icon { background: url("./images/sprites.svg#open-icon") no-repeat 72.5%; width: 30px; @@ -279,7 +299,7 @@ .lp-device-size-icon:hover, .lp-device-size-icon:focus, .lp-device-size-icon:active { - background: rgba(255, 255, 255, 0.06) !important; + background: transparent !important; border: none !important; box-shadow: none !important; } @@ -293,6 +313,7 @@ box-shadow: none !important; border: none; border-left: 1px solid transparent; + border-radius: 0 3px 3px 0; color: #a0a0a0; padding: 0 4px; margin: 0; @@ -307,7 +328,7 @@ .lp-device-size-dropdown-chevron:hover, .lp-device-size-dropdown-chevron:focus, .lp-device-size-dropdown-chevron:active { - background: rgba(255, 255, 255, 0.06) !important; + background: transparent !important; border: none !important; border-left: 1px solid rgba(255, 255, 255, 0.1) !important; box-shadow: none !important; From 42660a289f9af66433b83eaeb9944ca39f7070cc Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 24 Apr 2026 00:45:06 +0530 Subject: [PATCH 15/22] feat: use expand compress icons for the bottom panel --- src/view/PanelView.js | 8 ++++---- src/view/WorkspaceManager.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/view/PanelView.js b/src/view/PanelView.js index 0c6f8e0dd3..2696bd44df 100644 --- a/src/view/PanelView.js +++ b/src/view/PanelView.js @@ -990,12 +990,12 @@ define(function (require, exports, module) { let $btn = _$tabBar.find(".bottom-panel-maximize-btn"); let $icon = $btn.find("i"); if (_isMaximized) { - $icon.removeClass("fa-regular fa-square") - .addClass("fa-regular fa-window-restore"); + $icon.removeClass("fa-solid fa-expand") + .addClass("fa-solid fa-compress"); $btn.attr("title", Strings.BOTTOM_PANEL_RESTORE); } else { - $icon.removeClass("fa-regular fa-window-restore") - .addClass("fa-regular fa-square"); + $icon.removeClass("fa-solid fa-compress") + .addClass("fa-solid fa-expand"); $btn.attr("title", Strings.BOTTOM_PANEL_MAXIMIZE); } } diff --git a/src/view/WorkspaceManager.js b/src/view/WorkspaceManager.js index 1743d32f5b..de4ca2b8c3 100644 --- a/src/view/WorkspaceManager.js +++ b/src/view/WorkspaceManager.js @@ -420,7 +420,7 @@ define(function (require, exports, module) { .attr('title', Strings.BOTTOM_PANEL_MINIMIZE) ); $tabBarActions.append( - $('') + $('') .attr('title', Strings.BOTTOM_PANEL_MAXIMIZE) ); $bottomPanelTabBar.append($bottomPanelTabsOverflow); From d7adccb3e17e481ed90e8c05b658c11e3393aa7b Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 24 Apr 2026 01:45:23 +0530 Subject: [PATCH 16/22] feat: quick access tab always shown on first --- src/nls/root/strings.js | 2 +- src/styles/Extn-BottomPanelTabs.less | 43 ++------- src/view/DefaultPanelView.js | 6 +- src/view/PanelView.js | 127 ++++++++++++--------------- 4 files changed, 67 insertions(+), 111 deletions(-) diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 603fa3fc09..5b6d4d76fe 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -1561,7 +1561,7 @@ define({ "BOTTOM_PANEL_MINIMIZE": "Minimize Panel", "BOTTOM_PANEL_SHOW": "Show Bottom Panel", "BOTTOM_PANEL_HIDE_TOGGLE": "Hide Bottom Panel", - "BOTTOM_PANEL_DEFAULT_TITLE": "Tools", + "BOTTOM_PANEL_DEFAULT_TITLE": "Quick Access", "BOTTOM_PANEL_DEFAULT_HEADING": "Open a Panel", "BOTTOM_PANEL_OPEN_PANEL": "Open a Panel", "BOTTOM_PANEL_MAXIMIZE": "Maximize Panel", diff --git a/src/styles/Extn-BottomPanelTabs.less b/src/styles/Extn-BottomPanelTabs.less index f81bd6988b..839a408620 100644 --- a/src/styles/Extn-BottomPanelTabs.less +++ b/src/styles/Extn-BottomPanelTabs.less @@ -237,8 +237,7 @@ /* Fix all collapsed tabs to the same width so the UI doesn't shake when switching active tab. The width matches the active tab's natural content (icon + close button) using fixed px since the - icon has a fixed size. The Tools button (.bottom-panel-add-btn) - is a separate element and keeps its natural "Tools" text width. */ + icon has a fixed size. */ .bottom-panel-tab { min-width: 63px; box-sizing: border-box; @@ -247,7 +246,7 @@ .bottom-panel-tab:not(.active) .bottom-panel-tab-close-btn { display: none; } - /* Default panel (Tools) tab: keep natural width and show its title + /* Pinned Quick Access tab: keep natural width and show its title even in collapsed mode (other tabs collapse to icon-only). */ .bottom-panel-tab.bottom-panel-tab-default { min-width: auto; @@ -304,42 +303,14 @@ } } -.bottom-panel-add-btn { - display: flex; - align-items: center; - justify-content: center; - padding: 0 10px; - height: 2rem; - min-width: 70px; - line-height: 2rem; - cursor: pointer; - color: #888; - font-size: 0.82rem; - flex: 0 0 auto; - white-space: nowrap; - user-select: none; - -webkit-user-drag: none; - transition: color 0.12s ease, background-color 0.12s ease; - - img { - -webkit-user-drag: none; - pointer-events: none; - } +/* Pinned Quick Access tab: subtle separator to distinguish it from regular tabs */ +.bottom-panel-tab.bottom-panel-tab-default { + padding-right: 0.8rem; + border-right: 1px solid rgba(0, 0, 0, 0.15); .dark & { - color: #777; + border-right: 1px solid rgba(255, 255, 255, 0.1); } - - &:hover { - background-color: #e0e0e0; - color: #333; - - .dark & { - background-color: #333; - color: #eee; - } - } - } .bottom-panel-tab-bar-actions { diff --git a/src/view/DefaultPanelView.js b/src/view/DefaultPanelView.js index 07fc9d91b8..da4acd7944 100644 --- a/src/view/DefaultPanelView.js +++ b/src/view/DefaultPanelView.js @@ -198,11 +198,9 @@ define(function (require, exports, module) { } }); - // Auto-hide when any other panel is shown; update drawer button state. + // Update drawer button state when panels are shown. PanelView.on(PanelView.EVENT_PANEL_SHOWN, function (event, panelID) { - if (panelID !== WorkspaceManager.DEFAULT_PANEL_ID) { - _panel.hide(); - } else { + if (panelID === WorkspaceManager.DEFAULT_PANEL_ID) { _updateButtonVisibility(); } $drawerBtn.toggleClass("selected-button", panelID === WorkspaceManager.DEFAULT_PANEL_ID); diff --git a/src/view/PanelView.js b/src/view/PanelView.js index 2696bd44df..b3fdce9d74 100644 --- a/src/view/PanelView.js +++ b/src/view/PanelView.js @@ -108,9 +108,6 @@ define(function (require, exports, module) { /** @type {string|null} The default/quick-access panel ID */ let _defaultPanelId = null; - /** @type {jQueryObject} The "+" button inside the tab overflow area */ - let _$addBtn = null; - // --- Tab helper functions --- /** @@ -149,7 +146,7 @@ define(function (require, exports, module) { */ function _buildTab(panel, isActive) { let title = panel._tabTitle || _getPanelTitle(panel.panelID, panel.$panel); - // Default panel (Tools) tab is not draggable — it's a fixed slot, not a user tab + // Default panel (Quick Access) tab is pinned — not draggable, not closable const isDefault = panel.panelID === _defaultPanelId; let $tab = $('
') .toggleClass('bottom-panel-tab-default', isDefault) @@ -163,7 +160,9 @@ define(function (require, exports, module) { $icon[0].style.webkitMaskImage = maskUrl; $tab.append($icon); $tab.append($('').text(title)); - $tab.append($('×').attr('title', Strings.CLOSE)); + if (!isDefault) { + $tab.append($('×').attr('title', Strings.CLOSE)); + } return $tab; } @@ -171,10 +170,6 @@ define(function (require, exports, module) { if (!_$tabsOverflow) { return; } - // Detach the add button before emptying to preserve its event handlers - if (_$addBtn) { - _$addBtn.detach(); - } _$tabsOverflow.empty(); _openIds.forEach(function (panelId) { @@ -185,11 +180,6 @@ define(function (require, exports, module) { _$tabsOverflow.append(_buildTab(panel, panelId === _activeId)); }); - // Re-append the Tools button at the end - if (_$addBtn) { - _$tabsOverflow.append(_$addBtn); - } - _updateAddButtonVisibility(); _checkTabOverflow(); } @@ -226,13 +216,7 @@ define(function (require, exports, module) { return; } let $tab = _buildTab(panel, panelId === _activeId); - // Insert before the Tools button so it stays at the end - if (_$addBtn && _$addBtn.parent().length) { - _$addBtn.before($tab); - } else { - _$tabsOverflow.append($tab); - } - _updateAddButtonVisibility(); + _$tabsOverflow.append($tab); _checkTabOverflow(); } @@ -247,7 +231,6 @@ define(function (require, exports, module) { return; } _$tabsOverflow.find('.bottom-panel-tab[data-panel-id="' + panelId + '"]').remove(); - _updateAddButtonVisibility(); _checkTabOverflow(); } @@ -311,7 +294,7 @@ define(function (require, exports, module) { if (!draggedTab || this === draggedTab) { return; } - // Don't allow dropping onto the default panel (Tools) tab + // Don't allow dropping onto the pinned Quick Access tab if ($(this).data("panel-id") === _defaultPanelId) { return; } @@ -319,7 +302,13 @@ define(function (require, exports, module) { e.originalEvent.dataTransfer.dropEffect = "move"; _$tabBar.find(".bottom-panel-tab").removeClass("drag-target"); $(this).addClass("drag-target"); - updateIndicator(this, getDropPosition(this, e.originalEvent.clientX)); + let insertBefore = getDropPosition(this, e.originalEvent.clientX); + // Can't insert before the first non-default tab (would go ahead of pinned tab) + const targetIdx = _openIds.indexOf($(this).data("panel-id")); + if (insertBefore && targetIdx <= 1) { + insertBefore = false; + } + updateIndicator(this, insertBefore); }); _$tabBar.on("dragleave", ".bottom-panel-tab", function (e) { @@ -350,6 +339,10 @@ define(function (require, exports, module) { if (!insertBefore) { newIdx++; } + // Never place a tab before the pinned Quick Access tab at index 0 + if (newIdx < 1 && _defaultPanelId && _openIds[0] === _defaultPanelId) { + newIdx = 1; + } _openIds.splice(newIdx, 0, draggedId); cleanup(); _updateBottomPanelTabBar(); @@ -503,23 +496,6 @@ define(function (require, exports, module) { }); } - /** - * Show or hide the "+" button based on whether the default panel is active. - * The button is hidden when the default panel is the active tab (since - * clicking "+" would be a no-op) and shown otherwise. - * @private - */ - function _updateAddButtonVisibility() { - if (!_$addBtn) { - return; - } - if (_defaultPanelId && _activeId === _defaultPanelId) { - _$addBtn.hide(); - } else { - _$addBtn.show(); - } - } - /** * Switch the active tab to the given panel. Does not show/hide the container. * @param {string} panelId @@ -543,7 +519,6 @@ define(function (require, exports, module) { newPanel.$panel.addClass("active-bottom-panel"); } _updateActiveTabHighlight(); - _updateAddButtonVisibility(); } @@ -567,6 +542,12 @@ define(function (require, exports, module) { this._tabTitle = _getPanelTitle(id, $panel, title); this._options = options || {}; _panelMap[id] = this; + + // Quick Access panel is pinned: always at index 0, always in the tab bar + if (id === _defaultPanelId && _openIds.indexOf(id) === -1) { + _openIds.unshift(id); + _addTabToBar(id); + } } /** @@ -666,8 +647,13 @@ define(function (require, exports, module) { exports.trigger(EVENT_PANEL_SHOWN, panelId); return; } - // Not open: add to open set - _openIds.push(panelId); + // Not open: add to open set. + // Quick Access panel is always pinned at index 0. + if (panelId === _defaultPanelId) { + _openIds.unshift(panelId); + } else { + _openIds.push(panelId); + } // Show container if it was hidden if (!_$container.is(":visible")) { @@ -684,9 +670,26 @@ define(function (require, exports, module) { */ Panel.prototype.hide = function () { let panelId = this.panelID; + + // Quick Access panel is pinned — it stays in _openIds and the tab bar. + // Hiding it collapses the bottom panel container entirely. + if (panelId === _defaultPanelId) { + if (_activeId !== panelId) { + return; + } + this.$panel.removeClass("active-bottom-panel"); + _activeId = null; + _updateActiveTabHighlight(); + if (_$container) { + restoreIfMaximized(); + Resizer.hide(_$container[0]); + } + exports.trigger(EVENT_PANEL_HIDDEN, panelId); + return; + } + let idx = _openIds.indexOf(panelId); if (idx === -1) { - // Not open - no-op return; } @@ -700,10 +703,9 @@ define(function (require, exports, module) { if (wasActive && _openIds.length > 0) { let nextIdx = Math.min(idx, _openIds.length - 1); activatedId = _openIds[nextIdx]; - _activeId = null; // clear so _switchToTab runs + _activeId = null; _switchToTab(activatedId); } else if (wasActive) { - // No more tabs - hide the container _activeId = null; if (_$container) { restoreIfMaximized(); @@ -713,10 +715,8 @@ define(function (require, exports, module) { _removeTabFromBar(panelId); - // Always fire HIDDEN for the closed panel first exports.trigger(EVENT_PANEL_HIDDEN, panelId); - // Then fire SHOWN for the newly activated tab, if any if (activatedId) { exports.trigger(EVENT_PANEL_SHOWN, activatedId); } @@ -793,18 +793,11 @@ define(function (require, exports, module) { _recomputeLayout = recomputeLayoutFn; _defaultPanelId = defaultPanelId; - // Create the "Tools" button inside the scrollable tabs area. - _$addBtn = $('' - + '' - + Strings.BOTTOM_PANEL_DEFAULT_TITLE + ''); - _$tabsOverflow.append(_$addBtn); - // Tab bar click handlers _$tabBar.on("click", ".bottom-panel-tab-close-btn", function (e) { e.stopPropagation(); let panelId = $(this).closest(".bottom-panel-tab").data("panel-id"); - if (panelId) { + if (panelId && panelId !== _defaultPanelId) { let panel = _panelMap[panelId]; if (panel) { panel.requestClose(); @@ -836,14 +829,6 @@ define(function (require, exports, module) { _showOverflowMenu(); }); - // "+" button opens the default/quick-access panel - _$addBtn.on("click", function (e) { - e.stopPropagation(); - if (_defaultPanelId && _panelMap[_defaultPanelId]) { - _panelMap[_defaultPanelId].show(); - } - }); - // Hide-panel button collapses the container but keeps tabs intact. // Maximize state is preserved so the panel re-opens maximized. _$tabBar.on("click", ".bottom-panel-hide-btn", function (e) { @@ -860,9 +845,8 @@ define(function (require, exports, module) { }); // Double-click on empty tab bar area toggles maximize. - // Exclude tabs themselves, action buttons, and the add button. _$tabBar.on("dblclick", function (e) { - if ($(e.target).closest(".bottom-panel-tab, .bottom-panel-tab-close-btn, .bottom-panel-hide-btn, .bottom-panel-maximize-btn, .bottom-panel-add-btn").length) { + if ($(e.target).closest(".bottom-panel-tab, .bottom-panel-tab-close-btn, .bottom-panel-hide-btn, .bottom-panel-maximize-btn").length) { return; } _toggleMaximize(); @@ -1088,7 +1072,12 @@ define(function (require, exports, module) { // Clear internal state BEFORE hiding the container so the // panelCollapsed handler sees an empty _openIds and doesn't // redundantly update the stacks. - _openIds = []; + // The Quick Access panel stays pinned at index 0. + if (_defaultPanelId) { + _openIds = [_defaultPanelId]; + } else { + _openIds = []; + } _activeId = null; if (_$container && _$container.is(":visible")) { @@ -1098,8 +1087,6 @@ define(function (require, exports, module) { _updateBottomPanelTabBar(); - // Fire one EVENT_PANEL_HIDDEN per panel for stack tracking. - // No intermediate EVENT_PANEL_SHOWN events are emitted. for (let i = 0; i < closedIds.length; i++) { exports.trigger(EVENT_PANEL_HIDDEN, closedIds[i]); } From 7ba715565530c4ef4a72e53a3de86ef4b37dcf2a Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 24 Apr 2026 01:52:51 +0530 Subject: [PATCH 17/22] feat: show only icon in the bottom panel quick access --- src/nls/root/strings.js | 2 +- src/styles/Extn-BottomPanelTabs.less | 22 +++++++++++----------- src/view/PanelView.js | 13 ++++++++++--- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 5b6d4d76fe..5e797fc578 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -1561,7 +1561,7 @@ define({ "BOTTOM_PANEL_MINIMIZE": "Minimize Panel", "BOTTOM_PANEL_SHOW": "Show Bottom Panel", "BOTTOM_PANEL_HIDE_TOGGLE": "Hide Bottom Panel", - "BOTTOM_PANEL_DEFAULT_TITLE": "Quick Access", + "BOTTOM_PANEL_DEFAULT_TITLE": "Quick Access - Tools", "BOTTOM_PANEL_DEFAULT_HEADING": "Open a Panel", "BOTTOM_PANEL_OPEN_PANEL": "Open a Panel", "BOTTOM_PANEL_MAXIMIZE": "Maximize Panel", diff --git a/src/styles/Extn-BottomPanelTabs.less b/src/styles/Extn-BottomPanelTabs.less index 839a408620..18fb29ec9c 100644 --- a/src/styles/Extn-BottomPanelTabs.less +++ b/src/styles/Extn-BottomPanelTabs.less @@ -166,11 +166,12 @@ display: none; } -/* Default panel (Tools) tab: always show the icon alongside the title, - in both expanded and collapsed modes, active or inactive. */ +/* Pinned Quick Access tab: icon-only, always visible */ .bottom-panel-tab.bottom-panel-tab-default .bottom-panel-tab-icon { display: inline-flex; - margin-right: 0.4rem; + width: 1.1rem; + height: 1.1rem; + margin: 0; } .default-panel-btn .panel-titlebar-icon { @@ -246,14 +247,9 @@ .bottom-panel-tab:not(.active) .bottom-panel-tab-close-btn { display: none; } - /* Pinned Quick Access tab: keep natural width and show its title - even in collapsed mode (other tabs collapse to icon-only). */ + /* Pinned Quick Access tab: icon-only, keeps its natural width */ .bottom-panel-tab.bottom-panel-tab-default { min-width: auto; - justify-content: flex-start; - } - .bottom-panel-tab.bottom-panel-tab-default .bottom-panel-tab-title { - display: inline; } } @@ -303,13 +299,17 @@ } } -/* Pinned Quick Access tab: subtle separator to distinguish it from regular tabs */ +/* Pinned Quick Access tab: icon-only with separator */ .bottom-panel-tab.bottom-panel-tab-default { - padding-right: 0.8rem; + padding: 0 0.6rem; + min-width: auto; + justify-content: center; border-right: 1px solid rgba(0, 0, 0, 0.15); + background-color: transparent; .dark & { border-right: 1px solid rgba(255, 255, 255, 0.1); + background-color: transparent; } } diff --git a/src/view/PanelView.js b/src/view/PanelView.js index b3fdce9d74..0409745b98 100644 --- a/src/view/PanelView.js +++ b/src/view/PanelView.js @@ -159,8 +159,11 @@ define(function (require, exports, module) { $icon[0].style.maskImage = maskUrl; $icon[0].style.webkitMaskImage = maskUrl; $tab.append($icon); - $tab.append($('').text(title)); - if (!isDefault) { + if (isDefault) { + // Icon-only tab with tooltip + $tab.attr('title', title); + } else { + $tab.append($('').text(title)); $tab.append($('×').attr('title', Strings.CLOSE)); } return $tab; @@ -391,9 +394,13 @@ define(function (require, exports, module) { _$overflowBtn.toggle(stillOverflowing); } - // Show tooltip on hover only in collapsed mode (title text is hidden) + // Show tooltip on hover only in collapsed mode (title text is hidden). + // The pinned Quick Access tab always keeps its tooltip (icon-only). _$tabBar.find(".bottom-panel-tab").each(function () { const $tab = $(this); + if ($tab.data("panel-id") === _defaultPanelId) { + return; + } if (isOverflowing) { $tab.attr("title", $tab.find(".bottom-panel-tab-title").text()); } else { From 35e5abe5b2fdcc7996c7a453423328fa98b131e9 Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 24 Apr 2026 02:03:03 +0530 Subject: [PATCH 18/22] feat: better drag drop support in bottom panel tabs --- src/view/PanelView.js | 109 ++++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 25 deletions(-) diff --git a/src/view/PanelView.js b/src/view/PanelView.js index 0409745b98..6e9dcf8001 100644 --- a/src/view/PanelView.js +++ b/src/view/PanelView.js @@ -277,8 +277,55 @@ define(function (require, exports, module) { _$tabBar.find(".bottom-panel-tab").removeClass("drag-target"); } + // Find the closest non-default, non-dragged tab to mouseX + function findNearestDropTarget(mouseX) { + let closest = null; + let closestDist = Infinity; + _$tabsOverflow.find(".bottom-panel-tab").each(function () { + if (this === draggedTab) { + return; + } + if ($(this).data("panel-id") === _defaultPanelId) { + return; + } + const rect = this.getBoundingClientRect(); + const dist = Math.min(Math.abs(mouseX - rect.left), Math.abs(mouseX - rect.right)); + if (dist < closestDist) { + closestDist = dist; + closest = this; + } + }); + return closest; + } + + // Perform the reorder in _openIds and rebuild the tab bar + function reorderTabs(targetEl, mouseX) { + if (!draggedTab || targetEl === draggedTab) { + return; + } + let draggedId = $(draggedTab).data("panel-id"); + let targetId = $(targetEl).data("panel-id"); + let fromIdx = _openIds.indexOf(draggedId); + let toIdx = _openIds.indexOf(targetId); + if (fromIdx === -1 || toIdx === -1) { + return; + } + const insertBefore = getDropPosition(targetEl, mouseX); + _openIds.splice(fromIdx, 1); + let newIdx = _openIds.indexOf(targetId); + if (!insertBefore) { + newIdx++; + } + // Never place a tab before the pinned Quick Access tab at index 0 + if (newIdx < 1 && _defaultPanelId && _openIds[0] === _defaultPanelId) { + newIdx = 1; + } + _openIds.splice(newIdx, 0, draggedId); + _updateBottomPanelTabBar(); + _updateActiveTabHighlight(); + } + _$tabBar.on("dragstart", ".bottom-panel-tab", function (e) { - // Default panel (Tools) tab is never draggable if ($(this).data("panel-id") === _defaultPanelId) { e.preventDefault(); return; @@ -297,7 +344,6 @@ define(function (require, exports, module) { if (!draggedTab || this === draggedTab) { return; } - // Don't allow dropping onto the pinned Quick Access tab if ($(this).data("panel-id") === _defaultPanelId) { return; } @@ -305,13 +351,31 @@ define(function (require, exports, module) { e.originalEvent.dataTransfer.dropEffect = "move"; _$tabBar.find(".bottom-panel-tab").removeClass("drag-target"); $(this).addClass("drag-target"); - let insertBefore = getDropPosition(this, e.originalEvent.clientX); - // Can't insert before the first non-default tab (would go ahead of pinned tab) - const targetIdx = _openIds.indexOf($(this).data("panel-id")); - if (insertBefore && targetIdx <= 1) { - insertBefore = false; + updateIndicator(this, getDropPosition(this, e.originalEvent.clientX)); + }); + + // Fallback dragover on the overflow container: handles gaps between + // tabs, empty space after the last tab, and the Quick Access tab area + // by snapping to the nearest valid drop target. + _$tabsOverflow.on("dragover", function (e) { + if (!draggedTab) { + return; + } + // Skip if already over a valid tab (the tab handler above covers it) + const $closestTab = $(e.target).closest(".bottom-panel-tab"); + if ($closestTab.length && $closestTab[0] !== draggedTab + && $closestTab.data("panel-id") !== _defaultPanelId) { + return; } - updateIndicator(this, insertBefore); + const nearest = findNearestDropTarget(e.originalEvent.clientX); + if (!nearest) { + return; + } + e.preventDefault(); + e.originalEvent.dataTransfer.dropEffect = "move"; + _$tabBar.find(".bottom-panel-tab").removeClass("drag-target"); + $(nearest).addClass("drag-target"); + updateIndicator(nearest, getDropPosition(nearest, e.originalEvent.clientX)); }); _$tabBar.on("dragleave", ".bottom-panel-tab", function (e) { @@ -328,28 +392,23 @@ define(function (require, exports, module) { cleanup(); return; } - let draggedId = $(draggedTab).data("panel-id"); - let targetId = $(this).data("panel-id"); - let fromIdx = _openIds.indexOf(draggedId); - let toIdx = _openIds.indexOf(targetId); - if (fromIdx === -1 || toIdx === -1) { + reorderTabs(this, e.originalEvent.clientX); + cleanup(); + }); + + // Fallback drop on the overflow container + _$tabsOverflow.on("drop", function (e) { + if (!draggedTab) { cleanup(); return; } - const insertBefore = getDropPosition(this, e.originalEvent.clientX); - _openIds.splice(fromIdx, 1); - let newIdx = _openIds.indexOf(targetId); - if (!insertBefore) { - newIdx++; - } - // Never place a tab before the pinned Quick Access tab at index 0 - if (newIdx < 1 && _defaultPanelId && _openIds[0] === _defaultPanelId) { - newIdx = 1; + const nearest = findNearestDropTarget(e.originalEvent.clientX); + if (nearest) { + e.preventDefault(); + e.stopPropagation(); + reorderTabs(nearest, e.originalEvent.clientX); } - _openIds.splice(newIdx, 0, draggedId); cleanup(); - _updateBottomPanelTabBar(); - _updateActiveTabHighlight(); }); } From 967b20babf73b66901c51498f6663dc45f99093d Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 24 Apr 2026 02:22:32 +0530 Subject: [PATCH 19/22] chore: update API docs --- docs/API-Reference/view/PanelView.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/API-Reference/view/PanelView.md b/docs/API-Reference/view/PanelView.md index 7a4455bcce..544969a668 100644 --- a/docs/API-Reference/view/PanelView.md +++ b/docs/API-Reference/view/PanelView.md @@ -68,12 +68,6 @@ recomputeLayout callback from WorkspaceManager ## \_defaultPanelId : string \| null The default/quick-access panel ID -**Kind**: global variable - - -## \_$addBtn : jQueryObject -The "+" button inside the tab overflow area - **Kind**: global variable From 625a4c58d5653ebece25fbe1f79632a019150731 Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 24 Apr 2026 12:35:25 +0530 Subject: [PATCH 20/22] fix: central control bar tests failing --- test/spec/CentralControlBar-integ-test.js | 26 +++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/test/spec/CentralControlBar-integ-test.js b/test/spec/CentralControlBar-integ-test.js index e2a10643de..104e3377f0 100644 --- a/test/spec/CentralControlBar-integ-test.js +++ b/test/spec/CentralControlBar-integ-test.js @@ -887,30 +887,38 @@ define(function (require, exports, module) { expect(Math.abs(mtRect.right - testWindow.innerWidth)).toBeLessThan(2); }); - it("should, in normal mode, resize only the plugin-panel (sidebar untouched) and respect the 75%/sidebar clamp", async function () { + it("should, in normal mode, progressively shrink the sidebar when an oversized plugin-panel width is requested", async function () { await openLivePreview(); const iconsW = _$("#plugin-icons-bar").outerWidth(); const sidebarBefore = _$("#sidebar")[0].offsetWidth; - // Request a very wide panel — should be clamped against 75% window - // and (window - sidebar - 100). Either way sidebar must stay put. + // Request a very wide panel — the sidebar should shrink (or + // collapse) to make room, then the toolbar is clamped to + // (window - finalSidebarWidth - MIN_EDITOR_WIDTH). const requested = testWindow.innerWidth; // intentionally over-large WorkspaceManager.setPluginPanelWidth(requested); await awaits(0); - expect(_$("#sidebar")[0].offsetWidth).toBe(sidebarBefore); + // Sidebar must have shrunk or collapsed to accommodate the request. + const sidebarAfter = SidebarView.isVisible() ? _$("#sidebar")[0].offsetWidth : 0; + expect(sidebarAfter).toBeLessThan(sidebarBefore); const toolbar = _$("#main-toolbar").outerWidth(); - const maxAllowed = Math.min( - testWindow.innerWidth * 0.75, - testWindow.innerWidth - sidebarBefore - 100 - ); - // Toolbar must honour the clamp (+iconsBar = the WSM math). + // Toolbar is clamped to (window - sidebar - MIN_EDITOR_WIDTH). + const maxAllowed = testWindow.innerWidth - sidebarAfter - 100; expect(toolbar).toBeLessThanOrEqual(maxAllowed + 3); // And at minimum it's the icons-bar + LP's minWidth. const lp = livePanel(); const minToolbar = (lp && lp.minWidth ? lp.minWidth : 0) + iconsW; expect(toolbar).toBeGreaterThanOrEqual(minToolbar); + + // Restore sidebar for subsequent tests. + if (!SidebarView.isVisible()) { + SidebarView.show(); + await awaitsFor(function () { return SidebarView.isVisible(); }, + "sidebar to come back", 2000); + } + SidebarView.resize(200); }); }); From 0db45a7ef6ddde4d66013adcb84834f4c79c6312 Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 24 Apr 2026 17:27:32 +0530 Subject: [PATCH 21/22] feat: improve live preview dimension label styles --- .../Phoenix-live-preview/live-preview.css | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index 29e831d0b5..88e1bd1b26 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -155,20 +155,20 @@ transform: translateX(-50%); z-index: 10; display: none; - padding: 4px 12px; - border-radius: 4px; - background: rgba(0, 0, 0, 0.82); - border: 1px solid rgba(255, 255, 255, 0.15); - backdrop-filter: blur(8px); - -webkit-backdrop-filter: blur(8px); + padding: 6px 16px; + border-radius: 6px; + background: rgba(0, 0, 0, 0.88); + border: 1px solid rgba(255, 255, 255, 0.18); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); color: #fff; - font-size: 13px; + font-size: 15px; font-weight: 600; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; white-space: nowrap; pointer-events: none; - letter-spacing: 0.4px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.5); + letter-spacing: 0.5px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.06); } .plugin-toolbar { From da6fa9e8b7dab679763d03e3b5a549e488f6e089 Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 24 Apr 2026 17:39:03 +0530 Subject: [PATCH 22/22] refactor: live preview device size dropdown colors --- .../Phoenix-live-preview/live-preview.css | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index 88e1bd1b26..8c72ac0fbc 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -336,8 +336,6 @@ .device-size-item-icon { margin-right: 6px; - width: 12px; - text-align: center; font-size: inherit; } @@ -350,13 +348,12 @@ .device-size-item-width { margin-left: 10px; - opacity: 0.5; + color: #9a9a9a; + font-size: 12.5px; } .device-size-item-breakpoint-icon { margin-right: 6px; - width: 12px; - text-align: center; font-size: inherit; color: rgba(100, 180, 255, 0.8); }