xtralab 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +27 -11
  2. package/lib/commandBar/index.d.ts +14 -0
  3. package/lib/commandBar/index.js +114 -0
  4. package/lib/fileBrowser/fileBrowser.js +6 -1
  5. package/lib/highlight/index.d.ts +15 -0
  6. package/lib/highlight/index.js +214 -0
  7. package/lib/index.js +13 -1
  8. package/lib/launcher/agents.d.ts +18 -1
  9. package/lib/launcher/agents.js +47 -4
  10. package/lib/launcher/editorRegistry.js +5 -3
  11. package/lib/launcher/editors.d.ts +17 -2
  12. package/lib/launcher/editors.js +31 -5
  13. package/lib/launcher/index.js +7 -1
  14. package/lib/launcher/schemaDefaults.d.ts +15 -0
  15. package/lib/launcher/schemaDefaults.js +44 -0
  16. package/lib/omnibox/files.d.ts +7 -0
  17. package/lib/omnibox/files.js +50 -0
  18. package/lib/omnibox/index.d.ts +14 -0
  19. package/lib/omnibox/index.js +83 -0
  20. package/lib/omnibox/model.d.ts +45 -0
  21. package/lib/omnibox/model.js +142 -0
  22. package/lib/omnibox/tokens.d.ts +23 -0
  23. package/lib/omnibox/tokens.js +11 -0
  24. package/lib/omnibox/widget.d.ts +36 -0
  25. package/lib/omnibox/widget.js +161 -0
  26. package/lib/searchReplace/index.d.ts +25 -0
  27. package/lib/searchReplace/index.js +68 -0
  28. package/lib/showOutput/index.d.ts +17 -0
  29. package/lib/showOutput/index.js +154 -0
  30. package/lib/terminals/index.d.ts +4 -0
  31. package/lib/terminals/index.js +65 -16
  32. package/lib/terminals/model.d.ts +56 -3
  33. package/lib/terminals/model.js +261 -5
  34. package/lib/terminals/widget.d.ts +3 -1
  35. package/lib/terminals/widget.js +11 -3
  36. package/lib/walkthrough/index.d.ts +14 -0
  37. package/lib/walkthrough/index.js +162 -0
  38. package/lib/walkthrough/panel.d.ts +54 -0
  39. package/lib/walkthrough/panel.js +98 -0
  40. package/package.json +1 -1
  41. package/schema/launcher.json +5 -4
  42. package/schema/terminals.json +15 -0
  43. package/src/commandBar/index.ts +165 -0
  44. package/src/fileBrowser/fileBrowser.tsx +8 -1
  45. package/src/highlight/index.ts +251 -0
  46. package/src/index.ts +13 -1
  47. package/src/launcher/agents.ts +53 -3
  48. package/src/launcher/editorRegistry.ts +8 -4
  49. package/src/launcher/editors.ts +37 -4
  50. package/src/launcher/index.ts +7 -1
  51. package/src/launcher/schemaDefaults.ts +53 -0
  52. package/src/omnibox/files.ts +68 -0
  53. package/src/omnibox/index.ts +105 -0
  54. package/src/omnibox/model.ts +210 -0
  55. package/src/omnibox/tokens.ts +29 -0
  56. package/src/omnibox/widget.tsx +322 -0
  57. package/src/searchReplace/index.ts +86 -0
  58. package/src/showOutput/index.ts +199 -0
  59. package/src/terminals/index.ts +79 -16
  60. package/src/terminals/model.ts +304 -3
  61. package/src/terminals/widget.tsx +21 -4
  62. package/src/walkthrough/index.ts +202 -0
  63. package/src/walkthrough/panel.ts +152 -0
  64. package/style/commandBar.css +104 -0
  65. package/style/highlight.css +11 -0
  66. package/style/index.css +5 -0
  67. package/style/index.js +5 -0
  68. package/style/omnibox.css +120 -0
  69. package/style/showOutput.css +11 -0
  70. package/style/terminals.css +54 -10
  71. package/style/walkthrough.css +80 -0
@@ -0,0 +1,152 @@
1
+ import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
2
+ import type { TranslationBundle } from '@jupyterlab/translation';
3
+ import { fileIcon } from '@jupyterlab/ui-components';
4
+ import type { CommandRegistry } from '@lumino/commands';
5
+ import type { ReadonlyPartialJSONValue } from '@lumino/coreutils';
6
+ import type { Message } from '@lumino/messaging';
7
+ import { Panel, Widget } from '@lumino/widgets';
8
+
9
+ /** Command the jump links dispatch; keeps the panel decoupled from the plugin. */
10
+ const HIGHLIGHT_LINES_COMMAND = 'xtralab:highlight-lines';
11
+
12
+ /** A rich visual embedded in a step (rendered through the rendermime registry). */
13
+ export interface IWalkthroughMedia {
14
+ mimeType: string;
15
+ data: ReadonlyPartialJSONValue;
16
+ }
17
+
18
+ /** One step of a walkthrough. Every field is optional, but a step needs at least one. */
19
+ export interface IWalkthroughStep {
20
+ title?: string;
21
+ body?: string;
22
+ media?: IWalkthroughMedia;
23
+ path?: string;
24
+ line?: number;
25
+ endLine?: number;
26
+ }
27
+
28
+ export namespace WalkthroughPanel {
29
+ export interface IOptions {
30
+ rendermime: IRenderMimeRegistry;
31
+ commands: CommandRegistry;
32
+ trans: TranslationBundle;
33
+ }
34
+ }
35
+
36
+ /**
37
+ * A read-only, scrollable column of walkthrough steps for the side area.
38
+ *
39
+ * The agent appends steps as it narrates, so the explanation lives beside the
40
+ * code the user is looking at and persists for them to read at their own pace,
41
+ * rather than scrolling away in the chat. Each step renders Markdown (with code
42
+ * snippets, Mermaid, math), can embed a rich visual, and can offer a button
43
+ * that opens the referenced file and highlights its lines.
44
+ */
45
+ export class WalkthroughPanel extends Panel {
46
+ constructor(options: WalkthroughPanel.IOptions) {
47
+ super();
48
+ this._rendermime = options.rendermime;
49
+ this._commands = options.commands;
50
+ this._trans = options.trans;
51
+ this.addClass('jp-xtralab-Walkthrough');
52
+ }
53
+
54
+ /** Remove every step, leaving an empty panel. */
55
+ clear(): void {
56
+ while (this.widgets.length > 0) {
57
+ this.widgets[0].dispose();
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Dispose on close (e.g. the close button when the panel has been dragged to
63
+ * the main area) rather than leaving a detached, reusable widget behind. The
64
+ * next `xtralab:walkthrough` call recreates the panel in the side area.
65
+ */
66
+ protected onCloseRequest(msg: Message): void {
67
+ super.onCloseRequest(msg);
68
+ this.dispose();
69
+ }
70
+
71
+ /** Append a step and scroll it into view. */
72
+ async addStep(step: IWalkthroughStep): Promise<void> {
73
+ const card = new Panel();
74
+ card.addClass('jp-xtralab-Walkthrough-step');
75
+ this.addWidget(card);
76
+
77
+ if (step.title) {
78
+ const heading = new Widget({ node: document.createElement('h3') });
79
+ heading.addClass('jp-xtralab-Walkthrough-stepTitle');
80
+ heading.node.textContent = step.title;
81
+ card.addWidget(heading);
82
+ }
83
+
84
+ if (step.body) {
85
+ await this._render(card, 'text/markdown', step.body);
86
+ }
87
+
88
+ if (step.media && typeof step.media.mimeType === 'string') {
89
+ await this._render(card, step.media.mimeType, step.media.data);
90
+ }
91
+
92
+ if (step.path) {
93
+ card.addWidget(this._jumpButton(step.path, step.line, step.endLine));
94
+ }
95
+
96
+ // Bring the newest step into view.
97
+ this.node.scrollTop = this.node.scrollHeight;
98
+ }
99
+
100
+ private async _render(
101
+ parent: Panel,
102
+ mimeType: string,
103
+ data: ReadonlyPartialJSONValue
104
+ ): Promise<void> {
105
+ const bundle = { [mimeType]: data };
106
+ const chosen = this._rendermime.preferredMimeType(bundle, 'any');
107
+ if (!chosen) {
108
+ return;
109
+ }
110
+ const renderer = this._rendermime.createRenderer(chosen);
111
+ renderer.addClass('jp-xtralab-Walkthrough-content');
112
+ parent.addWidget(renderer);
113
+ await renderer.renderModel(
114
+ this._rendermime.createModel({ data: bundle, trusted: true })
115
+ );
116
+ }
117
+
118
+ private _jumpButton(path: string, line?: number, endLine?: number): Widget {
119
+ const node = document.createElement('div');
120
+ node.className = 'jp-xtralab-Walkthrough-jumpRow';
121
+ const where = line ? `${path}:${line}` : path;
122
+
123
+ const button = document.createElement('button');
124
+ button.type = 'button';
125
+ button.className = 'jp-xtralab-Walkthrough-jump';
126
+ button.title = this._trans.__('Open %1 in the editor', where);
127
+
128
+ const icon = fileIcon.element({
129
+ tag: 'span',
130
+ className: 'jp-xtralab-Walkthrough-jumpIcon'
131
+ });
132
+ const label = document.createElement('span');
133
+ label.className = 'jp-xtralab-Walkthrough-jumpLabel';
134
+ label.textContent = where;
135
+ button.appendChild(icon);
136
+ button.appendChild(label);
137
+ node.appendChild(button);
138
+
139
+ button.addEventListener('click', () => {
140
+ void this._commands.execute(HIGHLIGHT_LINES_COMMAND, {
141
+ path,
142
+ line,
143
+ endLine
144
+ });
145
+ });
146
+ return new Widget({ node });
147
+ }
148
+
149
+ private _rendermime: IRenderMimeRegistry;
150
+ private _commands: CommandRegistry;
151
+ private _trans: TranslationBundle;
152
+ }
@@ -0,0 +1,104 @@
1
+ /* Centered command bar in the top area (xtralab:command-bar). */
2
+
3
+ /*
4
+ * The bar is an overlay centered over the whole top panel rather than a flex
5
+ * item, so its position does not shift with the (variable) width of the menu
6
+ * bar on its left or the sidebar toggle button on its right. `#jp-top-panel`
7
+ * is a `.lm-Widget`, which Lumino renders `position: relative`, so this
8
+ * absolute box is centered against the full width of the top bar.
9
+ *
10
+ * `pointer-events: none` here (with `auto` restored on the pill below) keeps
11
+ * only the pill clickable: the transparent strips above and below it let
12
+ * clicks fall through to whatever sits beneath the overlay.
13
+ *
14
+ * The `z-index` must clear JupyterLab core's settings-driven "Topbar toolbar"
15
+ * (`#jp-top-bar`, added to the top area at rank 900), which is a `.jp-Toolbar`
16
+ * at `z-index: 8` that grows to fill the center and paints an opaque
17
+ * `--jp-toolbar-background`. Sitting one above it lets the centered pill show
18
+ * through; that toolbar is empty by default, so the overlay covers blank
19
+ * space rather than hiding any toolbar items.
20
+ */
21
+ .jp-xtralab-CommandBar {
22
+ position: absolute;
23
+ top: 0;
24
+ bottom: 0;
25
+ left: 50%;
26
+ z-index: 9;
27
+ display: flex;
28
+ align-items: center;
29
+ transform: translateX(-50%);
30
+ pointer-events: none;
31
+ }
32
+
33
+ .jp-xtralab-CommandBar-button {
34
+ display: flex;
35
+ flex: 0 0 auto;
36
+ gap: 6px;
37
+ align-items: center;
38
+ width: clamp(160px, 16vw, 220px);
39
+ height: 20px;
40
+ padding: 0 8px;
41
+ margin: 0;
42
+ overflow: hidden;
43
+ font-family: var(--jp-ui-font-family);
44
+ font-size: var(--jp-ui-font-size1);
45
+ color: var(--jp-ui-font-color2);
46
+ text-align: left;
47
+ cursor: pointer;
48
+
49
+ /* The theme's input-field fill, so the pill reads as a search box and tracks
50
+ each theme's input styling across light and dark (a flat layout color is
51
+ near-black in some dark themes). */
52
+ background: var(--jp-input-background);
53
+ border: var(--jp-border-width) solid var(--jp-border-color1);
54
+ border-radius: 10px;
55
+ appearance: none;
56
+ pointer-events: auto;
57
+ }
58
+
59
+ .jp-xtralab-CommandBar-button:hover {
60
+ color: var(--jp-ui-font-color1);
61
+ border-color: var(--jp-border-color0);
62
+ }
63
+
64
+ .jp-xtralab-CommandBar-button:focus-visible {
65
+ outline: var(--jp-border-width) solid var(--jp-brand-color1);
66
+ outline-offset: 1px;
67
+ }
68
+
69
+ .jp-xtralab-CommandBar-icon {
70
+ display: flex;
71
+ flex: 0 0 auto;
72
+ align-items: center;
73
+ }
74
+
75
+ .jp-xtralab-CommandBar-icon svg {
76
+ width: 14px;
77
+ height: 14px;
78
+ }
79
+
80
+ /* The built-in JupyterLab search icon (@jupyterlab/ui-components) paints with a
81
+ fixed `jp-icon3` theme gray; override it to currentColor so the magnifier
82
+ tracks the pill's text color and brightens with the label on hover. */
83
+ .jp-xtralab-CommandBar-button .jp-icon3[fill] {
84
+ fill: currentcolor;
85
+ }
86
+
87
+ .jp-xtralab-CommandBar-label {
88
+ flex: 1 1 auto;
89
+ overflow: hidden;
90
+ text-overflow: ellipsis;
91
+ white-space: nowrap;
92
+ }
93
+
94
+ /* Keyboard-shortcut hint, pushed to the trailing edge by the growing label. */
95
+ .jp-xtralab-CommandBar-shortcut {
96
+ flex: 0 0 auto;
97
+ margin-left: 6px;
98
+ padding: 1px 4px;
99
+ font-size: var(--jp-ui-font-size0);
100
+ line-height: 1.2;
101
+ color: var(--jp-ui-font-color3);
102
+ border: var(--jp-border-width) solid var(--jp-border-color1);
103
+ border-radius: 4px;
104
+ }
@@ -0,0 +1,11 @@
1
+ /*
2
+ * Line highlight applied by `xtralab:highlight-lines`. The class lands on the
3
+ * CodeMirror line wrapper (`.cm-line`), so the tint spans the full editor width
4
+ * and a left accent bar marks the run. The translucent background keeps the
5
+ * code legible on both light and dark themes.
6
+ */
7
+
8
+ .jp-xtralab-highlightLine {
9
+ background-color: rgb(250 204 21 / 18%);
10
+ box-shadow: inset 2px 0 0 0 var(--jp-brand-color1);
11
+ }
package/style/index.css CHANGED
@@ -1,8 +1,13 @@
1
1
  @import url('base.css');
2
+ @import url('commandBar.css');
2
3
  @import url('editorBreadcrumbs.css');
3
4
  @import url('git.css');
5
+ @import url('highlight.css');
4
6
  @import url('launcher.css');
7
+ @import url('omnibox.css');
8
+ @import url('showOutput.css');
5
9
  @import url('sidebar.css');
6
10
  @import url('tabs.css');
7
11
  @import url('terminals.css');
8
12
  @import url('topBar.css');
13
+ @import url('walkthrough.css');
package/style/index.js CHANGED
@@ -1,7 +1,12 @@
1
1
  import './base.css';
2
+ import './commandBar.css';
2
3
  import './git.css';
4
+ import './highlight.css';
3
5
  import './launcher.css';
6
+ import './omnibox.css';
7
+ import './showOutput.css';
4
8
  import './sidebar.css';
5
9
  import './tabs.css';
6
10
  import './terminals.css';
7
11
  import './topBar.css';
12
+ import './walkthrough.css';
@@ -0,0 +1,120 @@
1
+ /* Omnibox overlay (xtralab:omnibox): a centered search box over the shell. */
2
+
3
+ /*
4
+ * The widget node is attached to `document.body` (outside the shell) and only
5
+ * carries theme variables via `jp-ThemedContainer`; the React tree renders the
6
+ * fixed full-screen overlay below it.
7
+ */
8
+ .jp-xtralab-Omnibox {
9
+ position: absolute;
10
+ }
11
+
12
+ /* Transparent full-viewport layer that centers the panel and catches
13
+ click-outside to dismiss. */
14
+ .jp-xtralab-Omnibox-overlay {
15
+ position: fixed;
16
+ inset: 0;
17
+ z-index: 10001;
18
+ display: flex;
19
+ align-items: flex-start;
20
+ justify-content: center;
21
+ }
22
+
23
+ .jp-xtralab-Omnibox-panel {
24
+ display: flex;
25
+ flex-direction: column;
26
+ width: min(640px, 92vw);
27
+ max-height: 60vh;
28
+ overflow: hidden;
29
+
30
+ /* Drop just below the top bar so it reads as a command-center dropdown. */
31
+ margin-top: calc(var(--jp-private-menubar-height, 28px) + 4px);
32
+ background: var(--jp-layout-color1);
33
+ border: var(--jp-border-width) solid var(--jp-border-color1);
34
+ border-radius: 4px;
35
+ box-shadow: var(--jp-elevation-z6);
36
+ }
37
+
38
+ .jp-xtralab-Omnibox-input {
39
+ padding: 11px 14px;
40
+ font-family: var(--jp-ui-font-family);
41
+ font-size: var(--jp-ui-font-size2);
42
+ color: var(--jp-ui-font-color0);
43
+ background: transparent;
44
+ border: none;
45
+ border-bottom: var(--jp-border-width) solid var(--jp-border-color2);
46
+ outline: none;
47
+ }
48
+
49
+ .jp-xtralab-Omnibox-input::placeholder {
50
+ color: var(--jp-ui-font-color3);
51
+ }
52
+
53
+ .jp-xtralab-Omnibox-results {
54
+ padding: 4px 0;
55
+ overflow-y: auto;
56
+ }
57
+
58
+ .jp-xtralab-Omnibox-sectionHeader {
59
+ padding: 6px 14px 2px;
60
+ font-size: var(--jp-ui-font-size0);
61
+ font-weight: 600;
62
+ color: var(--jp-ui-font-color2);
63
+ text-transform: uppercase;
64
+ letter-spacing: 0.04em;
65
+ }
66
+
67
+ .jp-xtralab-Omnibox-item {
68
+ display: flex;
69
+ gap: 8px;
70
+ align-items: center;
71
+ padding: 5px 14px;
72
+ font-size: var(--jp-ui-font-size1);
73
+ color: var(--jp-ui-font-color1);
74
+ cursor: pointer;
75
+ }
76
+
77
+ .jp-xtralab-Omnibox-item.jp-mod-active {
78
+ background: var(--jp-layout-color2);
79
+ }
80
+
81
+ .jp-xtralab-Omnibox-itemIcon {
82
+ display: flex;
83
+ flex: 0 0 auto;
84
+ align-items: center;
85
+ width: 16px;
86
+ height: 16px;
87
+ }
88
+
89
+ .jp-xtralab-Omnibox-itemIcon svg {
90
+ width: 16px;
91
+ height: 16px;
92
+ }
93
+
94
+ .jp-xtralab-Omnibox-itemLabel {
95
+ flex: 1 1 auto;
96
+ overflow: hidden;
97
+ white-space: nowrap;
98
+ text-overflow: ellipsis;
99
+ }
100
+
101
+ .jp-xtralab-Omnibox-match {
102
+ font-weight: 600;
103
+ color: var(--jp-ui-font-color0);
104
+ }
105
+
106
+ .jp-xtralab-Omnibox-itemCaption {
107
+ flex: 0 1 auto;
108
+ max-width: 45%;
109
+ overflow: hidden;
110
+ font-size: var(--jp-ui-font-size0);
111
+ color: var(--jp-ui-font-color3);
112
+ white-space: nowrap;
113
+ text-overflow: ellipsis;
114
+ }
115
+
116
+ .jp-xtralab-Omnibox-empty {
117
+ padding: 14px;
118
+ font-size: var(--jp-ui-font-size1);
119
+ color: var(--jp-ui-font-color2);
120
+ }
@@ -0,0 +1,11 @@
1
+ /*
2
+ * The panel `xtralab:show` renders into. It holds a single rendered output and
3
+ * scrolls when that output is taller (or wider) than the panel, which matters
4
+ * most in the narrow side area.
5
+ */
6
+
7
+ .jp-xtralab-ShowPanel {
8
+ overflow: auto;
9
+ padding: 8px;
10
+ background: var(--jp-layout-color1);
11
+ }
@@ -1,9 +1,11 @@
1
1
  /*
2
2
  * Left-sidebar panel listing running terminal sessions. Each row shows
3
- * the session's real (program-published) title and an inline shutdown
4
- * button that fades in on hover; the header carries the panel title and
5
- * a "new terminal" button. Colors and spacing pull from `--jp-*` custom
6
- * properties so the panel tracks the active JupyterLab theme.
3
+ * the session's real (program-published) title, a smaller line below it
4
+ * with the latest output from a running coding agent, and an inline
5
+ * shutdown button that fades in on hover; the header carries the panel
6
+ * title and a "new terminal" button. Colors and spacing pull from
7
+ * `--jp-*` custom properties so the panel tracks the active JupyterLab
8
+ * theme.
7
9
  */
8
10
 
9
11
  .jp-xtralab-Terminals {
@@ -105,7 +107,7 @@
105
107
  .jp-xtralab-Terminals-item {
106
108
  display: flex;
107
109
  align-items: stretch;
108
- height: 28px;
110
+ min-height: 28px;
109
111
  }
110
112
 
111
113
  .jp-xtralab-Terminals-item:hover {
@@ -113,17 +115,19 @@
113
115
  }
114
116
 
115
117
  /*
116
- * The main click target: terminal icon + label, filling the row so the
117
- * whole strip activates the session. The close button sits to its right
118
- * and intercepts its own clicks via the React handler.
118
+ * The main click target: terminal icon + the title/activity text block,
119
+ * filling the row so the whole strip activates the session. The close button
120
+ * sits to its right and intercepts its own clicks via the React handler.
121
+ * Top-aligned so the icon sits on the title line when an activity line wraps
122
+ * the row to a second line.
119
123
  */
120
124
  .jp-xtralab-Terminals-item-activate {
121
125
  display: flex;
122
126
  flex: 1 1 auto;
123
- align-items: center;
127
+ align-items: flex-start;
124
128
  gap: 6px;
125
129
  min-width: 0;
126
- padding: 0 4px 0 12px;
130
+ padding: 5px 4px 5px 12px;
127
131
  background: transparent;
128
132
  border: none;
129
133
  color: inherit;
@@ -137,12 +141,44 @@
137
141
  outline-offset: -2px;
138
142
  }
139
143
 
144
+ /* Nudge the 16px icon down a touch so it lines up with the title's cap
145
+ * height rather than the very top of the text block. */
146
+ .jp-xtralab-Terminals-item-icon {
147
+ margin-top: 1px;
148
+ }
149
+
150
+ /* The title + activity column, between the icon and the close button. */
151
+ .jp-xtralab-Terminals-item-text {
152
+ display: flex;
153
+ flex: 1 1 auto;
154
+ flex-direction: column;
155
+ gap: 1px;
156
+ min-width: 0;
157
+ }
158
+
140
159
  .jp-xtralab-Terminals-item-label {
141
160
  overflow: hidden;
142
161
  text-overflow: ellipsis;
143
162
  white-space: nowrap;
144
163
  }
145
164
 
165
+ /*
166
+ * The latest line of agent output, shown under the title. Smaller and dimmer
167
+ * than the title so it reads as secondary, and clamped to two lines with an
168
+ * ellipsis so a long line can't stretch the row indefinitely.
169
+ */
170
+ .jp-xtralab-Terminals-item-detail {
171
+ display: -webkit-box;
172
+ overflow: hidden;
173
+ font-size: var(--jp-ui-font-size0);
174
+ line-height: 1.3;
175
+ color: var(--jp-ui-font-color3);
176
+ text-overflow: ellipsis;
177
+ overflow-wrap: anywhere;
178
+ -webkit-line-clamp: 2;
179
+ -webkit-box-orient: vertical;
180
+ }
181
+
146
182
  /*
147
183
  * Close button. Hidden by default so the row reads as plain text; fades
148
184
  * in when the row is hovered or the button itself takes focus.
@@ -205,6 +241,14 @@
205
241
  background-color: var(--jp-brand-color1);
206
242
  }
207
243
 
244
+ /* Keep the activity line legible on the brand background: swap the dim
245
+ * neutral for the inverse font color, held a touch lighter than the title so
246
+ * it still reads as secondary. */
247
+ .jp-xtralab-Terminals-item.jp-mod-current .jp-xtralab-Terminals-item-detail {
248
+ color: var(--jp-ui-inverse-font-color1);
249
+ opacity: 0.85;
250
+ }
251
+
208
252
  /*
209
253
  * Invert the monochrome terminal glyph against the brand background, exactly
210
254
  * as the file listing does for its selected rows. Colored agent logos carry
@@ -0,0 +1,80 @@
1
+ /*
2
+ * The read-only walkthrough panel (`xtralab:walkthrough`) in the side area. A
3
+ * scrollable column of step cards, each holding rendered Markdown, an optional
4
+ * embedded visual, and an optional "jump to code" button.
5
+ */
6
+
7
+ .jp-xtralab-Walkthrough {
8
+ overflow-y: auto;
9
+ padding: 4px 0;
10
+ background: var(--jp-layout-color1);
11
+ color: var(--jp-ui-font-color1);
12
+ font-size: var(--jp-ui-font-size1);
13
+ }
14
+
15
+ .jp-xtralab-Walkthrough-step {
16
+ padding: 10px 12px 14px;
17
+ border-bottom: 1px solid var(--jp-border-color2);
18
+ }
19
+
20
+ .jp-xtralab-Walkthrough-stepTitle {
21
+ margin: 0 0 6px;
22
+ font-size: var(--jp-ui-font-size2);
23
+ font-weight: 600;
24
+ color: var(--jp-ui-font-color0);
25
+ }
26
+
27
+ .jp-xtralab-Walkthrough-content {
28
+ overflow-x: auto;
29
+ }
30
+
31
+ .jp-xtralab-Walkthrough-jumpRow {
32
+ margin-top: 8px;
33
+ }
34
+
35
+ /* A subtle native-feeling button: UI font and neutral colors, like the rest of
36
+ the JupyterLab chrome, with a leading file icon and a hover background. */
37
+ .jp-xtralab-Walkthrough-jump {
38
+ display: inline-flex;
39
+ align-items: center;
40
+ gap: 4px;
41
+ max-width: 100%;
42
+ box-sizing: border-box;
43
+ padding: 2px 8px 2px 5px;
44
+ border: var(--jp-border-width) solid var(--jp-border-color2);
45
+ border-radius: var(--jp-border-radius);
46
+ background: none;
47
+ color: var(--jp-ui-font-color1);
48
+ font-family: var(--jp-ui-font-family);
49
+ font-size: var(--jp-ui-font-size1);
50
+ line-height: 1.5;
51
+ cursor: pointer;
52
+ }
53
+
54
+ .jp-xtralab-Walkthrough-jump:hover {
55
+ background-color: var(--jp-layout-color2);
56
+ border-color: var(--jp-border-color1);
57
+ }
58
+
59
+ .jp-xtralab-Walkthrough-jump:focus-visible {
60
+ outline: none;
61
+ border-color: var(--jp-brand-color1);
62
+ box-shadow: inset 0 0 0 1px var(--jp-brand-color1);
63
+ }
64
+
65
+ .jp-xtralab-Walkthrough-jumpIcon {
66
+ display: flex;
67
+ flex: 0 0 auto;
68
+ align-items: center;
69
+ }
70
+
71
+ .jp-xtralab-Walkthrough-jumpIcon svg {
72
+ width: 14px;
73
+ height: 14px;
74
+ }
75
+
76
+ .jp-xtralab-Walkthrough-jumpLabel {
77
+ overflow: hidden;
78
+ text-overflow: ellipsis;
79
+ white-space: nowrap;
80
+ }