feat: replace text buttons with icons (tooltip on hover)
Replaces the two visible 'button-like' affordances with LabIcon glyphs so the sidebar and toolbar stay compact; the explanatory text moves to the hover tooltip. Changes: - Toolbar 'Save Snapshot' button: text label -> saveIcon (floppy), tooltip '保存当前 notebook 为快照' - Sidebar panel '快照历史' text label -> saveIcon + caption='快照历史' (the panel tab is now icon-only) - Sidebar refresh button: text -> refreshIcon with a 1s rotate animation while loading Dependencies: - Adds @jupyterlab/ui-components to package.json (source of the standard LabIcon set: saveIcon, refreshIcon, historyIcon) Style: - New .jp-snapshot-panel-refresh-button sizing (28x24 fixed box, centered icon) and .is-loading spin keyframes - @keyframes jp-snapshot-spin applied to the icon's .jp-Icon element Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -61,6 +61,7 @@
|
|||||||
"@jupyterlab/notebook": "^4.0.0",
|
"@jupyterlab/notebook": "^4.0.0",
|
||||||
"@jupyterlab/services": "^7.0.0",
|
"@jupyterlab/services": "^7.0.0",
|
||||||
"@jupyterlab/settingregistry": "^4.0.0",
|
"@jupyterlab/settingregistry": "^4.0.0",
|
||||||
|
"@jupyterlab/ui-components": "^4.0.0",
|
||||||
"@lumino/signaling": "^2.0.0",
|
"@lumino/signaling": "^2.0.0",
|
||||||
"@lumino/widgets": "^2.0.0",
|
"@lumino/widgets": "^2.0.0",
|
||||||
"diff": "^5.2.0",
|
"diff": "^5.2.0",
|
||||||
|
|||||||
+9
-3
@@ -5,6 +5,7 @@ import {
|
|||||||
import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook';
|
import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook';
|
||||||
import { ToolbarButton, MainAreaWidget } from '@jupyterlab/apputils';
|
import { ToolbarButton, MainAreaWidget } from '@jupyterlab/apputils';
|
||||||
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
||||||
|
import { saveIcon } from '@jupyterlab/ui-components';
|
||||||
|
|
||||||
import { requestAPI } from './request';
|
import { requestAPI } from './request';
|
||||||
import { registerCommands, CommandIDs } from './commands';
|
import { registerCommands, CommandIDs } from './commands';
|
||||||
@@ -59,7 +60,11 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|||||||
onOpenDiff: openDiff
|
onOpenDiff: openDiff
|
||||||
});
|
});
|
||||||
panel.id = 'snapshot:panel';
|
panel.id = 'snapshot:panel';
|
||||||
panel.title.label = '快照历史';
|
// Icon-only panel tab: the title text becomes a hover caption so the
|
||||||
|
// sidebar stays compact. saveIcon is reused for visual consistency with
|
||||||
|
// the commit toolbar button (both signal "save" semantics).
|
||||||
|
panel.title.icon = saveIcon;
|
||||||
|
panel.title.caption = '快照历史';
|
||||||
app.shell.add(panel, 'left', { rank: 200 });
|
app.shell.add(panel, 'left', { rank: 200 });
|
||||||
|
|
||||||
// Keep the model in sync with the current notebook.
|
// Keep the model in sync with the current notebook.
|
||||||
@@ -73,13 +78,14 @@ const plugin: JupyterFrontEndPlugin<void> = {
|
|||||||
|
|
||||||
registerCommands(app, tracker, model);
|
registerCommands(app, tracker, model);
|
||||||
|
|
||||||
// Add a "保存快照" button to every notebook panel's toolbar.
|
// Add an icon-only "保存快照" button to every notebook panel's toolbar.
|
||||||
|
// The tooltip on hover carries the full description.
|
||||||
// NOTE: docRegistry.addWidgetExtension('Notebook', ...) places its
|
// NOTE: docRegistry.addWidgetExtension('Notebook', ...) places its
|
||||||
// returned widget in the *main area* (a new tab), not on the toolbar.
|
// returned widget in the *main area* (a new tab), not on the toolbar.
|
||||||
// The toolbar wants panel.toolbar.addItem directly.
|
// The toolbar wants panel.toolbar.addItem directly.
|
||||||
const addCommitButton = (panelHost: NotebookPanel) => {
|
const addCommitButton = (panelHost: NotebookPanel) => {
|
||||||
const button = new ToolbarButton({
|
const button = new ToolbarButton({
|
||||||
label: '保存快照',
|
icon: saveIcon,
|
||||||
tooltip: '保存当前 notebook 为快照',
|
tooltip: '保存当前 notebook 为快照',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
void app.commands.execute(CommandIDs.commit);
|
void app.commands.execute(CommandIDs.commit);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ReactWidget } from '@jupyterlab/apputils';
|
import { ReactWidget } from '@jupyterlab/apputils';
|
||||||
import { ServerConnection } from '@jupyterlab/services';
|
import { ServerConnection } from '@jupyterlab/services';
|
||||||
|
import { refreshIcon } from '@jupyterlab/ui-components';
|
||||||
|
|
||||||
import { getSnapshotContent } from '../api';
|
import { getSnapshotContent } from '../api';
|
||||||
import { INotebook } from '../diff';
|
import { INotebook } from '../diff';
|
||||||
@@ -50,14 +51,18 @@ const Panel: React.FC<PanelProps> = ({ model, app, tracker, serverSettings, onOp
|
|||||||
<div className="jp-snapshot-panel-container">
|
<div className="jp-snapshot-panel-container">
|
||||||
<div className="jp-snapshot-panel-toolbar">
|
<div className="jp-snapshot-panel-toolbar">
|
||||||
<button
|
<button
|
||||||
className="jp-snapshot-panel-refresh-button"
|
className={
|
||||||
|
'jp-snapshot-panel-refresh-button' +
|
||||||
|
(model.loading ? ' is-loading' : '')
|
||||||
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
void model.refresh();
|
void model.refresh();
|
||||||
}}
|
}}
|
||||||
disabled={model.loading}
|
disabled={model.loading}
|
||||||
title="重新拉取版本列表"
|
title="重新拉取版本列表"
|
||||||
|
aria-label="刷新"
|
||||||
>
|
>
|
||||||
{model.loading ? '刷新中…' : '刷新'}
|
<refreshIcon.react className="jp-Icon jp-Icon-16" tag="span" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{model.loading && model.versions.length === 0 ? (
|
{model.loading && model.versions.length === 0 ? (
|
||||||
|
|||||||
+21
-2
@@ -26,13 +26,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.jp-snapshot-panel-refresh-button {
|
.jp-snapshot-panel-refresh-button {
|
||||||
font-size: 0.8em;
|
display: inline-flex;
|
||||||
padding: 2px 8px;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 28px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 0;
|
||||||
border: 1px solid var(--jp-border-color2, #ccc);
|
border: 1px solid var(--jp-border-color2, #ccc);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background: var(--jp-layout-color2, #f5f5f5);
|
background: var(--jp-layout-color2, #f5f5f5);
|
||||||
color: var(--jp-ui-font-color1, #333);
|
color: var(--jp-ui-font-color1, #333);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
line-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jp-snapshot-panel-refresh-button:hover:not(:disabled) {
|
.jp-snapshot-panel-refresh-button:hover:not(:disabled) {
|
||||||
@@ -44,6 +49,20 @@
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jp-snapshot-panel-refresh-button.is-loading svg,
|
||||||
|
.jp-snapshot-panel-refresh-button.is-loading .jp-Icon {
|
||||||
|
animation: jp-snapshot-spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes jp-snapshot-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.jp-snapshot-panel-empty {
|
.jp-snapshot-panel-empty {
|
||||||
color: var(--jp-ui-font-color2, #555);
|
color: var(--jp-ui-font-color2, #555);
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
|||||||
@@ -1969,7 +1969,6 @@ wheels = [
|
|||||||
name = "snapshot"
|
name = "snapshot"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "boto3" },
|
|
||||||
{ name = "jupyter-server" },
|
{ name = "jupyter-server" },
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1978,6 +1977,9 @@ dev = [
|
|||||||
{ name = "jupyter-builder" },
|
{ name = "jupyter-builder" },
|
||||||
{ name = "jupyterlab" },
|
{ name = "jupyterlab" },
|
||||||
]
|
]
|
||||||
|
s3 = [
|
||||||
|
{ name = "boto3" },
|
||||||
|
]
|
||||||
test = [
|
test = [
|
||||||
{ name = "coverage" },
|
{ name = "coverage" },
|
||||||
{ name = "pytest" },
|
{ name = "pytest" },
|
||||||
@@ -1988,7 +1990,7 @@ test = [
|
|||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "boto3", specifier = ">=1.43.52" },
|
{ name = "boto3", marker = "extra == 's3'", specifier = ">=1.34.0" },
|
||||||
{ name = "coverage", marker = "extra == 'test'" },
|
{ name = "coverage", marker = "extra == 'test'" },
|
||||||
{ name = "jupyter-builder", marker = "extra == 'dev'", specifier = ">=1.0.0" },
|
{ name = "jupyter-builder", marker = "extra == 'dev'", specifier = ">=1.0.0" },
|
||||||
{ name = "jupyter-server", specifier = ">=2.4.0,<3" },
|
{ name = "jupyter-server", specifier = ">=2.4.0,<3" },
|
||||||
@@ -1998,7 +2000,7 @@ requires-dist = [
|
|||||||
{ name = "pytest-cov", marker = "extra == 'test'" },
|
{ name = "pytest-cov", marker = "extra == 'test'" },
|
||||||
{ name = "pytest-jupyter", extras = ["server"], marker = "extra == 'test'", specifier = ">=0.6.0" },
|
{ name = "pytest-jupyter", extras = ["server"], marker = "extra == 'test'", specifier = ">=0.6.0" },
|
||||||
]
|
]
|
||||||
provides-extras = ["dev", "test"]
|
provides-extras = ["dev", "s3", "test"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "soupsieve"
|
name = "soupsieve"
|
||||||
|
|||||||
@@ -2785,7 +2785,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@jupyterlab/ui-components@npm:^4.6.1":
|
"@jupyterlab/ui-components@npm:^4.0.0, @jupyterlab/ui-components@npm:^4.6.1":
|
||||||
version: 4.6.1
|
version: 4.6.1
|
||||||
resolution: "@jupyterlab/ui-components@npm:4.6.1"
|
resolution: "@jupyterlab/ui-components@npm:4.6.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9222,6 +9222,7 @@ __metadata:
|
|||||||
"@jupyterlab/settingregistry": ^4.0.0
|
"@jupyterlab/settingregistry": ^4.0.0
|
||||||
"@jupyterlab/testing": ^4.6.1
|
"@jupyterlab/testing": ^4.6.1
|
||||||
"@jupyterlab/testutils": ^4.0.0
|
"@jupyterlab/testutils": ^4.0.0
|
||||||
|
"@jupyterlab/ui-components": ^4.0.0
|
||||||
"@lumino/signaling": ^2.0.0
|
"@lumino/signaling": ^2.0.0
|
||||||
"@lumino/widgets": ^2.0.0
|
"@lumino/widgets": ^2.0.0
|
||||||
"@module-federation/runtime-tools": ^2.0.0
|
"@module-federation/runtime-tools": ^2.0.0
|
||||||
|
|||||||
Reference in New Issue
Block a user