@theia/core 1.64.0-next.0 → 1.64.0-next.17

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 (45) hide show
  1. package/lib/browser/catalog.json +767 -722
  2. package/lib/browser/hover-service.d.ts +9 -3
  3. package/lib/browser/hover-service.d.ts.map +1 -1
  4. package/lib/browser/hover-service.js +25 -13
  5. package/lib/browser/hover-service.js.map +1 -1
  6. package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.d.ts.map +1 -1
  7. package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js +5 -0
  8. package/lib/browser/shell/tab-bar-toolbar/tab-toolbar-item.js.map +1 -1
  9. package/lib/browser/status-bar/status-bar.d.ts +2 -1
  10. package/lib/browser/status-bar/status-bar.d.ts.map +1 -1
  11. package/lib/browser/status-bar/status-bar.js +14 -7
  12. package/lib/browser/status-bar/status-bar.js.map +1 -1
  13. package/lib/browser/tree/tree-widget.d.ts +2 -0
  14. package/lib/browser/tree/tree-widget.d.ts.map +1 -1
  15. package/lib/browser/tree/tree-widget.js +8 -3
  16. package/lib/browser/tree/tree-widget.js.map +1 -1
  17. package/lib/browser/widgets/alert-message.js +1 -2
  18. package/lib/browser/widgets/alert-message.js.map +1 -1
  19. package/lib/browser/widgets/select-component.d.ts +2 -0
  20. package/lib/browser/widgets/select-component.d.ts.map +1 -1
  21. package/lib/browser/widgets/select-component.js +1 -1
  22. package/lib/browser/widgets/select-component.js.map +1 -1
  23. package/lib/electron-main/electron-main-application.d.ts.map +1 -1
  24. package/lib/electron-main/electron-main-application.js +21 -7
  25. package/lib/electron-main/electron-main-application.js.map +1 -1
  26. package/package.json +4 -4
  27. package/src/browser/hover-service.ts +31 -13
  28. package/src/browser/shell/tab-bar-toolbar/tab-toolbar-item.tsx +8 -0
  29. package/src/browser/status-bar/status-bar.tsx +14 -7
  30. package/src/browser/style/alert-messages.css +20 -17
  31. package/src/browser/style/breadcrumbs.css +1 -2
  32. package/src/browser/style/dialog.css +3 -2
  33. package/src/browser/style/index.css +5 -3
  34. package/src/browser/style/progress-bar.css +3 -0
  35. package/src/browser/style/select-component.css +1 -4
  36. package/src/browser/style/sidepanel.css +10 -14
  37. package/src/browser/style/split-widget.css +4 -0
  38. package/src/browser/style/status-bar.css +23 -20
  39. package/src/browser/style/tabs.css +15 -13
  40. package/src/browser/style/tree.css +5 -3
  41. package/src/browser/style/view-container.css +3 -7
  42. package/src/browser/tree/tree-widget.tsx +11 -2
  43. package/src/browser/widgets/alert-message.tsx +2 -2
  44. package/src/browser/widgets/select-component.tsx +4 -1
  45. package/src/electron-main/electron-main-application.ts +22 -7
@@ -71,6 +71,11 @@ export interface HoverRequest {
71
71
  * Function that takes the desired width and returns a HTMLElement to be rendered.
72
72
  */
73
73
  visualPreview?: (width: number) => HTMLElement | undefined;
74
+ /**
75
+ * Indicates if the hover contains interactive/clickable items.
76
+ * When true, the hover will register a click handler to allow interaction with elements in the hover area.
77
+ */
78
+ interactive?: boolean;
74
79
  }
75
80
 
76
81
  @injectable()
@@ -102,13 +107,11 @@ export class HoverService {
102
107
  protected readonly disposeOnHide = new DisposableCollection();
103
108
 
104
109
  requestHover(request: HoverRequest): void {
105
- if (request.target !== this.hoverTarget) {
106
- this.cancelHover();
107
- this.pendingTimeout = disposableTimeout(() => this.renderHover(request), this.getHoverDelay());
108
- this.hoverTarget = request.target;
109
- this.listenForMouseOut();
110
- this.listenForMouseClick();
111
- }
110
+ this.cancelHover();
111
+ this.pendingTimeout = disposableTimeout(() => this.renderHover(request), this.getHoverDelay());
112
+ this.hoverTarget = request.target;
113
+ this.listenForMouseOut();
114
+ this.listenForMouseClick(request);
112
115
  }
113
116
 
114
117
  protected getHoverDelay(): number {
@@ -120,7 +123,7 @@ export class HoverService {
120
123
  protected async renderHover(request: HoverRequest): Promise<void> {
121
124
  const host = this.hoverHost;
122
125
  let firstChild: HTMLElement | undefined;
123
- const { target, content, position, cssClasses } = request;
126
+ const { target, content, position, cssClasses, interactive } = request;
124
127
  if (cssClasses) {
125
128
  host.classList.add(...cssClasses);
126
129
  }
@@ -144,6 +147,17 @@ export class HoverService {
144
147
  host.showPopover();
145
148
  }
146
149
 
150
+ if (interactive) {
151
+ // Add a click handler to the hover host to ensure clicks within the hover area work properly
152
+ const clickHandler = (e: MouseEvent) => {
153
+ // Let click events within the hover area be processed by their handlers
154
+ // but prevent them from triggering document handlers that might dismiss the tooltip
155
+ e.stopImmediatePropagation();
156
+ };
157
+ host.addEventListener('click', clickHandler);
158
+ this.disposeOnHide.push({ dispose: () => host.removeEventListener('click', clickHandler) });
159
+ }
160
+
147
161
  if (request.visualPreview) {
148
162
  // If just a string is being rendered use the size of the outer box
149
163
  const width = firstChild ? firstChild.offsetWidth : this.hoverHost.offsetWidth;
@@ -224,12 +238,16 @@ export class HoverService {
224
238
  }
225
239
 
226
240
  /**
227
- * Listen for any mouse click (mousedown) event and cancel the hover if detected.
228
- * This ensures the hover is dismissed when the user clicks anywhere (including on the target or elsewhere).
241
+ * Listen for mouse click (mousedown) events and handle them based on hover interactivity.
242
+ * For non-interactive hovers, any mousedown cancels the hover immediately.
243
+ * For interactive hovers, the hover remains visible to allow interaction with its elements.
229
244
  */
230
- protected listenForMouseClick(): void {
231
- const handleMouseDown = (e: MouseEvent) => {
232
- this.cancelHover();
245
+ protected listenForMouseClick(request: HoverRequest): void {
246
+ const handleMouseDown = (_e: MouseEvent) => {
247
+ const isInteractive = request.interactive;
248
+ if (!isInteractive) {
249
+ this.cancelHover();
250
+ }
233
251
  };
234
252
  document.addEventListener('mousedown', handleMouseDown, true);
235
253
  this.disposeOnHide.push({ dispose: () => document.removeEventListener('mousedown', handleMouseDown, true) });
@@ -95,6 +95,10 @@ export class RenderedToolbarItemImpl extends AbstractToolbarItemImpl<RenderedToo
95
95
  if (action.onDidChange) {
96
96
  this.disposables.push(action.onDidChange(() => this.onDidChangeEmitter.fire()));
97
97
  }
98
+
99
+ this.disposables.push(Disposable.create(() =>
100
+ this.contextKeyListener?.dispose()
101
+ ));
98
102
  }
99
103
 
100
104
  dispose(): void {
@@ -102,6 +106,10 @@ export class RenderedToolbarItemImpl extends AbstractToolbarItemImpl<RenderedToo
102
106
  }
103
107
 
104
108
  updateContextKeyListener(when: string): void {
109
+ if (this.contextKeyListener) {
110
+ this.contextKeyListener.dispose();
111
+ this.contextKeyListener = undefined;
112
+ }
105
113
  const contextKeys = new Set<string>();
106
114
  this.contextKeyService.parseKeys(when)?.forEach(key => contextKeys.add(key));
107
115
  if (contextKeys.size > 0) {
@@ -108,7 +108,7 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
108
108
  </React.Fragment>;
109
109
  }
110
110
 
111
- protected onclick(entry: StatusBarEntry): () => void {
111
+ protected triggerCommand(entry: StatusBarEntry): () => void {
112
112
  return () => {
113
113
  if (entry.command) {
114
114
  const args = entry.arguments || [];
@@ -117,6 +117,15 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
117
117
  };
118
118
  }
119
119
 
120
+ protected requestHover(e: React.MouseEvent<HTMLElement, MouseEvent>, entry: StatusBarEntry): void {
121
+ this.hoverService.requestHover({
122
+ content: entry.tooltip!,
123
+ target: e.currentTarget,
124
+ position: 'top',
125
+ interactive: entry.tooltip instanceof HTMLElement,
126
+ });
127
+ }
128
+
120
129
  protected createAttributes(viewEntry: StatusBarViewEntry): React.Attributes & React.HTMLAttributes<HTMLElement> {
121
130
  const attrs: React.Attributes & React.HTMLAttributes<HTMLElement> = {};
122
131
  const entry = viewEntry.entry;
@@ -126,9 +135,11 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
126
135
  attrs.className += ' hasCommand';
127
136
  }
128
137
  if (entry.command) {
129
- attrs.onClick = this.onclick(entry);
138
+ attrs.onClick = this.triggerCommand(entry);
130
139
  } else if (entry.onclick) {
131
140
  attrs.onClick = e => entry.onclick?.(e.nativeEvent);
141
+ } else {
142
+ attrs.onClick = e => this.requestHover(e, entry);
132
143
  }
133
144
 
134
145
  if (viewEntry.compact && viewEntry.alignment !== undefined) {
@@ -136,11 +147,7 @@ export class StatusBarImpl extends ReactWidget implements StatusBar {
136
147
  }
137
148
 
138
149
  if (entry.tooltip) {
139
- attrs.onMouseEnter = e => this.hoverService.requestHover({
140
- content: entry.tooltip!,
141
- target: e.currentTarget,
142
- position: 'top'
143
- });
150
+ attrs.onMouseEnter = e => this.requestHover(e, entry);
144
151
  }
145
152
  if (entry.className) {
146
153
  attrs.className += ' ' + entry.className;
@@ -16,13 +16,16 @@
16
16
 
17
17
  /* message container */
18
18
  .theia-alert-message-container {
19
- flex: 1;
20
- padding: 10px;
19
+ padding-block: calc(var(--theia-ui-padding) * 2);
20
+ padding-inline: calc(var(--theia-ui-padding) * 3) max(var(--theia-scrollbar-width), var(--theia-ui-padding));
21
+ flex-shrink: 0;
21
22
  }
22
23
 
23
- .theia-alert-message-container i {
24
- transform: translateY(2px);
25
- padding-right: 3px;
24
+ .theia-alert-message-container .theia-message-header {
25
+ display: flex;
26
+ align-items: center;
27
+ flex-wrap: wrap;
28
+ gap: var(--theia-ui-padding);
26
29
  }
27
30
 
28
31
  .theia-alert-message-container .theia-message-header,
@@ -31,32 +34,32 @@
31
34
  overflow: hidden;
32
35
  }
33
36
 
37
+ /* base alert message */
38
+ .theia-alert {
39
+ display: grid;
40
+ gap: var(--theia-ui-padding);
41
+ border-radius: 4px;
42
+ padding: calc(var(--theia-ui-padding) * 2);
43
+ border: var(--theia-border-width) solid var(--theia-inputValidation-infoBorder);
44
+ line-height: 16px;
45
+ }
46
+
34
47
  /* information message */
35
48
  .theia-info-alert {
36
49
  background-color: var(--theia-inputValidation-infoBackground);
37
- border: var(--theia-border-width) solid
38
- var(--theia-inputValidation-infoBorder);
39
- border-radius: 4px;
40
50
  color: var(--theia-inputValidation-infoForeground);
41
- padding: 10px;
42
51
  }
43
52
 
44
53
  /* warning message */
45
54
  .theia-warning-alert {
55
+ border-color: var(--theia-inputValidation-warningBorder);
46
56
  background-color: var(--theia-inputValidation-warningBackground);
47
- border: var(--theia-border-width) solid
48
- var(--theia-inputValidation-warningBorder);
49
- border-radius: 4px;
50
57
  color: var(--theia-inputValidation-warningForeground);
51
- padding: 10px;
52
58
  }
53
59
 
54
60
  /* error message */
55
61
  .theia-error-alert {
62
+ border-color: var(--theia-inputValidation-errorBorder);
56
63
  background-color: var(--theia-inputValidation-errorBackground);
57
- border: var(--theia-border-width) solid
58
- var(--theia-inputValidation-errorBorder);
59
- border-radius: 4px;
60
64
  color: var(--theia-inputValidation-errorForeground);
61
- padding: 10px;
62
65
  }
@@ -49,7 +49,6 @@
49
49
  height: 100%;
50
50
  color: var(--theia-breadcrumb-foreground);
51
51
  outline: none;
52
- padding: 0 0.3rem 0 0.25rem;
53
52
  }
54
53
 
55
54
  .theia-breadcrumbs .theia-breadcrumb-item:hover {
@@ -64,7 +63,7 @@
64
63
  align-items: center;
65
64
  width: 0.8em;
66
65
  text-align: right;
67
- padding-left: 4px;
66
+ padding-inline: 3px 6px;
68
67
  }
69
68
 
70
69
  .theia-breadcrumbs .theia-breadcrumb-item::before {
@@ -50,8 +50,9 @@
50
50
  font-size: var(--theia-ui-font-size1);
51
51
  background-color: var(--theia-statusBar-background);
52
52
  color: var(--theia-statusBar-foreground);
53
- padding: 0 calc(var(--theia-ui-padding) * 2);
54
- min-height: 24px;
53
+ padding-left: calc(var(--theia-ui-padding) * 2);
54
+ padding-right: var(--theia-ui-padding);
55
+ min-height: 30px;
55
56
  }
56
57
 
57
58
  .lm-Widget.dialogOverlay .dialogTitle i.closeButton {
@@ -123,8 +123,10 @@ blockquote {
123
123
  font-family: var(--theia-ui-font-family);
124
124
  font-size: var(--theia-ui-font-size1);
125
125
  line-height: var(--theia-content-line-height);
126
- padding-left: 5px;
126
+ padding: 3px 0 3px 8px;
127
127
  border-radius: 2px;
128
+ min-height: 28px;
129
+ box-sizing: border-box;
128
130
  }
129
131
 
130
132
  .theia-input[type="text"] {
@@ -248,7 +250,7 @@ blockquote {
248
250
 
249
251
  .action-label {
250
252
  padding: 2px;
251
- border-radius: 5px;
253
+ border-radius: 4px;
252
254
  cursor: pointer;
253
255
  }
254
256
 
@@ -262,7 +264,7 @@ blockquote {
262
264
  min-width: 65px;
263
265
  outline: none;
264
266
  cursor: pointer;
265
- padding: 4px 9px;
267
+ padding: 6px 9px;
266
268
  margin-left: calc(var(--theia-ui-padding) * 2);
267
269
  border-radius: 2px;
268
270
  }
@@ -15,6 +15,9 @@
15
15
  ********************************************************************************/
16
16
 
17
17
  .theia-progress-bar-container {
18
+ position: absolute;
19
+ top: -2px;
20
+ left: 0;
18
21
  width: 100%;
19
22
  height: 2px;
20
23
  }
@@ -43,10 +43,6 @@
43
43
  overflow: hidden;
44
44
  }
45
45
 
46
- .theia-select-component:focus {
47
- outline-color: var(--theia-focusBorder);
48
- }
49
-
50
46
  .theia-select-component-dropdown {
51
47
  font-family: var(--theia-ui-font-family);
52
48
  font-size: var(--theia-ui-font-size1);
@@ -57,6 +53,7 @@
57
53
  user-select: none;
58
54
  overflow: auto;
59
55
  border-radius: 2px;
56
+ margin-top: 2px;
60
57
  }
61
58
 
62
59
  .theia-select-component-dropdown .theia-select-component-option {
@@ -35,7 +35,6 @@
35
35
  .lm-TabBar.theia-app-sides {
36
36
  display: block;
37
37
  color: var(--theia-activityBar-inactiveForeground);
38
- background: var(--theia-activityBar-background);
39
38
  font-size: var(--theia-ui-font-size1);
40
39
  min-width: var(--theia-private-sidebar-tab-width);
41
40
  max-width: var(--theia-private-sidebar-tab-width);
@@ -52,7 +51,6 @@
52
51
 
53
52
  .lm-TabBar.theia-app-sides .lm-TabBar-tab {
54
53
  position: relative;
55
- background: var(--theia-activityBar-background);
56
54
  flex-direction: column;
57
55
  justify-content: center;
58
56
  align-items: center;
@@ -146,6 +144,14 @@
146
144
  max-width: var(--theia-private-sidebar-tab-width);
147
145
  }
148
146
 
147
+ #theia-left-content-panel.theia-mod-collapsed .theia-app-sidebar-container {
148
+ border-right: none;
149
+ }
150
+
151
+ #theia-right-content-panel.theia-mod-collapsed .theia-app-sidebar-container {
152
+ border-left: none;
153
+ }
154
+
149
155
  #theia-left-content-panel > .lm-Panel {
150
156
  border-right: var(--theia-panel-border-width) solid
151
157
  var(--theia-activityBar-border);
@@ -326,13 +332,9 @@
326
332
  |----------------------------------------------------------------------------*/
327
333
 
328
334
  .theia-sidepanel-toolbar {
329
- min-height: calc(
330
- var(--theia-private-horizontal-tab-height) +
331
- var(--theia-private-horizontal-tab-scrollbar-rail-height) / 2
332
- );
333
335
  display: flex;
334
- padding-left: 5px;
335
336
  align-items: center;
337
+ min-height: var(--theia-horizontal-toolbar-height);
336
338
  background-color: var(--theia-sideBar-background);
337
339
  overflow: hidden;
338
340
  }
@@ -340,7 +342,7 @@
340
342
  .theia-sidepanel-toolbar .theia-sidepanel-title {
341
343
  color: var(--theia-settings-headerForeground);
342
344
  flex: 1;
343
- margin-left: 14px;
345
+ margin-left: calc(var(--theia-ui-padding) * 3);
344
346
  text-transform: uppercase;
345
347
  font-size: var(--theia-ui-font-size0);
346
348
  min-width: 1rem;
@@ -350,12 +352,6 @@
350
352
  color: var(--theia-icon-foreground);
351
353
  }
352
354
 
353
- .theia-sidepanel-toolbar .lm-TabBar-toolbar .item > div {
354
- height: 18px;
355
- width: 18px;
356
- background-repeat: no-repeat;
357
- }
358
-
359
355
  .noWrapInfo {
360
356
  white-space: nowrap;
361
357
  overflow: hidden;
@@ -25,6 +25,10 @@
25
25
  min-height: var(--theia-content-line-height);
26
26
  }
27
27
 
28
+ .lm-SplitPanel-handle {
29
+ z-index: 6; /* Upper than the minimap */
30
+ }
31
+
28
32
  .theia-split-widget > .lm-SplitPanel > .lm-SplitPanel-handle {
29
33
  box-sizing: border-box;
30
34
  }
@@ -37,60 +37,63 @@ body.theia-no-open-workspace #theia-statusBar {
37
37
  flex: 1;
38
38
  display: flex;
39
39
  align-items: stretch;
40
+ gap: var(--theia-ui-padding)
40
41
  }
41
42
 
42
43
  #theia-statusBar .area.left {
43
44
  justify-content: flex-start;
45
+ padding-left: var(--theia-ui-padding);
44
46
  }
45
47
 
46
48
  #theia-statusBar .area.right {
47
49
  justify-content: flex-end;
48
- padding-right: calc(var(--theia-ui-padding) * 2);
50
+ padding-right: var(--theia-ui-padding);
49
51
  }
50
52
 
51
53
  #theia-statusBar .area .element {
52
54
  color: var(--theia-statusBar-foreground);
53
55
  display: flex;
54
56
  align-items: center;
57
+ justify-content: center;
55
58
  font-size: var(--theia-statusBar-font-size);
59
+ min-width: var(--theia-statusBar-height);
56
60
  }
57
61
 
58
62
  #theia-statusBar .area.left .element.has-background {
59
- margin-left: 0px;
60
- margin-right: 3px;
61
- padding-left: 7px;
62
- padding-right: 7px;
63
+ padding-inline: var(--theia-ui-padding);
63
64
  }
64
- #theia-statusBar .area .element>* {
65
- margin-left: calc(var(--theia-ui-padding)/2);
65
+
66
+ #theia-statusBar .area.left .element.has-background {
67
+ margin-left: calc(-1 * var(--theia-ui-padding));
66
68
  }
67
69
 
70
+ /* Icons */
68
71
  #theia-statusBar .area .element .codicon {
69
72
  /* Scaling down codicons from 16 to 14 pixels */
70
73
  font-size: 14px;
74
+ margin: auto;
71
75
  }
72
76
 
73
- #theia-statusBar .area .element > *:last-child {
74
- margin-right: calc(var(--theia-ui-padding) / 2);
77
+ /* Icon with text */
78
+ #theia-statusBar .area .element .codicon:has(+ span) {
79
+ margin-inline: calc(var(--theia-ui-padding) / 2);
75
80
  }
76
81
 
77
- .theia-mod-offline #theia-statusBar {
78
- background-color: var(--theia-statusBar-offlineBackground) !important;
82
+ /* Text labels */
83
+ #theia-statusBar .area .element>span:not(.codicon) {
84
+ margin-inline: calc(var(--theia-ui-padding) / 2)
79
85
  }
80
86
 
81
- .theia-mod-offline #theia-statusBar .area .element {
82
- color: var(--theia-statusBar-offlineForeground) !important;
87
+ #theia-statusBar .area .element>span:not(.codicon):empty {
88
+ display: none;
83
89
  }
84
90
 
85
- #theia-statusBar .area.left .element:first-child:not(.has-background) {
86
- margin-left: calc(var(--theia-ui-padding) * 3);
87
- }
88
- #theia-statusBar .area.left .element {
89
- margin-right: var(--theia-ui-padding);
91
+ .theia-mod-offline #theia-statusBar {
92
+ background-color: var(--theia-statusBar-offlineBackground) !important;
90
93
  }
91
94
 
92
- #theia-statusBar .area.right .element {
93
- margin-left: var(--theia-ui-padding);
95
+ .theia-mod-offline #theia-statusBar .area .element {
96
+ color: var(--theia-statusBar-offlineForeground) !important;
94
97
  }
95
98
 
96
99
  #theia-statusBar .area.right .element.compact-right,
@@ -4,12 +4,12 @@
4
4
 
5
5
  :root {
6
6
  /* These need to be root because tabs get attached to the body during dragging. */
7
- --theia-private-horizontal-tab-height: 28.5px;
7
+ --theia-private-horizontal-tab-height: 35px;
8
+ --theia-horizontal-toolbar-height: var(--theia-private-horizontal-tab-height);
8
9
  --theia-private-horizontal-tab-scrollbar-rail-height: 7px;
9
10
  --theia-private-horizontal-tab-scrollbar-height: 5px;
10
11
  --theia-tabbar-toolbar-z-index: 1001;
11
12
  --theia-toolbar-active-transform-scale: 1.272019649;
12
- --theia-horizontal-toolbar-height: calc(var(--theia-private-horizontal-tab-height) + var(--theia-private-horizontal-tab-scrollbar-rail-height) / 2);
13
13
  --theia-dragover-tab-border-width: 2px;
14
14
  }
15
15
 
@@ -32,8 +32,8 @@
32
32
  .lm-TabBar[data-orientation="horizontal"] .lm-TabBar-tab {
33
33
  flex: none;
34
34
  height: var(--theia-horizontal-toolbar-height);
35
+ line-height: var(--theia-horizontal-toolbar-height);
35
36
  min-width: 35px;
36
- line-height: var(--theia-private-horizontal-tab-height);
37
37
  padding: 0px 8px;
38
38
  align-items: center;
39
39
  overflow: hidden;
@@ -221,7 +221,6 @@
221
221
  .lm-TabBar.theia-app-centers .lm-TabBar-tab.lm-mod-closable>.lm-TabBar-tabCloseIcon,
222
222
  .lm-TabBar.theia-app-centers .lm-TabBar-tab.theia-mod-pinned>.lm-TabBar-tabCloseIcon {
223
223
  padding: 2px;
224
- margin-top: 2px;
225
224
  margin-left: 4px;
226
225
  height: var(--theia-icon-size);
227
226
  width: var(--theia-icon-size);
@@ -328,7 +327,8 @@
328
327
  |----------------------------------------------------------------------------*/
329
328
 
330
329
  .lm-TabBar[data-orientation="horizontal"] .lm-TabBar-content-container>.ps__rail-x {
331
- height: var(--theia-private-horizontal-tab-scrollbar-rail-height);
330
+ height: var(--theia-private-horizontal-tab-scrollbar-rail-height) !important;
331
+ background: transparent !important;
332
332
  z-index: 1000;
333
333
  }
334
334
 
@@ -384,9 +384,10 @@
384
384
  /* Due to the scrollbar (`z-index: 1000;`) it has a greater `z-index`. */
385
385
  display: flex;
386
386
  flex-direction: row-reverse;
387
- padding: 4px;
388
- padding-left: 0px;
389
- margin-right: 4px;
387
+ align-items: center;
388
+ justify-content: center;
389
+ padding-inline: var(--theia-ui-padding);
390
+ gap: 2px;
390
391
  }
391
392
 
392
393
  .lm-TabBar-content-container {
@@ -402,7 +403,7 @@
402
403
  display: flex;
403
404
  flex-direction: row;
404
405
  column-gap: 0px;
405
- align-items: centery;
406
+ align-items: center;
406
407
  }
407
408
 
408
409
  .lm-TabBar-toolbar .item>div {
@@ -414,7 +415,7 @@
414
415
  cursor: pointer;
415
416
  }
416
417
 
417
- .lm-TabBar-toolbar :not(.item.enabled) .action-label {
418
+ .lm-TabBar-toolbar > :not(.item.enabled) > .action-label {
418
419
  background: transparent;
419
420
  cursor: default;
420
421
  }
@@ -425,10 +426,10 @@
425
426
  }
426
427
 
427
428
  .lm-TabBar-toolbar .item>div {
428
- line-height: calc(var(--theia-icon-size) + 2px);
429
- height: calc(var(--theia-icon-size) + 2px);
429
+ min-width: var(--theia-icon-size);
430
+ height: var(--theia-icon-size);
431
+ line-height: var(--theia-icon-size);
430
432
  background-repeat: no-repeat;
431
- line-height: 18px;
432
433
  }
433
434
 
434
435
  .lm-TabBar-toolbar .item>div.no-icon {
@@ -492,6 +493,7 @@
492
493
 
493
494
  .lm-TabBar[data-orientation="horizontal"] .lm-TabBar-content {
494
495
  flex-direction: row;
496
+ min-height: var(--theia-horizontal-toolbar-height);
495
497
  }
496
498
 
497
499
  .lm-TabBar[data-orientation="vertical"] .lm-TabBar-content {
@@ -73,14 +73,16 @@
73
73
  .theia-TreeNodeContent {
74
74
  display: flex;
75
75
  align-items: center;
76
- width: calc(100% - var(--theia-scrollbar-rail-width));
76
+ width: 100%;
77
+ padding-right: var(--theia-ui-padding);
78
+ box-sizing: border-box;
77
79
  }
78
80
 
79
81
  .theia-ExpansionToggle {
80
82
  display: flex;
81
83
  justify-content: center;
82
- padding-left: calc(var(--theia-ui-padding) / 2);
83
- padding-right: calc(var(--theia-ui-padding) / 2);
84
+ padding-left: calc(var(--theia-ui-padding) / 3);
85
+ padding-right: calc(var(--theia-ui-padding) / 3);
84
86
  min-width: var(--theia-icon-size);
85
87
  min-height: var(--theia-icon-size);
86
88
  }
@@ -15,7 +15,7 @@
15
15
  ********************************************************************************/
16
16
 
17
17
  :root {
18
- --theia-view-container-title-height: var(--theia-content-line-height);
18
+ --theia-view-container-title-height: 24px;
19
19
  --theia-view-container-content-height: calc(100% - var(--theia-view-container-title-height));
20
20
  }
21
21
 
@@ -82,10 +82,6 @@
82
82
  box-shadow: none;
83
83
  }
84
84
 
85
- .theia-view-container-part-header .theia-ExpansionToggle {
86
- padding-left: 4px;
87
- }
88
-
89
85
  .theia-view-container>.lm-SplitPanel[data-orientation="horizontal"] .part>.theia-header .theia-ExpansionToggle::before {
90
86
  display: none;
91
87
  padding-left: 0px;
@@ -114,7 +110,7 @@
114
110
  }
115
111
 
116
112
  .theia-view-container-part-header .notification-count-container {
117
- margin-right: 12px;
113
+ margin-right: var(--theia-ui-padding);
118
114
  }
119
115
 
120
116
  .theia-view-container .part>.body {
@@ -156,7 +152,7 @@
156
152
  .lm-TabBar-toolbar.theia-view-container-part-title {
157
153
  overflow: visible !important;
158
154
  padding: 0px;
159
- padding-right: calc(var(--theia-ui-padding) * 2 / 3);
155
+ padding-right: var(--theia-ui-padding);
160
156
  }
161
157
 
162
158
  .theia-view-container-part-title {
@@ -81,6 +81,8 @@ export interface TreeScrollEvent {
81
81
  export interface TreeScrollState {
82
82
  readonly scrollTop: number;
83
83
  readonly isAtBottom: boolean;
84
+ readonly scrollHeight?: number;
85
+ readonly clientHeight?: number;
84
86
  }
85
87
 
86
88
  export const TreeProps = Symbol('TreeProps');
@@ -1643,7 +1645,7 @@ export namespace TreeWidget {
1643
1645
  }
1644
1646
  export class View extends React.Component<ViewProps> {
1645
1647
  list: VirtuosoHandle | undefined;
1646
- private lastScrollState: TreeScrollState = { scrollTop: 0, isAtBottom: true };
1648
+ private lastScrollState: TreeScrollState = { scrollTop: 0, isAtBottom: true, scrollHeight: 0, clientHeight: 0 };
1647
1649
 
1648
1650
  override render(): React.ReactNode {
1649
1651
  const { rows, width, height, scrollToRow, renderNodeRow, onScrollEmitter, ...other } = this.props;
@@ -1665,9 +1667,16 @@ export namespace TreeWidget {
1665
1667
  const isAtBottom = scrollHeight - scrollTop - clientHeight <= SCROLL_BOTTOM_THRESHOLD;
1666
1668
 
1667
1669
  // Store scroll state before firing the event to prevent jitter during inference and scrolling
1668
- this.lastScrollState = { scrollTop, isAtBottom };
1670
+ this.lastScrollState = { scrollTop, isAtBottom, scrollHeight, clientHeight };
1669
1671
  onScrollEmitter?.fire({ scrollTop, scrollLeft: e.target.scrollLeft || 0 });
1670
1672
  }}
1673
+ atBottomStateChange={(atBottom: boolean) => {
1674
+ this.lastScrollState = {
1675
+ ...this.lastScrollState,
1676
+ isAtBottom: atBottom
1677
+ };
1678
+ }}
1679
+ atBottomThreshold={SCROLL_BOTTOM_THRESHOLD}
1671
1680
  totalCount={rows.length}
1672
1681
  itemContent={index => renderNodeRow(rows[index])}
1673
1682
  width={width}
@@ -43,9 +43,9 @@ export class AlertMessage extends React.Component<AlertMessageProps> {
43
43
 
44
44
  override render(): React.ReactNode {
45
45
  return <div className='theia-alert-message-container'>
46
- <div className={`theia-${this.props.type.toLowerCase()}-alert`}>
46
+ <div className={`theia-alert theia-${this.props.type.toLowerCase()}-alert`}>
47
47
  <div className='theia-message-header'>
48
- <i className={AlertMessageIcon[this.props.type]}></i>&nbsp;
48
+ <i className={AlertMessageIcon[this.props.type]}></i>
49
49
  {this.props.header}
50
50
  </div>
51
51
  <div className='theia-message-content'>{this.props.children}</div>