Conversation
A new 30px control bar sits between the sidebar and the editor area with editor collapse, edit/save actions, file navigation, sidebar toggle, and a vertical filename label. The sidebar-toggle button has been moved from the titlebar into the control bar permanently. The collapse toggle expands live preview to fill the editor area (opening it first if not already open), and honors the user's last live preview width on restore. Dragging the plugin-toolbar resizer while collapsed exits the collapsed state so normal resize resumes. The NAVIGATE_SHOW_IN_FILE_TREE command now also expands the sidebar when it is hidden so reveal-in-tree works regardless of entry point (control-bar click, context menu, keyboard shortcut).
The control bar collapse toggle now presents as a feather icon with title "Switch to Visual Edit" while the editor is visible, and flips to the code icon with title "Switch to Code Editor" while the editor is collapsed into design/preview mode.
…mode While the editor is collapsed, window resize events triggered two visible glitches: (1) the sidebar shrunk by ~1px per resize in a slow drift, because Resizer.updateResizeLimits recomputes sideBarMaxSize from sibling widths (which equals ~sidebarWidth once #main-toolbar is a full-width sibling) and clamps only when data-maxsize is a percentage; (2) #main-toolbar flickered as WorkspaceManager's _clampPluginPanelWidth capped it below our desired width before our handler reset it each frame. Fix both by pinning data-maxsize to "1000%" during collapse so the sidebar clamp is short-circuited, and by setting main-toolbar geometry with !important so the workspace clamp can't override it. Also add an applyingCollapsedLayout reentry guard on the EVENT_WORKSPACE_UPDATE_LAYOUT listener so our own recomputeLayout calls don't re-enter.
…design mode The sidebar's right-resizer handle now visually sits to the right of #centralControlBar (instead of between the sidebar and the control bar), using a CSS transform so Resizer.repositionResizer can keep its own internal left offset. The same shift applies when the sidebar is hidden and the handle is reparented to .main-view. In design mode (editor collapsed), the main-toolbar's own left resizer is hidden — previously dragging it exited design mode. Now the single sidebar resizer acts as the sidebar↔live-preview splitter so the split can be adjusted without leaving the mode. Bumped sidebar data-minsize from 0 to 30 so drag can't auto-collapse the sidebar below the control-bar width; the dedicated sidebar-toggle button still fully hides it.
…ss toggles Introduce a CSS `max-width: 70vw` cap on the sidebar while in design mode so a drag can't push the sidebar past the cap — the cap is enforced during the drag itself instead of snapping back after the fact, and there are no width writes inside the Resizer's own frame that would trip "ResizeObserver loop completed with undelivered notifications" warnings. When exiting design mode the max-width constraint is removed; the sidebar's style.width may still hold the larger value the Resizer wrote during the capped drag, so the sidebar would snap back to that stale width. Before flipping the body class, pin style.width to the currently rendered width (reading via offsetWidth to force a synchronous reflow) and resync the Resizer handle so the sidebar keeps the size the user sees through collapse/expand cycles. Also switch _syncLeftPositions / _applyCollapsedLayout / _restoreExpandedLayout to read sidebar.offsetWidth directly rather than jQuery's outerWidth — the latter returned the uncapped style value in some frames mid-drag which left the control bar and main-toolbar positioned at stale offsets.
Clicking toolbar-go-live while in design mode hid the live preview panel but left the editor collapsed — producing a dead zone where the panel used to be. Now listen for EVENT_WORKSPACE_PANEL_HIDDEN on the live-preview panel and exit design mode so the editor comes back in its place. _restoreExpandedLayout accepts a skipToolbarRestore flag for this path — WorkspaceManager._hidePluginSidePanel has already sized #main-toolbar back to the icon-bar width when it fired the hide event, so our usual pre-collapse live-preview width restore would re-open the same dead zone we're trying to avoid.
… mode Capping the sidebar at 70vw worked on typical displays but became too generous on very large screens — the live-preview panel could shrink to a useless sliver. Change the design-mode sidebar cap to `calc(100vw - 230px)` so it always reserves at least 200px for the live preview plus the 30px control bar, regardless of viewport size.
In design mode the sidebar's right-resizer doubles as the sidebar↔live-preview splitter (the main-toolbar's own left-resizer is hidden). Listeners that watch #main-toolbar for panelResizeStart/Update/End — most notably the live-preview resize ruler / media-query ruler in lpedit-helper — weren't firing when the sidebar was dragged, so the ruler stayed hidden. Forward those three events from #sidebar to #main-toolbar while collapsed so the ruler (and any similar listener) reacts to the sidebar drag just like a main-toolbar drag in normal mode.
In design mode #main-toolbar's geometry is pinned with !important, so callers of WorkspaceManager.setPluginPanelWidth(w) had no way to programmatically size the live-preview panel. Wrap that API at CCB init time: while collapsed, translate the requested live-preview content width into a sidebar width (window - toolbar - CCB) and drive the normal sidebar sync pipeline. In normal mode the call falls through to the original implementation unchanged.
Register VIEW_TOGGLE_DESIGN_MODE (view.toggleDesignMode) at CentralControlBar module load so extensions and keybindings can trigger the design-mode toggle without reaching into the module directly. The command's checked state mirrors the body class so the menu shows a tick when design mode is active. Add a File menu item directly below Live Preview, wired from Phoenix-live-preview (where the live-preview menu group is built) so the anchor exists at insert time. Default shortcut Ctrl-F11 is wired via src/base-config/keyboard.json.
Expose WorkspaceManager.isInDesignMode() / setDesignMode() and a new EVENT_WORKSPACE_DESIGN_MODE_CHANGE so other modules can react to the full-live-preview layout without reaching into the control bar. CentralControlBar mirrors its editorCollapsed flag into the workspace manager on every toggle. NoDistractions now checks isInDesignMode(): in design mode entering/exiting only toggles the sidebar (the main toolbar and panels are part of the editing surface and hiding them would blank the live preview area). In the normal editor layout the previous behavior — hide sidebar + main toolbar + panels — still applies.
The central control bar now sits between #sidebar and .content, so the "should update the .content left offset" SidebarTabs spec — which used to assert sidebar.width — must add #centralControlBar.outerWidth() to match the new layout. Computed from the live CCB width so the test stays correct regardless of control-bar width changes. Add test/control-bar-tests-todo.md with the full mainview: suite we plan to write for the control bar + design-mode feature set. Serves as a running checklist; we'll land the actual tests in follow-ups.
… open, or git panel Each of these surfaces mounts UI in a region that design mode has collapsed away (the editor chrome or the bottom panel area), so clicking into them while in design mode produced a broken layout. Call the VIEW_TOGGLE_DESIGN_MODE command to exit first; the normal command flow then renders correctly. Each site includes a TODO noting the long-term desire: float the panel / picker on top of the live preview so users can use these features without leaving design mode.
Adds a new section 11b to control-bar-tests-todo.md tracking the auto-exit behavior wired into the tools panel (app-drawer-button), Find in Files, Quick Open, and the git toolbar icon — plus future follow-ups for each (floating variants that would avoid the need to exit design mode).
Quick Open's standard ModalBar mounts above #editor-holder, which is
collapsed in design mode — invoking the picker there would show no
UI. Add a ModalBar-compatible floating variant: when
WorkspaceManager.isInDesignMode() is true, showDialog creates a
centered overlay with a compact search bar instead. The picker stays
non-modal: no backdrop dim or blur so the live preview stays fully
visible and file switching never feels jarring.
- _createFloatingQuickOpenBar implements the bits of ModalBar that
QuickOpen uses (on("close", ...), close(), prepareClose, getRoot)
and returns a resolved jQuery Deferred from close() so callers
chain .done() safely.
- Dropdown (appended to <body> by QuickSearchField) is anchored to
the floating bar via the $positionEl option and bumped above the
overlay's stacking so its rendering isn't dimmed.
- verticalAdjust is computed as (bar.bottom - input.bottom) so the
dropdown sits flush with the bar instead of floating detached.
- Escape handling runs in capture phase on both the overlay and the
document so one keypress dismisses both dropdown and picker at
once instead of requiring two.
- setSearchFieldValue guards against a torn-down searchField so
re-entering the command after a stale close doesn't throw.
- QuickOpen's own "exit design mode first" branch is removed — the
floating picker replaces that workaround entirely.
…iframe-click dismiss Move the file-type classification helpers (getExtension, isPDF, isSVG, isImage, isHTMLFile, isMarkdownFile, isPreviewableFile, isServerRenderedFile) from Phoenix-live-preview/utils.js into a shared src/utils/FileTypeUtils.js module so non-live-preview code can depend on them. The live-preview utils now re-exports those helpers and keeps only its iframe-specific pieces (LIVE_PREVIEW_IFRAME_ID, MDVIEWR_IFRAME_ID, focusActiveEditorIfFocusInLivePreview). Quick Open's floating (design-mode) picker now restricts results to files that actually make sense to open into the live preview — HTML, SVG, Markdown, PDF — plus server-rendered sources (PHP, ASP, JSP, Python, Ruby/ERB, ColdFusion). Everything else is hidden because opening it would just collapse design mode. Also dismiss the floating picker when focus moves into the live preview iframe: those clicks never surface as mousedown / focusin on the parent document, so they used to leave the picker stranded. Listen for window blur and close once focus settles outside the bar / results dropdown.
When the md viewer iframe forwards an unhandled shortcut to Phoenix, it re-focuses its own viewer-content 100ms later so commands like Save return focus to the editor. That timer also fired for shortcuts that open parent UIs (Quick Open, Find in Files) — pulling focus out of the picker and making the dropdown vanish on the first keystroke. Send the set of "skip refocus" key strings from the parent to the iframe at runtime. MarkdownSync reads the bindings for the relevant commands from KeyBindingManager and posts MDVIEWR_SKIP_REFOCUS_KEYS on iframe ready and whenever a binding changes. The iframe stores the set and builds the same canonical key string KBM uses from each keydown to decide whether to skip the refocus. Adding more shortcuts is now just appending a command id to SKIP_REFOCUS_COMMANDS in MarkdownSync — no hardcoded keys in the iframe. Also remove the QuickOpen design-mode exit branch added earlier: the floating picker variant replaces that workaround entirely.
Rename the collapse-editor toggle's expanded-state title from "Switch to Visual Edit" to "Switch to Design Mode" so it matches the rest of the feature's naming (command id, menu item, body class, WorkspaceManager API all already use "design mode"). Also localize the control bar's hardcoded English titles: - Switch to Design Mode / Switch to Code Editor get new string keys (CCB_SWITCH_TO_DESIGN_MODE, CCB_SWITCH_TO_CODE_EDITOR). - Sidebar toggle, Undo, Redo, Save reuse existing CMD_TOGGLE_SIDEBAR / CMD_UNDO / CMD_REDO / CMD_FILE_SAVE. - Search / Back / Forward were already localized via NavigationProvider.updateTooltips. HTML keeps the English titles as fallback; the JS init overwrites them with the localized strings so the user's locale shows on first render.
The old "should remember scroll positions" spec called CodeInspection.scrollToProblem(40) and asserted the resulting scrollTop was non-zero. Both sides of that flaked across environments: - scrollToProblem uses Element.scrollIntoView, which picks a scrollable ancestor that isn't always the .table-container we asserted on. - The problems panel's height depends on the window size / user prefs; on wide windows the table fits all rows and no scroll is possible, so scrollTop stays 0 regardless of how we invoke it. Replace the assertion with the round-trip invariant: set scrollTop(200) on the table, switch away, switch back, and wait for scrollTop to land back at 200. The remember-scroll feature's entire contract is this round-trip; verifying it makes the test robust to panel height, platform, and headless runners. Also add an awaitsFor gate for row 40 before the scroll is seeded so the test doesn't race against async lint population.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




No description provided.