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:
tao.chen
2026-07-21 18:41:01 +08:00
co-authored by Claude
parent 2fc584d70f
commit 263232bea4
6 changed files with 45 additions and 11 deletions
+9 -3
View File
@@ -5,6 +5,7 @@ import {
import { INotebookTracker, NotebookPanel } from '@jupyterlab/notebook';
import { ToolbarButton, MainAreaWidget } from '@jupyterlab/apputils';
import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { saveIcon } from '@jupyterlab/ui-components';
import { requestAPI } from './request';
import { registerCommands, CommandIDs } from './commands';
@@ -59,7 +60,11 @@ const plugin: JupyterFrontEndPlugin<void> = {
onOpenDiff: openDiff
});
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 });
// Keep the model in sync with the current notebook.
@@ -73,13 +78,14 @@ const plugin: JupyterFrontEndPlugin<void> = {
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
// returned widget in the *main area* (a new tab), not on the toolbar.
// The toolbar wants panel.toolbar.addItem directly.
const addCommitButton = (panelHost: NotebookPanel) => {
const button = new ToolbarButton({
label: '保存快照',
icon: saveIcon,
tooltip: '保存当前 notebook 为快照',
onClick: () => {
void app.commands.execute(CommandIDs.commit);
+7 -2
View File
@@ -1,6 +1,7 @@
import * as React from 'react';
import { ReactWidget } from '@jupyterlab/apputils';
import { ServerConnection } from '@jupyterlab/services';
import { refreshIcon } from '@jupyterlab/ui-components';
import { getSnapshotContent } from '../api';
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-toolbar">
<button
className="jp-snapshot-panel-refresh-button"
className={
'jp-snapshot-panel-refresh-button' +
(model.loading ? ' is-loading' : '')
}
onClick={() => {
void model.refresh();
}}
disabled={model.loading}
title="重新拉取版本列表"
aria-label="刷新"
>
{model.loading ? '刷新中…' : '刷新'}
<refreshIcon.react className="jp-Icon jp-Icon-16" tag="span" />
</button>
</div>
{model.loading && model.versions.length === 0 ? (