Skip to content

Commit cc59a3c

Browse files
committed
Add markdown renderer for plugin tree tooltips
Signed-off-by: robmor01 <[email protected]>
1 parent 10d5275 commit cc59a3c

File tree

9 files changed

+133
-8
lines changed

9 files changed

+133
-8
lines changed

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"perfect-scrollbar": "^1.3.0",
5656
"react": "^16.8.0",
5757
"react-dom": "^16.8.0",
58+
"react-tooltip": "^4.2.21",
5859
"react-virtualized": "^9.20.0",
5960
"reconnecting-websocket": "^4.2.0",
6061
"reflect-metadata": "^0.1.10",

packages/core/src/browser/frontend-application.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { FrontendApplicationStateService } from './frontend-application-state';
2525
import { preventNavigation, parseCssTime, animationFrame } from './browser';
2626
import { CorePreferences } from './core-preferences';
2727
import { WindowService } from './window/window-service';
28+
import { tooltipSingleton } from './tooltip-renderer';
2829

2930
/**
3031
* Clients can implement to get a callback for contributing widgets to a shell on start.
@@ -130,6 +131,7 @@ export class FrontendApplication {
130131

131132
const host = await this.getHost();
132133
this.attachShell(host);
134+
this.attachTooltip(host);
133135
await animationFrame();
134136
this.stateService.state = 'attached_shell';
135137

@@ -221,6 +223,13 @@ export class FrontendApplication {
221223
Widget.attach(this.shell, host, ref);
222224
}
223225

226+
/**
227+
* Attach the tooltip container to the host element.
228+
*/
229+
protected attachTooltip(host: HTMLElement): void {
230+
host.appendChild(tooltipSingleton.host);
231+
}
232+
224233
/**
225234
* If a startup indicator is present, it is first hidden with the `theia-hidden` CSS class and then
226235
* removed after a while. The delay until removal is taken from the CSS transition duration.

packages/core/src/browser/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ export * from './diff-uris';
4040
export * from './core-preferences';
4141
export * from './view-container';
4242
export * from './breadcrumbs';
43+
export * from './tooltip-renderer';

packages/core/src/browser/style/index.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,4 @@ button.secondary[disabled], .theia-button.secondary[disabled] {
259259
@import './quick-title-bar.css';
260260
@import './progress-bar.css';
261261
@import './breadcrumbs.css';
262+
@import './tooltip.css';
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/********************************************************************************
2+
* Copyright (C) 2021 Arm and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the Eclipse
10+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
11+
* with the GNU Classpath Exception which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
********************************************************************************/
16+
17+
.theia-tooltip {
18+
color: var(--theia-list-hoverForeground) !important;
19+
background: var(--theia-list-hoverBackground) !important;
20+
border: 1px solid !important;
21+
border-color: var(--theia-list-hoverForeground) !important;
22+
}
23+
24+
/* Hide tooltip arrow */
25+
.theia-tooltip::before,
26+
.theia-tooltip::after {
27+
border: none !important;
28+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/********************************************************************************
2+
* Copyright (C) 2021 Arm and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the Eclipse
10+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
11+
* with the GNU Classpath Exception which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
********************************************************************************/
16+
17+
import * as React from 'react';
18+
import ReactTooltip from 'react-tooltip';
19+
import { ReactRenderer } from './widgets/react-renderer';
20+
import { v4 } from 'uuid';
21+
22+
export const TOOLTIP_ID = v4();
23+
24+
class TooltipRenderer extends ReactRenderer {
25+
protected rendered = false;
26+
27+
public update(): void {
28+
if (!this.rendered) {
29+
this.render();
30+
this.rendered = true;
31+
}
32+
33+
ReactTooltip.rebuild();
34+
}
35+
36+
protected doRender(): React.ReactNode {
37+
return <ReactTooltip id={TOOLTIP_ID} className='theia-tooltip' html={true} delayShow={1000} />;
38+
}
39+
}
40+
41+
export const tooltipSingleton = new TooltipRenderer();

packages/plugin-ext/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"@theia/terminal": "1.17.0",
2727
"@theia/timeline": "1.17.0",
2828
"@theia/workspace": "1.17.0",
29+
"@types/markdown-it": "*",
2930
"@types/mime": "^2.0.1",
3031
"decompress": "^4.2.1",
3132
"escape-html": "^1.0.3",
@@ -34,6 +35,7 @@
3435
"jsonc-parser": "^2.2.0",
3536
"lodash.clonedeep": "^4.5.0",
3637
"macaddress": "^0.2.9",
38+
"markdown-it": "^8.4.0",
3739
"mime": "^2.4.4",
3840
"ps-tree": "^1.2.0",
3941
"request": "^2.82.0",

packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ import {
2929
TREE_NODE_SEGMENT_GROW_CLASS,
3030
TREE_NODE_TAIL_CLASS,
3131
TreeModelImpl,
32-
TreeViewWelcomeWidget
32+
TreeViewWelcomeWidget,
33+
TOOLTIP_ID,
34+
tooltipSingleton
3335
} from '@theia/core/lib/browser';
3436
import { TreeViewItem, TreeViewItemCollapsibleState } from '../../../common/plugin-api-rpc';
3537
import { MenuPath, MenuModelRegistry, ActionMenuNode } from '@theia/core/lib/common/menu';
@@ -42,6 +44,9 @@ import { MessageService } from '@theia/core/lib/common/message-service';
4244
import { View } from '../../../common/plugin-protocol';
4345
import CoreURI from '@theia/core/lib/common/uri';
4446
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
47+
import * as markdownit from 'markdown-it';
48+
import { isMarkdownString } from '../../../plugin/markdown-string';
49+
import { Message } from '@theia/core/shared/@phosphor/messaging';
4550

4651
export const TREE_NODE_HYPERLINK = 'theia-TreeNodeHyperlink';
4752
export const VIEW_ITEM_CONTEXT_MENU: MenuPath = ['view-item-context-menu'];
@@ -274,13 +279,32 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
274279
classes.push(TREE_NODE_SEGMENT_GROW_CLASS);
275280
}
276281
const className = classes.join(' ');
277-
const title = node.tooltip ||
278-
(node.resourceUri && this.labelProvider.getLongName(new CoreURI(node.resourceUri)))
279-
|| this.toNodeName(node);
280-
const attrs = this.decorateCaption(node, {
281-
className, id: node.id,
282-
title
283-
});
282+
283+
let attrs: {} = {
284+
...this.decorateCaption(node, {}),
285+
className,
286+
id: node.id
287+
};
288+
289+
if (node.tooltip && isMarkdownString(node.tooltip)) {
290+
// Render markdown in custom tooltip
291+
const tooltip = markdownit().render(node.tooltip.value);
292+
293+
attrs = {
294+
...attrs,
295+
'data-tip': tooltip,
296+
'data-for': TOOLTIP_ID
297+
};
298+
} else {
299+
const title = node.tooltip ||
300+
(node.resourceUri && this.labelProvider.getLongName(new CoreURI(node.resourceUri)))
301+
|| this.toNodeName(node);
302+
303+
attrs = {
304+
...attrs,
305+
title
306+
};
307+
}
284308

285309
const children: React.ReactNode[] = [];
286310
const caption = this.toNodeName(node);
@@ -457,4 +481,9 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
457481
shouldShowWelcomeView(): boolean {
458482
return (this.model.proxy === undefined || this.model.isTreeEmpty) && this.message === undefined;
459483
}
484+
485+
protected onUpdateRequest(msg: Message): void {
486+
super.onUpdateRequest(msg);
487+
tooltipSingleton.update();
488+
}
460489
}

yarn.lock

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8672,6 +8672,14 @@ react-perfect-scrollbar@^1.5.3:
86728672
perfect-scrollbar "^1.5.0"
86738673
prop-types "^15.6.1"
86748674

8675+
react-tooltip@^4.2.21:
8676+
version "4.2.21"
8677+
resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.21.tgz#840123ed86cf33d50ddde8ec8813b2960bfded7f"
8678+
integrity sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==
8679+
dependencies:
8680+
prop-types "^15.7.2"
8681+
uuid "^7.0.3"
8682+
86758683
react-virtualized@^9.20.0:
86768684
version "9.22.3"
86778685
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.22.3.tgz#f430f16beb0a42db420dbd4d340403c0de334421"
@@ -10633,6 +10641,11 @@ uuid@^3.0.1, uuid@^3.3.2, uuid@^3.3.3:
1063310641
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
1063410642
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
1063510643

10644+
uuid@^7.0.3:
10645+
version "7.0.3"
10646+
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
10647+
integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
10648+
1063610649
uuid@^8.0.0, uuid@^8.3.2:
1063710650
version "8.3.2"
1063810651
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"

0 commit comments

Comments
 (0)