Search code examples
monaco-editor

Is it possible to add header sections to Monaco Editor's diff editor panels?


Monaco Diff Editor UX allows the user to resize original and modified panes by using the resizer that is in the middle of two panes.

  • Is it possible to add headers (a block element that would contain any HTML element) at the top of these panes as shown below? They should be contained within the limits of the respective pane so that they get resized as well.
  • If adding headers is not possible, would it be possible to read the width of the individual panes programmatically so desired behavior could be faked?

DiffEditor


Solution

  • You can fake the behaviour by hooking into the onDidLayoutChange event of the originalEditor (this is the left hand editor when displaying a DiffEditor). This event handler will listen for any change to layout (e.g. the user dragging the resize handle) and update the size of the left hand header to stay in sync with the editor:

    diffEditor._originalEditor.onDidLayoutChange(function(layout) {
        document.getElementById('left-header').style.width = layout.width + 'px';
    });
    

    This assumes you have the following HTML structure:

    <!-- Fake header -->
    <div style="display: flex">
        <div id="left-header" style="width: calc(50% - 14px)">Left Header</div>
        <div>Right Header</div>
    </div>
    <!-- container for Monaco editor -->
    <div id="container" style="height: 100%"></div>
    

    Here the initial width of the left hand header is set to 50% - 14px as 14px is the width of the resizer bar in Monaco.

    If you paste the following HTML and CSS into the Monaco Playground you will see it working:

    HTML

    <div style="display: flex">
        <div id="left-header" style="width: calc(50% - 14px)">Left Header</div>
        <div>Right Header</div>
    </div>
    <div id="container" style="height: 100%"></div>
    

    JavaScript

    // The diff editor offers a navigator to jump between changes. Once the diff is computed the <em>next()</em> and <em>previous()</em> method allow navigation. By default setting the selection in the editor manually resets the navigation state.
    var originalModel = monaco.editor.createModel(
        'just some text\n\nHello World\n\nSome more text',
        'text/plain'
    );
    var modifiedModel = monaco.editor.createModel(
        'just some Text\n\nHello World\n\nSome more changes',
        'text/plain'
    );
    
    var diffEditor = monaco.editor.createDiffEditor(document.getElementById('container'));
    diffEditor.setModel({
        original: originalModel,
        modified: modifiedModel
    });
    
    var navi = monaco.editor.createDiffNavigator(diffEditor, {
        followsCaret: true, // resets the navigator state when the user selects something in the editor
        ignoreCharChanges: true // jump from line to line
    });
    
    window.setInterval(function () {
        navi.next();
    }, 2000);
    
    diffEditor._originalEditor.onDidLayoutChange(function(layout) {
        document.getElementById('left-header').style.width = layout.width + 'px';
    });