Skip to content

Commit

Permalink
Add resizable panels to webR REPL app
Browse files Browse the repository at this point in the history
  • Loading branch information
georgestagg committed Jun 19, 2024
1 parent a543b3e commit f437d4c
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 91 deletions.
24 changes: 17 additions & 7 deletions src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"react-accessible-treeview": "^2.6.1",
"react-dom": "^18.2.0",
"react-icons": "^4.10.1",
"react-resizable-panels": "^2.0.19",
"tsx": "^4.0.0",
"xmlhttprequest-ssl": "^2.1.0",
"xterm": "^5.1.0",
Expand Down
50 changes: 8 additions & 42 deletions src/repl/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,54 +14,20 @@ body {
}

.repl {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(6, 1fr);
width: 100vw;
height: 100vh;
}

.editor {
grid-row: 1 / 5;
grid-column: 1;
overflow: auto;
border-style: solid;
border-color: var(--bg-secondary);
border-width: 0px 2px 2px 0px;
padding-top: 5px;
div[data-panel] {
display: flex;
flex-direction: column;
}

.term {
grid-row-start: 5;
grid-row-end: -1;
grid-column: 1;
border-style: solid;
background-color: var(--bg-primary);
border-color: var(--bg-secondary);
border-width: 2px 2px 0px 0px;
overflow: hidden;
padding: 0px 5px;
div[data-resize-handle] {
padding: 2px;
background-color: var(--bg-secondary);
}

.editor[style*='display: none']~.term {
grid-row-start: 1;
}

.files {
grid-row: 1 / 3;
grid-column: 2;
border-style: solid;
border-color: var(--bg-secondary);
border-width: 0px 0px 2px 2px;
overflow: auto;
padding: 5px 0;
}

.plot {
grid-row: 3 / -1;
grid-column: 2;
border-style: solid;
border-color: var(--bg-secondary);
border-width: 2px 0px 0px 2px;
overflow: hidden;
.d-none + div[data-resize-handle] {
display: none !important;
}
30 changes: 22 additions & 8 deletions src/repl/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Editor from './components/Editor';
import Plot from './components/Plot';
import Files from './components/Files';
import { Readline } from 'xterm-readline';
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
import { WebR } from '../webR/webr-main';
import { CanvasMessage, PagerMessage } from '../webR/webr-chan';
import './App.css';
Expand Down Expand Up @@ -73,14 +74,27 @@ async function handlePagerMessage(msg: PagerMessage) {
function App() {
return (
<div className='repl'>
<Editor
webR={webR}
terminalInterface={terminalInterface}
filesInterface={filesInterface}
/>
<Files webR={webR} filesInterface={filesInterface} />
<Terminal webR={webR} terminalInterface={terminalInterface} />
<Plot plotInterface={plotInterface} />
<PanelGroup direction="horizontal">
<Panel defaultSize={50} minSize={20}>
<PanelGroup autoSaveId="conditional" direction="vertical">
<Editor
webR={webR}
terminalInterface={terminalInterface}
filesInterface={filesInterface}
/>
<PanelResizeHandle />
<Terminal webR={webR} terminalInterface={terminalInterface} />
</PanelGroup>
</Panel>
<PanelResizeHandle />
<Panel minSize={20}>
<PanelGroup direction="vertical">
<Files webR={webR} filesInterface={filesInterface} />
<PanelResizeHandle />
<Plot plotInterface={plotInterface} />
</PanelGroup>
</Panel>
</PanelGroup>
</div>
);
}
Expand Down
20 changes: 11 additions & 9 deletions src/repl/components/Editor.css
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
.editor {
#editor {
position: relative;
display: grid;
grid-template-rows: auto 1fr;
}

.editor-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--bg-dark);
padding: 0 5px;
padding: 5px 5px 0 5px;
}

.editor-container {
flex: 1;
overflow: auto;
}

.editor-actions {
Expand Down Expand Up @@ -94,11 +97,6 @@
color: var(--primary);
}

.editor-container {
min-width: 0;
min-height: 0;
}

.cm-editor {
border: none;
outline: none;
Expand All @@ -110,3 +108,7 @@
border: none;
outline: none;
}

.d-none {
display: none !important;
}
16 changes: 9 additions & 7 deletions src/repl/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { EditorState, Compartment, Prec } from '@codemirror/state';
import { autocompletion, CompletionContext } from '@codemirror/autocomplete';
import { keymap } from '@codemirror/view';
import { indentWithTab } from '@codemirror/commands';
import { Panel } from 'react-resizable-panels';
import { FilesInterface, TerminalInterface } from '../App';
import { r } from 'codemirror-lang-r';
import './Editor.css';
Expand Down Expand Up @@ -341,13 +342,14 @@ export function Editor({
};
}, [files, syncActiveFileState, activeFile, editorView]);

const displayStyle = files.length === 0 ? { display: 'none' } : undefined;

return (
<div role="region"
<Panel
id="editor"
role="region"
aria-label="Editor Pane"
className="editor"
style={displayStyle}
order={1}
minSize={20}
className={files.length === 0 ? "d-none" : ""}
>
<div className="editor-header">
<FileTabs
Expand All @@ -364,7 +366,7 @@ export function Editor({
ref={editorRef}
>
</div>
<p style={{ display: 'none' }} id="editor-desc">
<p className="d-none" id="editor-desc">
This component is an instance of the <a href="https://codemirror.net/">CodeMirror</a> interactive text editor.
The editor has been configured so that the Tab key controls the indentation of code.
To move focus away from the editor, press the Escape key, and then press the Tab key directly after it.
Expand All @@ -382,7 +384,7 @@ export function Editor({
<FaRegSave aria-hidden="true" className="icon" /> Save
</button>}
</div>
</div>
</Panel>
);
}

Expand Down
6 changes: 3 additions & 3 deletions src/repl/components/Files.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.files {
display: grid;
grid-template-rows: auto 1fr;
#files {
padding: 5px 0;
}

.files-header {
Expand Down Expand Up @@ -34,6 +33,7 @@
user-select: none;
padding: 0 10px;
overflow: auto;
flex-grow: 1;
color: var(--primary);
}

Expand Down
5 changes: 3 additions & 2 deletions src/repl/components/Files.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { ChangeEventHandler } from 'react';
import * as Fa from 'react-icons/fa';
import TreeView, { flattenTree, INode, ITreeViewProps } from 'react-accessible-treeview';
import { Panel } from 'react-resizable-panels';
import { WebR, WebRError } from '../../webR/webr-main';
import type { FSNode } from '../../webR/webr-main';
import { FilesInterface } from '../App';
Expand Down Expand Up @@ -235,7 +236,7 @@ export function Files({
/>;

return (
<div role="region" aria-label="Files Pane" className='files'>
<Panel id="files" role="region" aria-label="Files Pane" defaultSize={35} minSize={20}>
<div className="files-header">
<div
role="toolbar"
Expand Down Expand Up @@ -288,7 +289,7 @@ export function Files({
<div aria-label="WebAssembly Filesystem" className="directory">
{treeData[0].name ? treeView : undefined}
</div>
</div>
</Panel>
);
}

Expand Down
6 changes: 1 addition & 5 deletions src/repl/components/Plot.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
.plot {
display: grid;
grid-template-rows: auto 1fr;
}

.plot-background {
background-color: var(--bg-dark);
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
Expand Down
5 changes: 3 additions & 2 deletions src/repl/components/Plot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import './Plot.css';
import { PlotInterface } from '../App';
import { FaArrowCircleLeft, FaArrowCircleRight, FaRegSave, FaTrashAlt } from 'react-icons/fa';
import { Panel } from 'react-resizable-panels';

export function Plot({
plotInterface,
Expand Down Expand Up @@ -67,7 +68,7 @@ export function Plot({
const prevPlot = () => setSelectedCanvas((selectedCanvas === null) ? null : selectedCanvas - 1);

return (
<div role="region" aria-label="Plotting Pane" className="plot">
<Panel id="plot" role="region" aria-label="Plotting Pane" minSize={20}>
<div className="plot-header">
<div role="toolbar" aria-label="Plotting Toolbar" className="plot-actions">
<button
Expand Down Expand Up @@ -111,7 +112,7 @@ export function Plot({
<div className='plot-background'>
<div ref={plotContainerRef} className="plot-container"></div>
</div>
</div>
</Panel>
);
}

Expand Down
9 changes: 9 additions & 0 deletions src/repl/components/Terminal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#terminal {
background-color: var(--bg-primary);
padding: 0px 5px;
}

.terminal-container {
flex-grow: 1;
overflow: auto;
}
13 changes: 7 additions & 6 deletions src/repl/components/Terminal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React from 'react';
import './Terminal.css';
import { Terminal as XTerminal } from 'xterm';
import { Readline } from 'xterm-readline';
import { FitAddon } from 'xterm-addon-fit';
import { Panel } from 'react-resizable-panels';
import { TerminalInterface } from '../App';
import { WebR } from '../../webR/webr-main';
import 'xterm/css/xterm.css';
Expand Down Expand Up @@ -99,12 +101,11 @@ export function Terminal({
};
}, [readline, terminalInterface]);

return <div
role="region"
aria-label="Terminal Pane"
ref={divRef}
className='term'
></div>;
return (
<Panel id="terminal" role="region" aria-label="Terminal Pane" order={2} minSize={20}>
<div className="terminal-container" ref={divRef}></div>
</Panel>
);
}

export default Terminal;

0 comments on commit f437d4c

Please sign in to comment.