Skip to content

Commit 2de6ccf

Browse files
ergunshDevtools-frontend LUCI CQ
authored andcommitted
[Freestyler] Update no agent empty state design
Screenshot: https://g-issues.chromium.org/action/issues/40248266/attachments/60631650?download=false Bug: 376431804 Change-Id: If3cdd2d99abad29dad48e1d1df7e74b21de3db58 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5999713 Reviewed-by: Nikolay Vitkov <[email protected]> Commit-Queue: Ergün Erdoğmuş <[email protected]> Reviewed-by: Alex Rudenko <[email protected]>
1 parent cd5440f commit 2de6ccf

File tree

7 files changed

+177
-122
lines changed

7 files changed

+177
-122
lines changed

config/gni/devtools_grd_files.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ grd_files_release_sources = [
5555
"front_end/Images/breakpoint-circle.svg",
5656
"front_end/Images/breakpoint-crossed-filled.svg",
5757
"front_end/Images/breakpoint-crossed.svg",
58+
"front_end/Images/brush-2.svg",
5859
"front_end/Images/brush-filled.svg",
5960
"front_end/Images/brush.svg",
6061
"front_end/Images/bug.svg",

config/gni/devtools_image_files.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ devtools_svg_sources = [
6262
"breakpoint-circle.svg",
6363
"breakpoint-crossed-filled.svg",
6464
"breakpoint-crossed.svg",
65+
"brush-2.svg",
6566
"brush-filled.svg",
6667
"brush.svg",
6768
"bug.svg",

front_end/Images/src/brush-2.svg

Lines changed: 3 additions & 0 deletions
Loading

front_end/panels/freestyler/components/FreestylerChatUi.test.ts

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -118,35 +118,64 @@ css
118118
assert.strictEqual(chatInput.placeholder, 'Ask a question about the selected element');
119119
});
120120

121-
it('shows usage instructions', async () => {
122-
const stub = getGetHostConfigStub({
123-
devToolsFreestyler: {
124-
enabled: true,
125-
},
126-
devToolsAiAssistanceNetworkAgent: {
127-
enabled: true,
128-
},
129-
devToolsAiAssistanceFileAgent: {
130-
enabled: true,
131-
},
132-
devToolsAiAssistancePerformanceAgent: {
133-
enabled: true,
134-
},
135-
});
136-
const props = getProp({
137-
agentType: undefined,
121+
describe('no agent empty state', () => {
122+
it('should show feature cards for enabled features', () => {
123+
const stub = getGetHostConfigStub({
124+
devToolsFreestyler: {
125+
enabled: true,
126+
},
127+
devToolsAiAssistanceNetworkAgent: {
128+
enabled: true,
129+
},
130+
devToolsAiAssistanceFileAgent: {
131+
enabled: true,
132+
},
133+
devToolsAiAssistancePerformanceAgent: {
134+
enabled: true,
135+
},
136+
});
137+
const props = getProp({
138+
agentType: undefined,
139+
});
140+
const chat = new Freestyler.FreestylerChatUi(props);
141+
renderElementIntoDOM(chat);
142+
const featureCards = chat.shadowRoot?.querySelectorAll('.feature-card');
143+
assert.isDefined(featureCards);
144+
assert.strictEqual(featureCards?.length, 4);
145+
assert.strictEqual(featureCards[0].querySelector('.feature-card-content h3')?.textContent, 'CSS styles');
146+
assert.strictEqual(featureCards[1].querySelector('.feature-card-content h3')?.textContent, 'Network');
147+
assert.strictEqual(featureCards[2].querySelector('.feature-card-content h3')?.textContent, 'Files');
148+
assert.strictEqual(featureCards[3].querySelector('.feature-card-content h3')?.textContent, 'Performance');
149+
150+
stub.restore();
138151
});
139-
const chat = new Freestyler.FreestylerChatUi(props);
140-
renderElementIntoDOM(chat);
141-
const instructions = chat.shadowRoot?.querySelectorAll('.instructions strong');
142-
assert.isDefined(instructions);
143-
assert.strictEqual(instructions?.length, 4);
144-
assert.strictEqual(instructions[0].textContent, 'CSS help:');
145-
assert.strictEqual(instructions[1].textContent, 'File insights:');
146-
assert.strictEqual(instructions[2].textContent, 'Network request insights:');
147-
assert.strictEqual(instructions[3].textContent, 'Performance analysis:');
148152

149-
stub.restore();
153+
it('should not show any feature cards if none of the entrypoints are available', () => {
154+
const stub = getGetHostConfigStub({
155+
devToolsFreestyler: {
156+
enabled: false,
157+
},
158+
devToolsAiAssistanceNetworkAgent: {
159+
enabled: false,
160+
},
161+
devToolsAiAssistanceFileAgent: {
162+
enabled: false,
163+
},
164+
devToolsAiAssistancePerformanceAgent: {
165+
enabled: false,
166+
},
167+
});
168+
const props = getProp({
169+
agentType: undefined,
170+
});
171+
const chat = new Freestyler.FreestylerChatUi(props);
172+
renderElementIntoDOM(chat);
173+
const featureCards = chat.shadowRoot?.querySelectorAll('.feature-card');
174+
assert.isDefined(featureCards);
175+
assert.strictEqual(featureCards?.length, 0);
176+
177+
stub.restore();
178+
});
150179
});
151180
});
152181
});

front_end/panels/freestyler/components/FreestylerChatUi.ts

Lines changed: 75 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ const UIStringsNotTranslate = {
139139
*@description Text for the empty state of the AI assistance panel.
140140
*/
141141
emptyStateText: 'How can I help you?',
142+
/**
143+
*@description Text for the empty state of the AI assistance panel when there is no agent selected.
144+
*/
145+
noAgentStateText: 'Explore AI assistance',
142146
/**
143147
* @description The error message when the LLM loop is stopped for some reason (Max steps reached or request to LLM failed)
144148
*/
@@ -204,46 +208,6 @@ const UIStringsNotTranslate = {
204208
*@description Aria label for the cancel icon to be read by screen reader
205209
*/
206210
canceled: 'Canceled',
207-
/*
208-
* @description Header text for instructions on how to use the AI assistance feature.
209-
*/
210-
getStarted: 'Hi! Here’s how to get started:',
211-
/**
212-
* @description AI assistance for CSS.
213-
*/
214-
cssHelp: 'CSS help:',
215-
/**
216-
* @description Explanation on how to use AI assistance for DOM elements.
217-
*/
218-
cssHelpExplainer:
219-
'Navigate to the Elements panel, right-click a DOM element, and select "Ask AI assistant". I’ll be happy to explain its styles or behavior.',
220-
/**
221-
* @description AI assistance for files.
222-
*/
223-
fileHelp: 'File insights:',
224-
/**
225-
* @description Explanation on how to use AI assistance for files in the Sources panel.
226-
*/
227-
fileHelpExplainer:
228-
'Open the Sources panel, right-click a file, and select "Ask AI". I can provide insights into its purpose or origin.',
229-
/**
230-
* @description AI assistance for network requests.
231-
*/
232-
networkHelp: 'Network request insights:',
233-
/**
234-
* @description Explanation on how to use AI assistance for network requests.
235-
*/
236-
networkHelpExplainer:
237-
'In the Network panel, right-click any request and select "Ask AI assistant". I’ll help break down what’s happening with each request.',
238-
/**
239-
* @description AI assistance for performance traces.
240-
*/
241-
performanceHelp: 'Performance analysis:',
242-
/**
243-
* @description Explanation on how to use AI assistance for performance traces.
244-
*/
245-
performanceHelpExplainer:
246-
'In the Performance panel, run a trace. Then, right-click any function in the timeline and select "Ask AI". I’ll help you analyze its performance impact and suggest improvements.',
247211
};
248212

249213
const str_ = i18n.i18n.registerUIStrings('panels/freestyler/components/FreestylerChatUi.ts', UIStrings);
@@ -858,7 +822,7 @@ export class FreestylerChatUi extends HTMLElement {
858822
</div>
859823
<h1>${lockedString(UIStringsNotTranslate.emptyStateText)}</h1>
860824
</div>
861-
<div class="suggestions">
825+
<div class="empty-state-content">
862826
${suggestions.map(suggestion => {
863827
return html`<devtools-button
864828
class="suggestion"
@@ -991,7 +955,11 @@ export class FreestylerChatUi extends HTMLElement {
991955
// clang-format on
992956
}
993957

994-
#renderChatInput = (): LitHtml.TemplateResult => {
958+
#renderChatInput = (): LitHtml.LitTemplate => {
959+
if (!this.#props.agentType) {
960+
return LitHtml.nothing;
961+
}
962+
995963
// clang-format off
996964
return html`
997965
<div class="chat-input-container">
@@ -1087,33 +1055,75 @@ export class FreestylerChatUi extends HTMLElement {
10871055

10881056
#renderNoAgentState(): LitHtml.TemplateResult {
10891057
const config = Common.Settings.Settings.instance().getHostConfig();
1058+
const featureCards: {
1059+
icon: string,
1060+
heading: string,
1061+
content: LitHtml.TemplateResult,
1062+
}[] =
1063+
[
1064+
...(config.devToolsFreestyler?.enabled ? [{
1065+
icon: 'brush-2',
1066+
heading: 'CSS styles',
1067+
content: html`Open <button class="link" role="link" jslog=${
1068+
VisualLogging.link('open-elements-panel').track({click: true})} @click=${() => {
1069+
void UI.ViewManager.ViewManager.instance().showView('elements');
1070+
}}>Elements</button> to ask about CSS styles`,
1071+
}] :
1072+
[]),
1073+
...(config.devToolsAiAssistanceNetworkAgent?.enabled) ? [{
1074+
icon: 'arrow-up-down',
1075+
heading: 'Network',
1076+
content: html`Open <button class="link" role="link" jslog=${
1077+
VisualLogging.link('open-network-panel').track({click: true})} @click=${() => {
1078+
void UI.ViewManager.ViewManager.instance().showView('network');
1079+
}}>Network</button> to ask about a request's details`,
1080+
}] :
1081+
[],
1082+
...(config.devToolsAiAssistanceFileAgent?.enabled) ? [{
1083+
icon: 'document',
1084+
heading: 'Files',
1085+
content: html`Open <button class="link" role="link" jslog=${
1086+
VisualLogging.link('open-sources-panel').track({click: true})} @click=${() => {
1087+
void UI.ViewManager.ViewManager.instance().showView('sources');
1088+
}}>Sources</button> to ask about a file's content`,
1089+
}] :
1090+
[],
1091+
...(config.devToolsAiAssistancePerformanceAgent?.enabled ? [{
1092+
icon: 'performance',
1093+
heading: 'Performance',
1094+
content: html`Open <button class="link" role="link" jslog=${
1095+
VisualLogging.link('open-performance-panel').track({click: true})} @click=${() => {
1096+
void UI.ViewManager.ViewManager.instance().showView('timeline');
1097+
}}>Performance</button> to ask about a trace item`,
1098+
}] :
1099+
[]),
1100+
];
10901101

10911102
// clang-format off
10921103
return html`
1093-
<div class="messages-container">
1094-
<section class="no-agent-message" jslog=${VisualLogging.section('no-agent-entrypoint')}>
1095-
<div class="header">
1096-
<devtools-icon name="smart-assistant"></devtools-icon>
1097-
<h2>${lockedString(UIStringsNotTranslate.ai)}</h2>
1098-
</div>
1099-
<div class="instructions">
1100-
<p>${lockedString(UIStringsNotTranslate.getStarted)}</p>
1101-
${config.devToolsFreestyler?.enabled ? html`
1102-
<p><strong>${lockedString(UIStringsNotTranslate.cssHelp)}</strong> ${lockedString(UIStringsNotTranslate.cssHelpExplainer)}</p>
1103-
` : LitHtml.nothing}
1104-
${(config.devToolsAiAssistanceFileAgent?.enabled) ? html`
1105-
<p><strong>${lockedString(UIStringsNotTranslate.fileHelp)}</strong> ${lockedString(UIStringsNotTranslate.fileHelpExplainer)}</p>
1106-
` : LitHtml.nothing}
1107-
${(config.devToolsAiAssistanceNetworkAgent?.enabled) ? html`
1108-
<p><strong>${lockedString(UIStringsNotTranslate.networkHelp)}</strong> ${lockedString(UIStringsNotTranslate.networkHelpExplainer)}</p>
1109-
` : LitHtml.nothing}
1110-
${(config.devToolsAiAssistancePerformanceAgent?.enabled) ? html`
1111-
<p><strong>${lockedString(UIStringsNotTranslate.performanceHelp)}</strong> ${lockedString(UIStringsNotTranslate.performanceHelpExplainer)}</p>
1112-
` : LitHtml.nothing}
1104+
<div class="empty-state-container">
1105+
<div class="header">
1106+
<div class="icon">
1107+
<devtools-icon
1108+
name="smart-assistant"
1109+
></devtools-icon>
11131110
</div>
1114-
</section>
1115-
</div>
1116-
`;
1111+
<h1>${lockedString(UIStringsNotTranslate.noAgentStateText)}</h1>
1112+
</div>
1113+
<div class="empty-state-content">
1114+
${featureCards.map(featureCard => html`
1115+
<div class="feature-card">
1116+
<div class="feature-card-icon">
1117+
<devtools-icon name=${featureCard.icon}></devtools-icon>
1118+
</div>
1119+
<div class="feature-card-content">
1120+
<h3>${featureCard.heading}</h3>
1121+
<p>${featureCard.content}</p>
1122+
</div>
1123+
</div>
1124+
`)}
1125+
</div>
1126+
</div>`;
11171127
// clang-format on
11181128
}
11191129

front_end/panels/freestyler/components/freestylerChatUi.css

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -264,35 +264,6 @@
264264
}
265265
}
266266

267-
.no-agent-message {
268-
user-select: text;
269-
cursor: initial;
270-
display: flex;
271-
flex-direction: column;
272-
gap: var(--sys-size-5);
273-
width: 100%;
274-
padding: var(--sys-size-7) var(--sys-size-5);
275-
height: 100%;
276-
277-
.header {
278-
display: flex;
279-
align-items: center;
280-
height: var(--sys-size-11);
281-
gap: var(--sys-size-4);
282-
283-
h2 {
284-
font: var(--sys-typescale-body4-bold);
285-
}
286-
}
287-
288-
.instructions {
289-
display: flex;
290-
flex-direction: column;
291-
gap: var(--sys-size-6);
292-
line-height: 18px;
293-
}
294-
}
295-
296267
.indicator {
297268
color: var(--sys-color-green-bright);
298269
}
@@ -530,7 +501,7 @@ main {
530501
}
531502
}
532503

533-
.suggestions {
504+
.empty-state-content {
534505
display: flex;
535506
flex-direction: column;
536507
gap: var(--sys-size-5);
@@ -540,6 +511,42 @@ main {
540511
}
541512
}
542513

514+
.feature-card {
515+
display: flex;
516+
padding: var(--sys-size-4) var(--sys-size-6);
517+
gap: 10px;
518+
background-color: var(--sys-color-surface2);
519+
border-radius: var(--sys-shape-corner-medium-small);
520+
width: var(--sys-size-32);
521+
align-items: center;
522+
523+
.feature-card-icon {
524+
width: var(--sys-size-12);
525+
height: var(--sys-size-12);
526+
display: flex;
527+
justify-content: center;
528+
align-items: center;
529+
background-color: var(--sys-color-tonal-container);
530+
border-radius: var(--sys-shape-corner-full);
531+
532+
devtools-icon {
533+
width: 18px;
534+
height: 18px;
535+
}
536+
}
537+
538+
.feature-card-content {
539+
h3 {
540+
font: var(--sys-typescale-body3-medium);
541+
}
542+
543+
p {
544+
font: var(--sys-typescale-body4-regular);
545+
line-height: 18px;
546+
}
547+
}
548+
}
549+
543550
.disabled-view {
544551
display: flex;
545552
max-width: var(--sys-size-34);

front_end/ui/visual_logging/KnownContextValues.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2171,12 +2171,16 @@ export const knownContextValues = new Set([
21712171
'only-show-third-party',
21722172
'opacity',
21732173
'open-ai-settings',
2174+
'open-elements-panel',
21742175
'open-folder',
21752176
'open-in-animations-panel',
21762177
'open-in-containing-folder',
21772178
'open-in-new-tab',
21782179
'open-link-handler',
21792180
'open-memory-inspector',
2181+
'open-network-panel',
2182+
'open-performance-panel',
2183+
'open-sources-panel',
21802184
'open-using',
21812185
'opened-windows',
21822186
'opera-mac',

0 commit comments

Comments
 (0)