From 6ffb2ed2d622357352bb94f427c9a32846208dcd Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 24 Aug 2026 00:41:02 +0530 Subject: [PATCH 1/6] feat: add live preview full screen state to WorkspaceManager Full screen means the editor is collapsed and the sidebar is hidden, so live preview owns everything to the right of the central control bar. Modelled as a superset of design mode rather than a third independent mode: isInDesignMode() stays true while full screen is active. That way every existing design mode check keeps its meaning and needs no change, including the auto exit hooks in find in files, the tools drawer and quick open, and the responsive sizing in phoenix-pro. Adds isInLPFullScreen() / setLPFullScreen(), the matching change event, the toggle command id and the strings. The control bar owns the actual state and is the only thing that should call setLPFullScreen(). --- src/command/Commands.js | 3 +++ src/nls/root/strings.js | 3 +++ src/view/WorkspaceManager.js | 42 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/src/command/Commands.js b/src/command/Commands.js index b2586a1656..11a39c1ed4 100644 --- a/src/command/Commands.js +++ b/src/command/Commands.js @@ -260,6 +260,9 @@ define(function (require, exports, module) { /** Toggles the design (full live-preview) mode — collapses/expands the editor */ exports.VIEW_TOGGLE_DESIGN_MODE = "view.toggleDesignMode"; // view/CentralControlBar.js _setEditorCollapsed() + /** Toggles live-preview full screen (design mode with the sidebar hidden) */ + exports.VIEW_TOGGLE_LP_FULL_SCREEN = "view.toggleLivePreviewFullScreen"; // view/CentralControlBar.js _setLPFullScreen() + /** Toggles tabbar visibility */ exports.TOGGLE_TABBAR = "view.toggleTabbar"; // extensionsIntegrated/TabBar/main.js diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 704cad2a44..08b8a9eeac 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -1198,6 +1198,9 @@ define({ "CMD_TOGGLE_DESIGN_MODE": "Toggle Design Mode", "CCB_SWITCH_TO_DESIGN_MODE": "Switch to Design Mode", "CCB_SWITCH_TO_CODE_EDITOR": "Switch to Code Editor", + "CMD_TOGGLE_LP_FULL_SCREEN": "Toggle Live Preview Full Screen", + "LIVE_PREVIEW_FULL_SCREEN": "Expand Live Preview to Full Screen", + "LIVE_PREVIEW_EXIT_FULL_SCREEN": "Exit Full Screen", "CMD_TOGGLE_TABBAR": "File Tab Bar", "CMD_TOGGLE_PANELS": "Toggle Panels", "CMD_TOGGLE_PURE_CODE": "No Distractions", diff --git a/src/view/WorkspaceManager.js b/src/view/WorkspaceManager.js index a17e5663ce..5f87fcb70d 100644 --- a/src/view/WorkspaceManager.js +++ b/src/view/WorkspaceManager.js @@ -81,6 +81,13 @@ define(function (require, exports, module) { */ const EVENT_WORKSPACE_DESIGN_MODE_CHANGE = "workspaceDesignModeChange"; + /** + * Event triggered when live-preview full screen (design mode with the sidebar + * hidden) is entered or exited. Payload: `(active: boolean)`. + * @const + */ + const EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE = "workspaceLPFullScreenChange"; + /** * Width of the main toolbar in pixels. * @const @@ -755,6 +762,38 @@ define(function (require, exports, module) { exports.trigger(EVENT_WORKSPACE_DESIGN_MODE_CHANGE, _isInDesignMode); } + let _isInLPFullScreen = false; + + /** + * Returns true while live preview is expanded to full screen, meaning design mode + * with the sidebar hidden so live preview owns everything to the right of the + * central control bar. + * + * Full screen is a superset of design mode, so `isInDesignMode()` is true here + * too. Use `isInDesignMode()` if you only care that the editor is collapsed; + * use this only when the sidebar state matters. + * @returns {boolean} + */ + function isInLPFullScreen() { + return _isInLPFullScreen; + } + + /** + * Sets the live-preview full-screen flag and fires + * EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE when the value actually changes. + * Intended to be called by the control bar; other callers should use the + * dedicated toggle command instead. + * @param {boolean} active + */ + function setLPFullScreen(active) { + const next = !!active; + if (_isInLPFullScreen === next) { + return; + } + _isInLPFullScreen = next; + exports.trigger(EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE, _isInLPFullScreen); + } + // Escape key and toggle panel special handling let _escapeKeyConsumers = {}; @@ -918,8 +957,11 @@ define(function (require, exports, module) { exports.EVENT_WORKSPACE_PANEL_SHOWN = EVENT_WORKSPACE_PANEL_SHOWN; exports.EVENT_WORKSPACE_PANEL_HIDDEN = EVENT_WORKSPACE_PANEL_HIDDEN; exports.EVENT_WORKSPACE_DESIGN_MODE_CHANGE = EVENT_WORKSPACE_DESIGN_MODE_CHANGE; + exports.EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE = EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE; exports.isInDesignMode = isInDesignMode; exports.setDesignMode = setDesignMode; + exports.isInLPFullScreen = isInLPFullScreen; + exports.setLPFullScreen = setLPFullScreen; exports.DEFAULT_PANEL_ID = DEFAULT_PANEL_ID; /** From 7e0667d63ccd50e41732b0c7a54b9261764f0446 Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 24 Aug 2026 00:41:24 +0530 Subject: [PATCH 2/6] feat: implement live preview full screen in the control bar Full screen is derived state, not a mode of its own. Live preview is full screen exactly when the editor is collapsed and the sidebar is away, so it also turns on when you enter design mode and then collapse the sidebar by hand, which previously left the expand icon out of sync with what was on screen. Exiting undoes only what entering did. Entering from the code editor turns design mode on and hides the sidebar, so exiting restores both. Entering from design mode only hides the sidebar, so exiting brings the sidebar back and stays in design mode instead of jumping to the editor. The sidebar toggle keeps working as it always did. Showing the sidebar from full screen drops you into design mode on its own, so it needed no special casing. Two other bits: - Resizer persists visible:false when the sidebar hides, but full screen is not a persisted mode, so quitting from it would reopen the app with no sidebar and no clue why. The stored flag is put back after hiding. - The sidebar drag handle is hidden in full screen. It sits invisible over the left edge of the preview and would otherwise steal clicks. --- src/styles/CentralControlBar.less | 4 + src/view/CentralControlBar.js | 142 ++++++++++++++++++++++++++++-- 2 files changed, 139 insertions(+), 7 deletions(-) diff --git a/src/styles/CentralControlBar.less b/src/styles/CentralControlBar.less index 75dc500e50..a4c3b2b4d0 100644 --- a/src/styles/CentralControlBar.less +++ b/src/styles/CentralControlBar.less @@ -232,3 +232,7 @@ body:not(.ccb-editor-collapsed) #centralControlBar .ccb-group-file { .ccb-editor-collapsed #sidebar { max-width: ~"calc(100vw - 230px)"; } + +body.lp-fullscreen .main-view > .horz-resizer { + display: none; +} diff --git a/src/view/CentralControlBar.js b/src/view/CentralControlBar.js index 8610a82a4e..7d59861286 100644 --- a/src/view/CentralControlBar.js +++ b/src/view/CentralControlBar.js @@ -27,6 +27,7 @@ define(function (require, exports, module) { const LanguageManager = require("language/LanguageManager"); const MainViewManager = require("view/MainViewManager"); const Metrics = require("utils/Metrics"); + const PreferencesManager = require("preferences/PreferencesManager"); const Strings = require("strings"); const WorkspaceManager = require("view/WorkspaceManager"); const SidebarView = require("project/SidebarView"); @@ -43,6 +44,9 @@ define(function (require, exports, module) { let livePreviewWasOpen = false; let savedSidebarMaxSize = null; let applyingCollapsedLayout = false; + let lpFullScreen = false; + let sidebarHiddenByFullScreen = false; + let designModeEnabledByFullScreen = false; function _getRenderedSidebarWidth() { // Use offsetWidth (not jQuery's outerWidth) to force a synchronous reflow @@ -316,6 +320,11 @@ define(function (require, exports, module) { function _setEditorCollapsed(collapsed, opts) { const wantCollapsed = !!collapsed; + // Leaving design mode also leaves full screen, so give the sidebar back + // if full screen was what hid it. + if (!wantCollapsed) { + _restoreSidebarFromFullScreen(); + } if (wantCollapsed === editorCollapsed) { return; } @@ -347,15 +356,14 @@ define(function (require, exports, module) { _flushTracker(_mdDesignTracker); } $("body").toggleClass("ccb-editor-collapsed", editorCollapsed); - const $collapseBtn = $("#ccbCollapseEditorBtn"); - $collapseBtn.toggleClass("is-active", editorCollapsed) - .attr("title", editorCollapsed ? Strings.CCB_SWITCH_TO_CODE_EDITOR : Strings.CCB_SWITCH_TO_DESIGN_MODE); + _updateCollapseBtn(); if (_toggleDesignModeCommand) { _toggleDesignModeCommand.setChecked(editorCollapsed); } if (WorkspaceManager.setDesignMode) { WorkspaceManager.setDesignMode(editorCollapsed); } + _recomputeFullScreen(); if (editorCollapsed) { livePreviewWasOpen = _isLivePreviewOpen(); @@ -398,8 +406,110 @@ define(function (require, exports, module) { if (!$btn.length) { return; } - const isVisible = SidebarView.isVisible(); - $btn.find("i").attr("class", isVisible ? "fa-solid fa-angles-left" : "fa-solid fa-angles-right"); + const sidebarVisible = SidebarView.isVisible(); + $btn.find("i").attr("class", sidebarVisible ? "fa-solid fa-angles-left" : "fa-solid fa-angles-right"); + $btn.attr("title", lpFullScreen + ? Strings.LIVE_PREVIEW_EXIT_FULL_SCREEN : Strings.CMD_TOGGLE_SIDEBAR); + } + + function _updateCollapseBtn() { + $("#ccbCollapseEditorBtn") + .toggleClass("is-active", editorCollapsed) + .attr("title", editorCollapsed + ? Strings.CCB_SWITCH_TO_CODE_EDITOR : Strings.CCB_SWITCH_TO_DESIGN_MODE); + } + + function _hideSidebarForFullScreen() { + if (!SidebarView.isVisible()) { + return; + } + sidebarHiddenByFullScreen = true; + SidebarView.hide(); + // Resizer persists visible:false on hide, but full screen itself isn't + // persisted, so quitting from it would reopen the app with no sidebar. + // Put the stored flag back. + const sidebarViewState = PreferencesManager.getViewState("sidebar"); + if (sidebarViewState) { + sidebarViewState.visible = true; + PreferencesManager.setViewState("sidebar", sidebarViewState); + } + } + + function _restoreSidebarFromFullScreen() { + if (!sidebarHiddenByFullScreen) { + return; + } + sidebarHiddenByFullScreen = false; + if (!SidebarView.isVisible()) { + SidebarView.show(); + } + } + + /** + * Full screen is derived state: live preview is full screen exactly when the + * editor is collapsed and the sidebar is away, however the user got there. + * Call this after either of those two inputs changes. + * @private + */ + function _recomputeFullScreen() { + const nextFullScreen = editorCollapsed && !SidebarView.isVisible(); + if (nextFullScreen === lpFullScreen) { + return; + } + lpFullScreen = nextFullScreen; + if (!lpFullScreen) { + sidebarHiddenByFullScreen = false; + designModeEnabledByFullScreen = false; + } + $("body").toggleClass("lp-fullscreen", lpFullScreen); + if (WorkspaceManager.setLPFullScreen) { + WorkspaceManager.setLPFullScreen(lpFullScreen); + } + if (_toggleLPFullScreenCommand) { + _toggleLPFullScreenCommand.setChecked(lpFullScreen); + } + _updateSidebarToggleIcon(); + } + + /** + * Enters or exits live-preview full screen, meaning design mode with the sidebar + * hidden. + * + * Exiting undoes only what entering did, so it turns design mode off only when + * entering was what turned it on. Entering from design mode returns to design + * mode, not to the editor. + * @param {boolean} fullScreen + * @private + */ + function _setLPFullScreen(fullScreen) { + const wantFullScreen = !!fullScreen; + if (wantFullScreen === lpFullScreen) { + return; + } + if (wantFullScreen) { + designModeEnabledByFullScreen = !editorCollapsed; + if (!editorCollapsed) { + _setEditorCollapsed(true); + } + _hideSidebarForFullScreen(); + _recomputeFullScreen(); + _syncLeftPositions(); + _applyCollapsedLayout(); + return; + } + if (designModeEnabledByFullScreen) { + _restoreSidebarFromFullScreen(); + _setEditorCollapsed(false); + return; + } + // Design mode was already on, so bringing the sidebar back is the whole undo. + if (!SidebarView.isVisible()) { + SidebarView.show(); + } + sidebarHiddenByFullScreen = false; + _recomputeFullScreen(); + _syncLeftPositions(); + _applyCollapsedLayout(); } function _ccbClickMetric(label) { @@ -446,6 +556,11 @@ define(function (require, exports, module) { _setEditorCollapsed(!editorCollapsed); }, { supportsDesignMode: true }); + const _toggleLPFullScreenCommand = CommandManager.register(Strings.CMD_TOGGLE_LP_FULL_SCREEN, + Commands.VIEW_TOGGLE_LP_FULL_SCREEN, function () { + _setLPFullScreen(!lpFullScreen); + }, { supportsDesignMode: true }); + AppInit.htmlReady(function () { $bar = $("#centralControlBar"); $sidebar = $("#sidebar"); @@ -458,8 +573,7 @@ define(function (require, exports, module) { // strings; set the localized versions up front so the initial render // reflects the user's locale. (searchNav / navBackButton / // navForwardButton get their localized titles from NavigationProvider.) - $("#ccbCollapseEditorBtn").attr("title", Strings.CCB_SWITCH_TO_DESIGN_MODE); - $("#ccbSidebarToggleBtn").attr("title", Strings.CMD_TOGGLE_SIDEBAR); + _updateCollapseBtn(); $("#ccbUndoBtn").attr("title", Strings.CMD_UNDO); $("#ccbRedoBtn").attr("title", Strings.CMD_REDO); $("#ccbSaveBtn").attr("title", Strings.CMD_FILE_SAVE); @@ -511,6 +625,7 @@ define(function (require, exports, module) { _forwardResizeToMainToolbar("panelResizeUpdate"); }); $sidebar.on("panelResizeEnd.ccb panelCollapsed.ccb panelExpanded.ccb", function (e) { + _recomputeFullScreen(); _syncLeftPositions(); if (editorCollapsed) { _applyCollapsedLayout(); @@ -611,4 +726,17 @@ define(function (require, exports, module) { exports.isEditorCollapsed = function () { return editorCollapsed; }; exports.setEditorCollapsed = _setEditorCollapsed; + + /** + * True while live preview is expanded to full screen. Full screen implies design + * mode, so `isEditorCollapsed()` is true as well. + * @returns {boolean} + */ + exports.isLPFullScreen = function () { return lpFullScreen; }; + + /** + * Enters or exits live-preview full screen. + * @param {boolean} fullScreen + */ + exports.setLPFullScreen = _setLPFullScreen; }); From 349ae3536f03a5a4adffc16eafffeace7df33e4a Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 24 Aug 2026 00:41:47 +0530 Subject: [PATCH 3/6] feat: make the live preview expand button go full screen The expand icon in the live preview toolbar was just a second copy of the design mode toggle, which is not what the icon says it does. It now expands live preview to full screen, and design mode stays its own thing on the control bar. Renamed the button to fullScreenLivePreviewButton since the old id said design mode, and pointed its icon and tooltip at the full screen change event instead of the design mode one. The mode dropdown chevron keeps hiding in design mode as before, now driven directly by the design mode event. --- .../Phoenix-live-preview/live-preview.css | 4 +- .../Phoenix-live-preview/main.js | 37 +++++++++---------- .../Phoenix-live-preview/panel.html | 2 +- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index 40fcf5e973..cfc18c4e57 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -370,13 +370,13 @@ } #reloadLivePreviewButton, -#designModeToggleLivePreviewButton { +#fullScreenLivePreviewButton { border: 1px solid transparent; border-radius: 3px; } #live-preview-plugin-toolbar #reloadLivePreviewButton:hover, -#live-preview-plugin-toolbar #designModeToggleLivePreviewButton:hover { +#live-preview-plugin-toolbar #fullScreenLivePreviewButton:hover { border-color: rgba(255, 255, 255, 0.1) !important; background: transparent !important; box-shadow: none !important; diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index 3e99097216..1f8dc1e25b 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -190,7 +190,7 @@ define(function (require, exports, module) { $modeBtn, $modeBtnGroup, $previewBtn, - $designModeBtn; + $fullScreenBtn; let customLivePreviewBannerShown = false; @@ -800,7 +800,7 @@ define(function (require, exports, module) { livePreview: Strings.LIVE_DEV_STATUS_TIP_OUT_OF_SYNC, clickToReload: Strings.LIVE_DEV_CLICK_TO_RELOAD_PAGE, clickToToggleEdit: Strings.LIVE_PREVIEW_MODE_TOGGLE_EDIT, - switchToDesignMode: Strings.CCB_SWITCH_TO_DESIGN_MODE, + fullScreenLivePreview: Strings.LIVE_PREVIEW_FULL_SCREEN, livePreviewSettings: Strings.LIVE_DEV_SETTINGS, livePreviewConfigureModes: Strings.LIVE_PREVIEW_CONFIGURE_MODES, clickToPopout: Strings.LIVE_DEV_CLICK_POPOUT, @@ -833,7 +833,7 @@ define(function (require, exports, module) { $modeBtn = $panel.find("#livePreviewModeBtn"); $modeBtnGroup = $panel.find("#lpModeBtnGroup"); $previewBtn = $panel.find("#previewModeLivePreviewButton"); - $designModeBtn = $panel.find("#designModeToggleLivePreviewButton"); + $fullScreenBtn = $panel.find("#fullScreenLivePreviewButton"); // Markdown theme toggle — persist user choice MarkdownSync.setThemeToggleHandler((theme) => { @@ -918,28 +918,25 @@ define(function (require, exports, module) { Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW, "reloadBtn", "click"); }); - // Design-mode toggle: mirrors the CCB's pen-nib button so the user can - // enter/exit design mode without moving focus to the sidebar strip. - // Icon swaps between fa-expand (enter) and fa-compress (exit). - function _updateDesignModeButton() { - const on = WorkspaceManager.isInDesignMode && WorkspaceManager.isInDesignMode(); - const $icon = $designModeBtn.find("i"); - $icon.removeClass("fa-expand fa-compress") + function _updateFullScreenButton() { + const on = WorkspaceManager.isInLPFullScreen && WorkspaceManager.isInLPFullScreen(); + $fullScreenBtn.find("i") + .removeClass("fa-expand fa-compress") .addClass(on ? "fa-compress" : "fa-expand"); - $designModeBtn.attr("title", - on ? Strings.CCB_SWITCH_TO_CODE_EDITOR : Strings.CCB_SWITCH_TO_DESIGN_MODE); - if ($modeBtn) { - $modeBtn.toggle(!on && !_isMdviewrActive); - } + $fullScreenBtn.attr("title", + on ? Strings.LIVE_PREVIEW_EXIT_FULL_SCREEN : Strings.LIVE_PREVIEW_FULL_SCREEN); } - $designModeBtn.click(()=>{ - CommandManager.execute(Commands.VIEW_TOGGLE_DESIGN_MODE); - Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW, "designModeBtn", "click"); + $fullScreenBtn.click(()=>{ + CommandManager.execute(Commands.VIEW_TOGGLE_LP_FULL_SCREEN); + Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW, "fullScreenBtn", "click"); }); WorkspaceManager.off(WorkspaceManager.EVENT_WORKSPACE_DESIGN_MODE_CHANGE + ".livePreview"); WorkspaceManager.on(WorkspaceManager.EVENT_WORKSPACE_DESIGN_MODE_CHANGE + ".livePreview", - _updateDesignModeButton); - _updateDesignModeButton(); + _updateLPControlsForMdviewer); + WorkspaceManager.off(WorkspaceManager.EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE + ".livePreview"); + WorkspaceManager.on(WorkspaceManager.EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE + ".livePreview", + _updateFullScreenButton); + _updateFullScreenButton(); // init the status overlay _initOverlay(); diff --git a/src/extensionsIntegrated/Phoenix-live-preview/panel.html b/src/extensionsIntegrated/Phoenix-live-preview/panel.html index 0a32900fd1..1a24d179a8 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/panel.html +++ b/src/extensionsIntegrated/Phoenix-live-preview/panel.html @@ -4,7 +4,7 @@ - From 944a56bdb5b2c14ed837f742cc51e58fac54656e Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 24 Aug 2026 01:10:13 +0530 Subject: [PATCH 4/6] chore: auto update api docs --- docs/API-Reference/command/Commands.md | 6 ++++ docs/API-Reference/view/WorkspaceManager.md | 36 +++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/docs/API-Reference/command/Commands.md b/docs/API-Reference/command/Commands.md index 631fa03621..37a71de251 100644 --- a/docs/API-Reference/command/Commands.md +++ b/docs/API-Reference/command/Commands.md @@ -458,6 +458,12 @@ Toggles sidebar visibility ## VIEW\_TOGGLE\_DESIGN\_MODE Toggles the design (full live-preview) mode — collapses/expands the editor +**Kind**: global variable + + +## VIEW\_TOGGLE\_LP\_FULL\_SCREEN +Toggles live-preview full screen (design mode with the sidebar hidden) + **Kind**: global variable diff --git a/docs/API-Reference/view/WorkspaceManager.md b/docs/API-Reference/view/WorkspaceManager.md index eff290c760..1f26abee19 100644 --- a/docs/API-Reference/view/WorkspaceManager.md +++ b/docs/API-Reference/view/WorkspaceManager.md @@ -29,6 +29,7 @@ Events: * [.EVENT_WORKSPACE_PANEL_SHOWN](#module_view/WorkspaceManager..EVENT_WORKSPACE_PANEL_SHOWN) * [.EVENT_WORKSPACE_PANEL_HIDDEN](#module_view/WorkspaceManager..EVENT_WORKSPACE_PANEL_HIDDEN) * [.EVENT_WORKSPACE_DESIGN_MODE_CHANGE](#module_view/WorkspaceManager..EVENT_WORKSPACE_DESIGN_MODE_CHANGE) + * [.EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE](#module_view/WorkspaceManager..EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE) * [.createBottomPanel(id, $panel, [minSize], [title], [options])](#module_view/WorkspaceManager..createBottomPanel) ⇒ Panel * [.destroyBottomPanel(id)](#module_view/WorkspaceManager..destroyBottomPanel) * [.createPluginPanel(id, $panel, [minSize], $toolbarIcon, [initialSize])](#module_view/WorkspaceManager..createPluginPanel) ⇒ Panel @@ -39,6 +40,8 @@ Events: * [.setPluginPanelWidth(width)](#module_view/WorkspaceManager..setPluginPanelWidth) * [.isInDesignMode()](#module_view/WorkspaceManager..isInDesignMode) ⇒ boolean * [.setDesignMode(active)](#module_view/WorkspaceManager..setDesignMode) + * [.isInLPFullScreen()](#module_view/WorkspaceManager..isInLPFullScreen) ⇒ boolean + * [.setLPFullScreen(active)](#module_view/WorkspaceManager..setLPFullScreen) * [.addEscapeKeyEventHandler(consumerName, eventHandler)](#module_view/WorkspaceManager..addEscapeKeyEventHandler) ⇒ boolean * [.removeEscapeKeyEventHandler(consumerName)](#module_view/WorkspaceManager..removeEscapeKeyEventHandler) ⇒ boolean @@ -96,6 +99,13 @@ Event triggered when a panel is hidden. Event triggered when design mode (editor collapsed, full live preview) is entered or exited. Payload: `(active: boolean)`. +**Kind**: inner constant of [view/WorkspaceManager](#module_view/WorkspaceManager) + + +### view/WorkspaceManager.EVENT\_WORKSPACE\_LP\_FULL\_SCREEN\_CHANGE +Event triggered when live-preview full screen (design mode with the sidebar +hidden) is entered or exited. Payload: `(active: boolean)`. + **Kind**: inner constant of [view/WorkspaceManager](#module_view/WorkspaceManager) @@ -220,6 +230,32 @@ callers should use the dedicated toggle command instead. | --- | --- | | active | boolean | + + +### view/WorkspaceManager.isInLPFullScreen() ⇒ boolean +Returns true while live preview is expanded to full screen, meaning design mode +with the sidebar hidden so live preview owns everything to the right of the +central control bar. + +Full screen is a superset of design mode, so `isInDesignMode()` is true here +too. Use `isInDesignMode()` if you only care that the editor is collapsed; +use this only when the sidebar state matters. + +**Kind**: inner method of [view/WorkspaceManager](#module_view/WorkspaceManager) + + +### view/WorkspaceManager.setLPFullScreen(active) +Sets the live-preview full-screen flag and fires +EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE when the value actually changes. +Intended to be called by the control bar; other callers should use the +dedicated toggle command instead. + +**Kind**: inner method of [view/WorkspaceManager](#module_view/WorkspaceManager) + +| Param | Type | +| --- | --- | +| active | boolean | + ### view/WorkspaceManager.addEscapeKeyEventHandler(consumerName, eventHandler) ⇒ boolean From 12411d948c17e1c3bb0fa3a7c16088775918f679 Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 24 Aug 2026 01:23:34 +0530 Subject: [PATCH 5/6] feat: tests covering the new live preview full screen mode --- test/spec/CentralControlBar-integ-test.js | 157 ++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/test/spec/CentralControlBar-integ-test.js b/test/spec/CentralControlBar-integ-test.js index 3fe377a13d..77c67f91fa 100644 --- a/test/spec/CentralControlBar-integ-test.js +++ b/test/spec/CentralControlBar-integ-test.js @@ -1316,5 +1316,162 @@ define(function (require, exports, module) { expect(CentralControlBar.isEditorCollapsed()).toBe(false); }); }); + + describe("14. Live preview full screen", function () { + // Full screen is derived state: live preview is full screen exactly when + // the editor is collapsed and the sidebar is away. These cover the state + // rule and the enter/exit contract, not icon classes or tooltip strings. + let PreferencesManager; + + beforeAll(function () { + PreferencesManager = brackets.test.PreferencesManager; + }); + + async function enterFullScreen() { + if (WorkspaceManager.isInLPFullScreen()) { + return; + } + CommandManager.execute(Commands.VIEW_TOGGLE_LP_FULL_SCREEN); + await awaitsFor(function () { return WorkspaceManager.isInLPFullScreen(); }, + "full screen to activate", 10000); + await awaitsFor(function () { + const p = livePanel(); + return p && p.isVisible(); + }, "live preview to be visible in full screen", 10000); + } + + async function exitFullScreen() { + if (!WorkspaceManager.isInLPFullScreen()) { + return; + } + CommandManager.execute(Commands.VIEW_TOGGLE_LP_FULL_SCREEN); + await awaitsFor(function () { return !WorkspaceManager.isInLPFullScreen(); }, + "full screen to deactivate", 10000); + } + + it("should collapse the editor and give live preview the full width minus the control bar", + async function () { + await openLivePreview(); + await enterFullScreen(); + + expect(WorkspaceManager.isInDesignMode()).toBe(true); + expect(SidebarView.isVisible()).toBe(false); + + const ccbLeft = _$("#centralControlBar")[0].getBoundingClientRect().left; + expect(ccbLeft).toBeLessThan(2); + + const mtWidth = _$("#main-toolbar").outerWidth(); + expect(Math.abs(mtWidth - (testWindow.innerWidth - CCB_WIDTH))).toBeLessThan(5); + }); + + it("should return to the code editor with the sidebar back when entered from the editor", + async function () { + await openLivePreview(); + await enterFullScreen(); + await exitFullScreen(); + + expect(WorkspaceManager.isInDesignMode()).toBe(false); + expect(SidebarView.isVisible()).toBe(true); + // Live preview was open before full screen, so it stays open. + expect(livePanel().isVisible()).toBe(true); + }); + + it("should return to design mode, not the editor, when entered from design mode", + async function () { + await enterDesignMode(); + await enterFullScreen(); + await exitFullScreen(); + + expect(WorkspaceManager.isInDesignMode()).toBe(true); + expect(SidebarView.isVisible()).toBe(true); + }); + + it("should turn on and off as the sidebar is hidden and shown in design mode", async function () { + await enterDesignMode(); + expect(WorkspaceManager.isInLPFullScreen()).toBe(false); + + SidebarView.hide(); + await awaitsFor(function () { return WorkspaceManager.isInLPFullScreen(); }, + "full screen to follow the sidebar collapsing", 3000); + + SidebarView.show(); + await awaitsFor(function () { return !WorkspaceManager.isInLPFullScreen(); }, + "full screen to follow the sidebar coming back", 3000); + // Only the sidebar came back, the editor stays collapsed. + expect(WorkspaceManager.isInDesignMode()).toBe(true); + }); + + it("should not be full screen when the sidebar is hidden but the editor is still up", + async function () { + expect(WorkspaceManager.isInDesignMode()).toBe(false); + + SidebarView.hide(); + await awaitsFor(function () { return !SidebarView.isVisible(); }, + "sidebar to hide", 2000); + + expect(WorkspaceManager.isInLPFullScreen()).toBe(false); + }); + + it("should drop to design mode when the CCB sidebar toggle is clicked in full screen", + async function () { + await openLivePreview(); + await enterFullScreen(); + + _$("#ccbSidebarToggleBtn").trigger("click"); + + await awaitsFor(function () { return !WorkspaceManager.isInLPFullScreen(); }, + "full screen to exit on sidebar toggle", 5000); + expect(WorkspaceManager.isInDesignMode()).toBe(true); + expect(SidebarView.isVisible()).toBe(true); + }); + + it("should leave the stored sidebar visibility alone so quitting from full screen restores it", + async function () { + await openLivePreview(); + await enterFullScreen(); + + // Resizer writes visible:false on hide. Full screen is not a + // persisted mode, so the stored flag must stay true or the next + // launch comes up with no sidebar. + expect(SidebarView.isVisible()).toBe(false); + expect(PreferencesManager.getViewState("sidebar").visible).toBe(true); + }); + + it("should keep the sidebar hidden on exit when the user hid it themselves", async function () { + await openLivePreview(); + SidebarView.hide(); + await awaitsFor(function () { return !SidebarView.isVisible(); }, + "sidebar to hide", 2000); + + await enterFullScreen(); + await exitFullScreen(); + + expect(SidebarView.isVisible()).toBe(false); + }); + + it("should exit and restore the sidebar when live preview is closed in full screen", + async function () { + await openLivePreview(); + await enterFullScreen(); + + livePanel().hide(); + + await awaitsFor(function () { return !WorkspaceManager.isInLPFullScreen(); }, + "full screen to exit when live preview closes", 5000); + expect(WorkspaceManager.isInDesignMode()).toBe(false); + expect(SidebarView.isVisible()).toBe(true); + }); + + it("should dispatch VIEW_TOGGLE_LP_FULL_SCREEN from the live preview expand button", + async function () { + await openLivePreview(); + + const executed = recordCommands(function () { + _$("#fullScreenLivePreviewButton").trigger("click"); + }); + + expect(executed).toContain(Commands.VIEW_TOGGLE_LP_FULL_SCREEN); + }); + }); }); }); From 348648460a722ac6a97365a9f15d6d588a2cf916 Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 24 Aug 2026 01:54:09 +0530 Subject: [PATCH 6/6] fix: sidebar resizer remove display none when in full screen --- src/styles/CentralControlBar.less | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/styles/CentralControlBar.less b/src/styles/CentralControlBar.less index a4c3b2b4d0..75dc500e50 100644 --- a/src/styles/CentralControlBar.less +++ b/src/styles/CentralControlBar.less @@ -232,7 +232,3 @@ body:not(.ccb-editor-collapsed) #centralControlBar .ccb-group-file { .ccb-editor-collapsed #sidebar { max-width: ~"calc(100vw - 230px)"; } - -body.lp-fullscreen .main-view > .horz-resizer { - display: none; -}