Skip to content

Commit ab57fa1

Browse files
Customize the shell layout with the settings (#6921)
* Add settings file * Add support for layout customization * Fix tests * Add `type` option * Fix opening document widgets * Fix opening documents * Add defaults for Markdown Preview * Add docs * Add screenshots * Add `@jupyterlab/attachments` * Fix integrity * Add simple UI tests for layout customization * Lint * Update Playwright Snapshots * Update Playwright Snapshots * Update docs * Add missing null --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 33a383d commit ab57fa1

File tree

14 files changed

+2715
-2407
lines changed

14 files changed

+2715
-2407
lines changed

app/package.json

Lines changed: 81 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
"watch": "webpack --config ./webpack.config.watch.js"
1111
},
1212
"resolutions": {
13-
"@codemirror/state": "~6.2.0",
14-
"@codemirror/view": "~6.11.0",
13+
"@codemirror/state": "~6.2.1",
14+
"@codemirror/view": "~6.13.2",
1515
"@jupyter-notebook/application": "~7.0.0-beta.4",
1616
"@jupyter-notebook/application-extension": "~7.0.0-beta.4",
1717
"@jupyter-notebook/console-extension": "~7.0.0-beta.4",
@@ -24,76 +24,79 @@
2424
"@jupyter-notebook/tree-extension": "~7.0.0-beta.4",
2525
"@jupyter-notebook/ui-components": "~7.0.0-beta.4",
2626
"@jupyter/ydoc": "~1.0.2",
27-
"@jupyterlab/application": "~4.0.1",
28-
"@jupyterlab/application-extension": "~4.0.1",
29-
"@jupyterlab/apputils": "~4.1.1",
30-
"@jupyterlab/apputils-extension": "~4.0.1",
31-
"@jupyterlab/cell-toolbar": "~4.0.1",
32-
"@jupyterlab/cell-toolbar-extension": "~4.0.1",
33-
"@jupyterlab/celltags-extension": "~4.0.1",
34-
"@jupyterlab/codeeditor": "~4.0.1",
35-
"@jupyterlab/codemirror": "~4.0.1",
36-
"@jupyterlab/codemirror-extension": "~4.0.1",
37-
"@jupyterlab/completer": "~4.0.1",
38-
"@jupyterlab/completer-extension": "~4.0.1",
39-
"@jupyterlab/console": "~4.0.1",
40-
"@jupyterlab/console-extension": "~4.0.1",
41-
"@jupyterlab/coreutils": "~6.0.1",
42-
"@jupyterlab/csvviewer-extension": "~4.0.1",
43-
"@jupyterlab/debugger": "~4.0.1",
44-
"@jupyterlab/debugger-extension": "~4.0.1",
45-
"@jupyterlab/docmanager": "~4.0.1",
46-
"@jupyterlab/docmanager-extension": "~4.0.1",
47-
"@jupyterlab/documentsearch": "~4.0.1",
48-
"@jupyterlab/documentsearch-extension": "~4.0.1",
49-
"@jupyterlab/extensionmanager": "~4.0.1",
50-
"@jupyterlab/extensionmanager-extension": "~4.0.1",
51-
"@jupyterlab/filebrowser": "~4.0.1",
52-
"@jupyterlab/filebrowser-extension": "~4.0.1",
53-
"@jupyterlab/fileeditor": "~4.0.1",
54-
"@jupyterlab/fileeditor-extension": "~4.0.1",
55-
"@jupyterlab/htmlviewer": "~4.0.1",
56-
"@jupyterlab/htmlviewer-extension": "~4.0.1",
57-
"@jupyterlab/hub-extension": "~4.0.1",
58-
"@jupyterlab/javascript-extension": "~4.0.1",
59-
"@jupyterlab/json-extension": "~4.0.1",
60-
"@jupyterlab/lsp": "~4.0.1",
61-
"@jupyterlab/lsp-extension": "~4.0.1",
62-
"@jupyterlab/mainmenu": "~4.0.1",
63-
"@jupyterlab/mainmenu-extension": "~4.0.1",
64-
"@jupyterlab/markedparser-extension": "~4.0.1",
65-
"@jupyterlab/mathjax-extension": "~4.0.1",
66-
"@jupyterlab/metadataform": "~4.0.1",
67-
"@jupyterlab/metadataform-extension": "~4.0.1",
68-
"@jupyterlab/notebook": "~4.0.1",
69-
"@jupyterlab/notebook-extension": "~4.0.1",
70-
"@jupyterlab/observables": "~5.0.1",
71-
"@jupyterlab/outputarea": "~4.0.1",
72-
"@jupyterlab/pdf-extension": "~4.0.1",
73-
"@jupyterlab/rendermime": "~4.0.1",
74-
"@jupyterlab/rendermime-interfaces": "~3.8.1",
75-
"@jupyterlab/running-extension": "~4.0.1",
76-
"@jupyterlab/services": "~7.0.1",
77-
"@jupyterlab/settingeditor": "~4.0.1",
78-
"@jupyterlab/settingeditor-extension": "~4.0.1",
79-
"@jupyterlab/settingregistry": "~4.0.1",
80-
"@jupyterlab/shortcuts-extension": "~4.0.1",
81-
"@jupyterlab/statedb": "~4.0.1",
82-
"@jupyterlab/statusbar": "~4.0.1",
83-
"@jupyterlab/terminal": "~4.0.1",
84-
"@jupyterlab/terminal-extension": "~4.0.1",
85-
"@jupyterlab/theme-dark-extension": "~4.0.1",
86-
"@jupyterlab/theme-light-extension": "~4.0.1",
87-
"@jupyterlab/toc-extension": "~6.0.1",
88-
"@jupyterlab/tooltip": "~4.0.1",
89-
"@jupyterlab/tooltip-extension": "~4.0.1",
90-
"@jupyterlab/translation": "~4.0.1",
91-
"@jupyterlab/translation-extension": "~4.0.1",
92-
"@jupyterlab/ui-components": "~4.0.1",
93-
"@jupyterlab/ui-components-extension": "~4.0.1",
94-
"@jupyterlab/vega5-extension": "~4.0.1",
95-
"@lezer/common": "~1.0.2",
96-
"@lezer/highlight": "~1.1.4",
27+
"@jupyterlab/application": "~4.0.2",
28+
"@jupyterlab/application-extension": "~4.0.2",
29+
"@jupyterlab/apputils": "~4.1.2",
30+
"@jupyterlab/apputils-extension": "~4.0.2",
31+
"@jupyterlab/attachments": "~4.0.2",
32+
"@jupyterlab/cell-toolbar": "~4.0.2",
33+
"@jupyterlab/cell-toolbar-extension": "~4.0.2",
34+
"@jupyterlab/celltags-extension": "~4.0.2",
35+
"@jupyterlab/codeeditor": "~4.0.2",
36+
"@jupyterlab/codemirror": "~4.0.2",
37+
"@jupyterlab/codemirror-extension": "~4.0.2",
38+
"@jupyterlab/completer": "~4.0.2",
39+
"@jupyterlab/completer-extension": "~4.0.2",
40+
"@jupyterlab/console": "~4.0.2",
41+
"@jupyterlab/console-extension": "~4.0.2",
42+
"@jupyterlab/coreutils": "~6.0.2",
43+
"@jupyterlab/csvviewer-extension": "~4.0.2",
44+
"@jupyterlab/debugger": "~4.0.2",
45+
"@jupyterlab/debugger-extension": "~4.0.2",
46+
"@jupyterlab/docmanager": "~4.0.2",
47+
"@jupyterlab/docmanager-extension": "~4.0.2",
48+
"@jupyterlab/documentsearch": "~4.0.2",
49+
"@jupyterlab/documentsearch-extension": "~4.0.2",
50+
"@jupyterlab/extensionmanager": "~4.0.2",
51+
"@jupyterlab/extensionmanager-extension": "~4.0.2",
52+
"@jupyterlab/filebrowser": "~4.0.2",
53+
"@jupyterlab/filebrowser-extension": "~4.0.2",
54+
"@jupyterlab/fileeditor": "~4.0.2",
55+
"@jupyterlab/fileeditor-extension": "~4.0.2",
56+
"@jupyterlab/htmlviewer": "~4.0.2",
57+
"@jupyterlab/htmlviewer-extension": "~4.0.2",
58+
"@jupyterlab/hub-extension": "~4.0.2",
59+
"@jupyterlab/javascript-extension": "~4.0.2",
60+
"@jupyterlab/json-extension": "~4.0.2",
61+
"@jupyterlab/lsp": "~4.0.2",
62+
"@jupyterlab/lsp-extension": "~4.0.2",
63+
"@jupyterlab/mainmenu": "~4.0.2",
64+
"@jupyterlab/mainmenu-extension": "~4.0.2",
65+
"@jupyterlab/markdownviewer": "~4.0.2",
66+
"@jupyterlab/markdownviewer-extension": "~4.0.2",
67+
"@jupyterlab/markedparser-extension": "~4.0.2",
68+
"@jupyterlab/mathjax-extension": "~4.0.2",
69+
"@jupyterlab/metadataform": "~4.0.2",
70+
"@jupyterlab/metadataform-extension": "~4.0.2",
71+
"@jupyterlab/notebook": "~4.0.2",
72+
"@jupyterlab/notebook-extension": "~4.0.2",
73+
"@jupyterlab/observables": "~5.0.2",
74+
"@jupyterlab/outputarea": "~4.0.2",
75+
"@jupyterlab/pdf-extension": "~4.0.2",
76+
"@jupyterlab/rendermime": "~4.0.2",
77+
"@jupyterlab/rendermime-interfaces": "~3.8.2",
78+
"@jupyterlab/running-extension": "~4.0.2",
79+
"@jupyterlab/services": "~7.0.2",
80+
"@jupyterlab/settingeditor": "~4.0.2",
81+
"@jupyterlab/settingeditor-extension": "~4.0.2",
82+
"@jupyterlab/settingregistry": "~4.0.2",
83+
"@jupyterlab/shortcuts-extension": "~4.0.2",
84+
"@jupyterlab/statedb": "~4.0.2",
85+
"@jupyterlab/statusbar": "~4.0.2",
86+
"@jupyterlab/terminal": "~4.0.2",
87+
"@jupyterlab/terminal-extension": "~4.0.2",
88+
"@jupyterlab/theme-dark-extension": "~4.0.2",
89+
"@jupyterlab/theme-light-extension": "~4.0.2",
90+
"@jupyterlab/toc-extension": "~6.0.2",
91+
"@jupyterlab/tooltip": "~4.0.2",
92+
"@jupyterlab/tooltip-extension": "~4.0.2",
93+
"@jupyterlab/translation": "~4.0.2",
94+
"@jupyterlab/translation-extension": "~4.0.2",
95+
"@jupyterlab/ui-components": "~4.0.2",
96+
"@jupyterlab/ui-components-extension": "~4.0.2",
97+
"@jupyterlab/vega5-extension": "~4.0.2",
98+
"@lezer/common": "~1.0.3",
99+
"@lezer/highlight": "~1.1.6",
97100
"@lumino/algorithm": "~2.0.0",
98101
"@lumino/application": "~2.1.1",
99102
"@lumino/commands": "~2.1.1",
@@ -108,7 +111,7 @@
108111
"@lumino/widgets": "~2.1.1",
109112
"react": "~18.2.0",
110113
"react-dom": "~18.2.0",
111-
"yjs": "~13.6.1"
114+
"yjs": "~13.6.2"
112115
},
113116
"dependencies": {
114117
"@jupyter-notebook/application": "^7.0.0-beta.4",
@@ -124,6 +127,7 @@
124127
"@jupyter-notebook/ui-components": "^7.0.0-beta.4",
125128
"@jupyterlab/application-extension": "^4.0.1",
126129
"@jupyterlab/apputils-extension": "^4.0.1",
130+
"@jupyterlab/attachments": "^4.0.1",
127131
"@jupyterlab/cell-toolbar-extension": "^4.0.1",
128132
"@jupyterlab/celltags-extension": "^4.0.1",
129133
"@jupyterlab/codemirror": "^4.0.1",
@@ -145,6 +149,7 @@
145149
"@jupyterlab/lsp": "^4.0.1",
146150
"@jupyterlab/lsp-extension": "^4.0.1",
147151
"@jupyterlab/mainmenu-extension": "^4.0.1",
152+
"@jupyterlab/markdownviewer-extension": "^4.0.1",
148153
"@jupyterlab/markedparser-extension": "^4.0.1",
149154
"@jupyterlab/mathjax-extension": "^4.0.1",
150155
"@jupyterlab/metadataform-extension": "^4.0.1",
@@ -322,7 +327,8 @@
322327
"@jupyterlab/fileeditor-extension": [
323328
"@jupyterlab/fileeditor-extension:completer",
324329
"@jupyterlab/fileeditor-extension:search"
325-
]
330+
],
331+
"@jupyterlab/markdownviewer-extension": true
326332
}
327333
},
328334
"singletonPackages": [
@@ -347,6 +353,7 @@
347353
"@jupyterlab/htmlviewer",
348354
"@jupyterlab/lsp",
349355
"@jupyterlab/mainmenu",
356+
"@jupyterlab/markdownviewer",
350357
"@jupyterlab/metadataform",
351358
"@jupyterlab/notebook",
352359
"@jupyterlab/observables",

docs/source/configuration.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
:maxdepth: 1
66
77
configuring/config_overview
8-
configuring/plugins
98
Security <https://jupyter-server.readthedocs.io/en/stable/operators/security.html>
109
extending/index.rst
1110
```
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Interface Customization
2+
3+
Multiple elements in the Notebook interface can be customized via the Settings Editor.
4+
5+
## Layout
6+
7+
By default some widgets are displayed in pre-defined parts of the user interface, which are often called "areas" or "regions".
8+
For example the table of contents will be displayed in the `left` area by default, while the debugger will be displayed in the `right` area.
9+
10+
However the positioning of some of these components can also be customized via the Settings Editor. Below are a few examples of how to do this.
11+
12+
### Open the Markdown Preview on the left
13+
14+
It is often useful to be able to see a rendered preview of a Markdown document while editing it.
15+
16+
By default the Markdown Preview opens on the right side of the application. However it is also possible to open it on the left side by changing the Notebook Shell settings in the Advanced Settings Editor:
17+
18+
```json
19+
{
20+
"layout": {
21+
"Markdown Preview": {
22+
"area": "left"
23+
}
24+
}
25+
}
26+
```
27+
28+
![a screenshot showing the markdown preview in Notebook 7](https://github.com/jupyter/notebook/assets/591645/3faf0823-ec6f-4d5f-a66f-d6f53dc383de)
29+
30+
### Configuring a third-party widget
31+
32+
Third-party extensions can also add widgets to the application shell. This is for example the case with the [Voila extension](https://github.com/voila-dashboards/voila), which adds a preview widget to visualize a notebook as a dashboard.
33+
34+
By default in JupyterLab the Voila Preview is added to the `main` area next to the corresponding notebook. With Notebook 7 it is possible to move the Voila Preview to the `right` area by changing the Notebook Shell setting in the Advanced Settings Editor as follows:
35+
36+
```json
37+
{
38+
"layout": {
39+
"Voila Preview": {
40+
"area": "right"
41+
}
42+
}
43+
}
44+
```
45+
46+
![a screenshot showing the voila preview in Notebook 7](https://github.com/jupyter/notebook/assets/591645/524ade3b-05de-4d3b-8ff9-089f2d38ac77)
47+
48+
```{note}
49+
Refer to the [JupyterLab Layout Documentation](https://jupyterlab.readthedocs.io/en/latest/user/interface_customization.html#layout)
50+
to learn more about the default positioning of other UI elements.
51+
```
52+
53+
## Toolbars, Menu bar and Context Menu
54+
55+
It is also possible to customize toolbars, menus and context menu entries via the Settings Editor.
56+
57+
For example the items of the notebook toolbar can be reordered, or some menu entries can be hidden.
58+
59+
```{note}
60+
Refer to the [JupyterLab Documentation](https://jupyterlab.readthedocs.io/en/latest/user/interface_customization.html)
61+
to learn more about general interface customization via the settings editor.
62+
```

docs/source/user-documentation.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ ui_components
1010
notebook_7_features
1111
examples/Notebook/examples_index.rst
1212
custom_css
13+
configuring/plugins
14+
configuring/interface_customization
1315
troubleshooting
1416
changelog
1517
```
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema",
3+
"title": "Notebook Shell",
4+
"description": "Notebook Shell layout settings.",
5+
"properties": {
6+
"layout": {
7+
"$ref": "#/definitions/layout",
8+
"type": "object",
9+
"title": "Customize shell widget positioning",
10+
"description": "Overrides default widget position in the application layout",
11+
"default": {
12+
"Markdown Preview": { "area": "right" }
13+
}
14+
}
15+
},
16+
"additionalProperties": false,
17+
"type": "object",
18+
"definitions": {
19+
"layout": {
20+
"type": "object",
21+
"properties": {
22+
"[\\w-]+": {
23+
"type": "object",
24+
"properties": {
25+
"area": {
26+
"enum": ["left", "right"]
27+
}
28+
},
29+
"additionalProperties": false
30+
}
31+
}
32+
}
33+
}
34+
}

packages/application-extension/src/index.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -384,14 +384,36 @@ const rendermime: JupyterFrontEndPlugin<IRenderMimeRegistry> = {
384384
*/
385385
const shell: JupyterFrontEndPlugin<INotebookShell> = {
386386
id: '@jupyter-notebook/application-extension:shell',
387-
activate: (app: JupyterFrontEnd) => {
387+
autoStart: true,
388+
provides: INotebookShell,
389+
optional: [ISettingRegistry],
390+
activate: (
391+
app: JupyterFrontEnd,
392+
settingRegistry: ISettingRegistry | null
393+
) => {
388394
if (!(app.shell instanceof NotebookShell)) {
389395
throw new Error(`${shell.id} did not find a NotebookShell instance.`);
390396
}
391-
return app.shell;
397+
const notebookShell = app.shell;
398+
399+
if (settingRegistry) {
400+
settingRegistry
401+
.load(shell.id)
402+
.then((settings) => {
403+
// Add a layer of customization to support app shell mode
404+
const customLayout = settings.composite['layout'] as any;
405+
406+
// Restore the layout.
407+
void notebookShell.restoreLayout(customLayout);
408+
})
409+
.catch((reason) => {
410+
console.error('Fail to load settings for the layout restorer.');
411+
console.error(reason);
412+
});
413+
}
414+
415+
return notebookShell;
392416
},
393-
autoStart: true,
394-
provides: INotebookShell,
395417
};
396418

397419
/**

0 commit comments

Comments
 (0)