Skip to content

Commit 829391b

Browse files
Nicholas RoscinoDevtools-frontend LUCI CQ
authored andcommitted
Change PopoverHelper for devtools-tooltip
Bug: 441236757 Change-Id: Ifce767d64df8094ccdf6410e0eb4498657f36ef6 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6964999 Reviewed-by: Ergün Erdoğmuş <ergunsh@chromium.org> Reviewed-by: Alex Rudenko <alexrudenko@chromium.org> Commit-Queue: Nicholas Roscino <nroscino@chromium.org>
1 parent bc179fc commit 829391b

3 files changed

Lines changed: 73 additions & 123 deletions

File tree

front_end/panels/ai_assistance/PatchWidget.ts

Lines changed: 17 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,6 @@ export interface ViewInput {
182182
}
183183

184184
export interface ViewOutput {
185-
tooltipRef?: Directives.Ref<HTMLElement>;
186185
changeRef?: Directives.Ref<HTMLElement>;
187186
summaryRef?: Directives.Ref<HTMLElement>;
188187
}
@@ -211,7 +210,6 @@ export class PatchWidget extends UI.Widget.Widget {
211210
#automaticFileSystem =
212211
Persistence.AutomaticFileSystemManager.AutomaticFileSystemManager.instance().automaticFileSystem;
213212
#applyToDisconnectedAutomaticWorkspace = false;
214-
#popoverHelper: UI.PopoverHelper.PopoverHelper|null = null;
215213
// `rpcId` from the `applyPatch` request
216214
#rpcId: Host.AidaClient.RpcGlobalId|null = null;
217215

@@ -228,7 +226,7 @@ export class PatchWidget extends UI.Widget.Widget {
228226
if (!input.changeSummary && input.patchSuggestionState === PatchSuggestionState.INITIAL) {
229227
return;
230228
}
231-
output.tooltipRef = output.tooltipRef ?? Directives.createRef<HTMLElement>();
229+
232230
output.changeRef = output.changeRef ?? Directives.createRef<HTMLElement>();
233231
output.summaryRef = output.summaryRef ?? Directives.createRef<HTMLElement>();
234232

@@ -390,8 +388,23 @@ export class PatchWidget extends UI.Widget.Widget {
390388
.jslogContext=${'patch-widget.info-tooltip-trigger'}
391389
.iconName=${'info'}
392390
.variant=${Buttons.Button.Variant.ICON}
393-
.title=${input.applyToWorkspaceTooltipText}
394391
></devtools-button>
392+
<devtools-tooltip
393+
id="info-tooltip"
394+
variant=${'rich'}
395+
>
396+
<div class="info-tooltip-container">
397+
${input.applyToWorkspaceTooltipText}
398+
<button
399+
class="link tooltip-link"
400+
role="link"
401+
jslog=${VisualLogging.link('open-ai-settings').track({
402+
click: true,
403+
})}
404+
@click=${input.onLearnMoreTooltipClick}
405+
>${lockedString(UIStringsNotTranslate.learnMore)}</button>
406+
</div>
407+
</devtools-tooltip>
395408
</div>
396409
</div>`;
397410
}
@@ -417,62 +430,11 @@ export class PatchWidget extends UI.Widget.Widget {
417430

418431
render(template, target, {host: target});
419432
});
420-
// We're using PopoverHelper as a workaround instead of using <devtools-tooltip>. See the bug for more details.
421-
// TODO: Update here when b/409965560 is fixed.
422-
this.#popoverHelper = new UI.PopoverHelper.PopoverHelper(this.contentElement, event => {
423-
// There are two ways this event is received for showing a popover case:
424-
// * The latest element on the composed path is `<devtools-button>`
425-
// * The 2nd element on the composed path is `<devtools-button>` (the last element is the `<button>` inside it.)
426-
const hoveredNode = event.composedPath()[0];
427-
const maybeDevToolsButton = event.composedPath()[2];
428-
429-
const popoverShownNode = hoveredNode instanceof HTMLElement && hoveredNode.getAttribute('aria-details') === 'info-tooltip' ? hoveredNode
430-
: maybeDevToolsButton instanceof HTMLElement && maybeDevToolsButton.getAttribute('aria-details') === 'info-tooltip' ? maybeDevToolsButton
431-
: null;
432-
if (!popoverShownNode) {
433-
return null;
434-
}
435-
return {
436-
box: popoverShownNode.boxInWindow(),
437-
show: async (popover: UI.GlassPane.GlassPane) => {
438-
// clang-format off
439-
render(html`
440-
<style>
441-
.info-tooltip-container {
442-
max-width: var(--sys-size-28);
443-
padding: var(--sys-size-4) var(--sys-size-5);
444-
445-
.tooltip-link {
446-
display: block;
447-
margin-top: var(--sys-size-4);
448-
color: var(--sys-color-primary);
449-
padding-left: 0;
450-
}
451-
}
452-
</style>
453-
<div class="info-tooltip-container">
454-
${UIStringsNotTranslate.applyToWorkspaceTooltip}
455-
<button
456-
class="link tooltip-link"
457-
role="link"
458-
jslog=${VisualLogging.link('open-ai-settings').track({
459-
click: true,
460-
})}
461-
@click=${this.#onLearnMoreTooltipClick}
462-
>${lockedString(UIStringsNotTranslate.learnMore)}</button>
463-
</div>`, popover.contentElement, {host: this});
464-
// clang-forat on
465-
return true;
466-
},
467-
};
468-
}, 'patch-widget.info-tooltip');
469-
this.#popoverHelper.setTimeout(0);
470433
// clang-format on
471434
this.requestUpdate();
472435
}
473436

474437
#onLearnMoreTooltipClick(): void {
475-
this.#viewOutput.tooltipRef?.value?.hidePopover();
476438
void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
477439
}
478440

front_end/panels/ai_assistance/components/ChatView.ts

Lines changed: 44 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
214214
const lockedString = i18n.i18n.lockedString;
215215

216216
const SCROLL_ROUNDING_OFFSET = 1;
217-
const TOOLTIP_POPOVER_OFFSET = 4;
218-
const RELEVANT_DATA_LINK_ID = 'relevant-data-link';
217+
const RELEVANT_DATA_LINK_FOOTER_ID = 'relevant-data-link-footer';
218+
const RELEVANT_DATA_LINK_CHAT_ID = 'relevant-data-link-chat';
219219

220220
export interface Step {
221221
isLoading: boolean;
@@ -313,7 +313,6 @@ export class ChatView extends HTMLElement {
313313
#messagesContainerElement?: Element;
314314
#mainElementRef?: Lit.Directives.Ref<Element> = Lit.Directives.createRef();
315315
#messagesContainerResizeObserver = new ResizeObserver(() => this.#handleMessagesContainerResize());
316-
#popoverHelper: UI.PopoverHelper.PopoverHelper|null = null;
317316
/**
318317
* Indicates whether the chat scroll position should be pinned to the bottom.
319318
*
@@ -391,63 +390,6 @@ export class ChatView extends HTMLElement {
391390
this.#setMainElementScrollTop(this.#mainElementRef.value.scrollHeight);
392391
}
393392

394-
#handleChatUiRef(el: Element|undefined): void {
395-
if (!el || this.#popoverHelper) {
396-
return;
397-
}
398-
399-
// TODO: Update here when b/409965560 is fixed.
400-
this.#popoverHelper = new UI.PopoverHelper.PopoverHelper((el as HTMLElement), event => {
401-
const popoverShownNode =
402-
event.target instanceof HTMLElement && event.target.id === RELEVANT_DATA_LINK_ID ? event.target : null;
403-
if (!popoverShownNode) {
404-
return null;
405-
}
406-
407-
// We move the glass pane to be a bit lower so
408-
// that it does not disappear when moving the cursor
409-
// over to link.
410-
const nodeBox = popoverShownNode.boxInWindow();
411-
nodeBox.y = nodeBox.y + TOOLTIP_POPOVER_OFFSET;
412-
return {
413-
box: nodeBox,
414-
show: async (popover: UI.GlassPane.GlassPane) => {
415-
// clang-format off
416-
Lit.render(html`
417-
<style>
418-
.info-tooltip-container {
419-
max-width: var(--sys-size-28);
420-
padding: var(--sys-size-4) var(--sys-size-5);
421-
422-
.tooltip-link {
423-
display: block;
424-
margin-top: var(--sys-size-4);
425-
color: var(--sys-color-primary);
426-
padding-left: 0;
427-
}
428-
}
429-
</style>
430-
<div class="info-tooltip-container">
431-
${this.#props.disclaimerText}
432-
<button
433-
class="link tooltip-link"
434-
role="link"
435-
jslog=${VisualLogging.link('open-ai-settings').track({
436-
click: true,
437-
})}
438-
@click=${() => {
439-
void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
440-
}}
441-
>${i18nString(UIStrings.learnAbout)}</button>
442-
</div>`, popover.contentElement, {host: this});
443-
// clang-format on
444-
return true;
445-
},
446-
};
447-
});
448-
this.#popoverHelper.setTimeout(0);
449-
}
450-
451393
#handleMessagesContainerResize(): void {
452394
if (!this.#pinScrollToBottom) {
453395
return;
@@ -583,9 +525,11 @@ export class ChatView extends HTMLElement {
583525
// clang-format off
584526
const footerContents = this.#props.conversationType
585527
? renderRelevantDataDisclaimer({
586-
isLoading: this.#props.isLoading,
587-
blockedByCrossOrigin: this.#props.blockedByCrossOrigin,
588-
})
528+
isLoading: this.#props.isLoading,
529+
blockedByCrossOrigin: this.#props.blockedByCrossOrigin,
530+
tooltipId: RELEVANT_DATA_LINK_FOOTER_ID,
531+
disclaimerText: this.#props.disclaimerText,
532+
})
589533
: html`<p>
590534
${lockedString(UIStringsNotTranslate.inputDisclaimerForEmptyState)}
591535
<button
@@ -611,7 +555,7 @@ export class ChatView extends HTMLElement {
611555
// clang-format off
612556
Lit.render(html`
613557
<style>${chatViewStyles}</style>
614-
<div class="chat-ui" ${Lit.Directives.ref(this.#handleChatUiRef)}>
558+
<div class="chat-ui">
615559
<main @scroll=${this.#handleScroll} ${ref(this.#mainElementRef)}>
616560
${renderMainContents({
617561
state: this.#props.state,
@@ -643,6 +587,7 @@ export class ChatView extends HTMLElement {
643587
isTextInputDisabled: this.#props.isTextInputDisabled,
644588
inputPlaceholder: this.#props.inputPlaceholder,
645589
state: this.#props.state,
590+
disclaimerText: this.#props.disclaimerText,
646591
selectedContext: this.#props.selectedContext,
647592
inspectElementToggled: this.#props.inspectElementToggled,
648593
multimodalInputEnabled: this.#props.multimodalInputEnabled,
@@ -1433,8 +1378,12 @@ function renderImageInput({
14331378
// clang-format on
14341379
}
14351380

1436-
function renderRelevantDataDisclaimer(
1437-
{isLoading, blockedByCrossOrigin}: {isLoading: boolean, blockedByCrossOrigin: boolean}): Lit.LitTemplate {
1381+
function renderRelevantDataDisclaimer({isLoading, blockedByCrossOrigin, tooltipId, disclaimerText}: {
1382+
isLoading: boolean,
1383+
blockedByCrossOrigin: boolean,
1384+
tooltipId: string,
1385+
disclaimerText: string,
1386+
}): Lit.LitTemplate {
14381387
const classes =
14391388
Lit.Directives.classMap({'chat-input-disclaimer': true, 'hide-divider': !isLoading && blockedByCrossOrigin});
14401389
// clang-format off
@@ -1443,14 +1392,15 @@ function renderRelevantDataDisclaimer(
14431392
<button
14441393
class="link"
14451394
role="link"
1446-
id=${RELEVANT_DATA_LINK_ID}
1395+
aria-details=${tooltipId}
14471396
jslog=${VisualLogging.link('open-ai-settings').track({
14481397
click: true,
14491398
})}
14501399
@click=${() => {
14511400
void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
14521401
}}
14531402
>${lockedString('Relevant data')}</button>&nbsp;${lockedString('is sent to Google')}
1403+
${renderDisclamerTooltip(tooltipId, disclaimerText)}
14541404
</p>
14551405
`;
14561406
// clang-format on
@@ -1470,6 +1420,7 @@ function renderChatInput({
14701420
isTextInputEmpty,
14711421
uploadImageInputEnabled,
14721422
aidaAvailability,
1423+
disclaimerText,
14731424
onContextClick,
14741425
onInspectElementClick,
14751426
onSubmit,
@@ -1490,6 +1441,7 @@ function renderChatInput({
14901441
inspectElementToggled: boolean,
14911442
isTextInputEmpty: boolean,
14921443
aidaAvailability: Host.AidaClient.AidaAccessPreconditions,
1444+
disclaimerText: string,
14931445
onContextClick: () => void,
14941446
onInspectElementClick: () => void,
14951447
onSubmit: (ev: SubmitEvent) => void,
@@ -1547,7 +1499,7 @@ function renderChatInput({
15471499
</div>
15481500
<div class="chat-input-actions-right">
15491501
<div class="chat-input-disclaimer-container">
1550-
${renderRelevantDataDisclaimer({isLoading, blockedByCrossOrigin})}
1502+
${renderRelevantDataDisclaimer({ isLoading, blockedByCrossOrigin, tooltipId: RELEVANT_DATA_LINK_CHAT_ID, disclaimerText})}
15511503
</div>
15521504
${renderMultimodalInputButtons({
15531505
multimodalInputEnabled, blockedByCrossOrigin, isTextInputDisabled, imageInput, uploadImageInputEnabled, onTakeScreenshot, onImageUpload
@@ -1697,6 +1649,30 @@ function renderMainContents({
16971649
return renderEmptyState({isTextInputDisabled, suggestions, onSuggestionClick});
16981650
}
16991651

1652+
function renderDisclamerTooltip(id: string, disclaimerText: string): Lit.TemplateResult {
1653+
// clang-format off
1654+
return html`
1655+
<devtools-tooltip
1656+
id=${id}
1657+
variant=${'rich'}
1658+
>
1659+
<div class="info-tooltip-container">
1660+
${disclaimerText}
1661+
<button
1662+
class="link tooltip-link"
1663+
role="link"
1664+
jslog=${VisualLogging.link('open-ai-settings').track({
1665+
click: true,
1666+
})}
1667+
@click=${() => {
1668+
void UI.ViewManager.ViewManager.instance().showView('chrome-ai');
1669+
}}>${i18nString(UIStrings.learnAbout)}
1670+
</button>
1671+
</div>
1672+
</devtools-tooltip>`;
1673+
// clang-format on
1674+
}
1675+
17001676
declare global {
17011677
interface HTMLElementTagNameMap {
17021678
'devtools-ai-chat-view': ChatView;

front_end/panels/ai_assistance/components/chatView.css

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@
8989
color: var(--sys-color-on-surface-subtle);
9090
}
9191

92+
.info-tooltip-container {
93+
max-width: var(--sys-size-28);
94+
padding: var(--sys-size-4) var(--sys-size-5);
95+
}
96+
97+
.tooltip-link {
98+
display: block;
99+
margin-top: var(--sys-size-4);
100+
color: var(--sys-color-primary);
101+
padding-left: 0;
102+
}
103+
92104
.chat-input-container {
93105
width: 100%;
94106
display: flex;

0 commit comments

Comments
 (0)