[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 <nvitkov@chromium.org>
Commit-Queue: Ergün Erdoğmuş <ergunsh@chromium.org>
Reviewed-by: Alex Rudenko <alexrudenko@chromium.org>
diff --git a/config/gni/devtools_grd_files.gni b/config/gni/devtools_grd_files.gni
index 15c7f5b..314831d 100644
--- a/config/gni/devtools_grd_files.gni
+++ b/config/gni/devtools_grd_files.gni
@@ -55,6 +55,7 @@
   "front_end/Images/breakpoint-circle.svg",
   "front_end/Images/breakpoint-crossed-filled.svg",
   "front_end/Images/breakpoint-crossed.svg",
+  "front_end/Images/brush-2.svg",
   "front_end/Images/brush-filled.svg",
   "front_end/Images/brush.svg",
   "front_end/Images/bug.svg",
diff --git a/config/gni/devtools_image_files.gni b/config/gni/devtools_image_files.gni
index 19196ea..3c595f6 100644
--- a/config/gni/devtools_image_files.gni
+++ b/config/gni/devtools_image_files.gni
@@ -62,6 +62,7 @@
   "breakpoint-circle.svg",
   "breakpoint-crossed-filled.svg",
   "breakpoint-crossed.svg",
+  "brush-2.svg",
   "brush-filled.svg",
   "brush.svg",
   "bug.svg",
diff --git a/front_end/Images/src/brush-2.svg b/front_end/Images/src/brush-2.svg
new file mode 100644
index 0000000..e2c6c98
--- /dev/null
+++ b/front_end/Images/src/brush-2.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.14583 17.1042C4.52083 17.1042 3.93403 16.9618 3.38542 16.6771C2.83681 16.3924 2.375 16.0069 2 15.5208C2.43056 15.4931 2.79861 15.3333 3.10417 15.0417C3.40972 14.75 3.5625 14.3889 3.5625 13.9583C3.5625 13.2917 3.79271 12.7326 4.25312 12.2812C4.7134 11.8299 5.27243 11.6042 5.93021 11.6042C6.58785 11.6042 7.14236 11.8331 7.59375 12.2908C8.04514 12.7486 8.27083 13.3044 8.27083 13.9583C8.27083 14.8333 7.96875 15.5764 7.36458 16.1875C6.76042 16.7986 6.02083 17.1042 5.14583 17.1042ZM5.14583 15.7083C5.62708 15.7083 6.0391 15.5369 6.38187 15.1942C6.72451 14.8515 6.89583 14.4396 6.89583 13.9583C6.89583 13.6944 6.80208 13.4687 6.61458 13.2812C6.42708 13.0937 6.20139 13 5.9375 13C5.67361 13 5.44792 13.0937 5.26042 13.2812C5.07292 13.4687 4.97917 13.6944 4.97917 13.9583C4.97917 14.2639 4.94444 14.559 4.875 14.8437C4.80556 15.1285 4.67361 15.3819 4.47917 15.6042C4.59028 15.6319 4.70139 15.6562 4.8125 15.6771C4.92361 15.6979 5.03472 15.7083 5.14583 15.7083ZM10.0625 12.1667L7.9375 10.0417L14.5833 3.39583C14.7778 3.20139 15.0139 3.10416 15.2917 3.10416C15.5694 3.10416 15.8056 3.20139 16 3.39583L16.7083 4.10416C16.9028 4.30486 17 4.53909 17 4.80687C17 5.07451 16.9028 5.30555 16.7083 5.5L10.0625 12.1667Z" fill="black"/>
+</svg>
diff --git a/front_end/panels/freestyler/components/FreestylerChatUi.test.ts b/front_end/panels/freestyler/components/FreestylerChatUi.test.ts
index 7ee323a..efe5c6f 100644
--- a/front_end/panels/freestyler/components/FreestylerChatUi.test.ts
+++ b/front_end/panels/freestyler/components/FreestylerChatUi.test.ts
@@ -118,35 +118,64 @@
       assert.strictEqual(chatInput.placeholder, 'Ask a question about the selected element');
     });
 
-    it('shows usage instructions', async () => {
-      const stub = getGetHostConfigStub({
-        devToolsFreestyler: {
-          enabled: true,
-        },
-        devToolsAiAssistanceNetworkAgent: {
-          enabled: true,
-        },
-        devToolsAiAssistanceFileAgent: {
-          enabled: true,
-        },
-        devToolsAiAssistancePerformanceAgent: {
-          enabled: true,
-        },
-      });
-      const props = getProp({
-        agentType: undefined,
-      });
-      const chat = new Freestyler.FreestylerChatUi(props);
-      renderElementIntoDOM(chat);
-      const instructions = chat.shadowRoot?.querySelectorAll('.instructions strong');
-      assert.isDefined(instructions);
-      assert.strictEqual(instructions?.length, 4);
-      assert.strictEqual(instructions[0].textContent, 'CSS help:');
-      assert.strictEqual(instructions[1].textContent, 'File insights:');
-      assert.strictEqual(instructions[2].textContent, 'Network request insights:');
-      assert.strictEqual(instructions[3].textContent, 'Performance analysis:');
+    describe('no agent empty state', () => {
+      it('should show feature cards for enabled features', () => {
+        const stub = getGetHostConfigStub({
+          devToolsFreestyler: {
+            enabled: true,
+          },
+          devToolsAiAssistanceNetworkAgent: {
+            enabled: true,
+          },
+          devToolsAiAssistanceFileAgent: {
+            enabled: true,
+          },
+          devToolsAiAssistancePerformanceAgent: {
+            enabled: true,
+          },
+        });
+        const props = getProp({
+          agentType: undefined,
+        });
+        const chat = new Freestyler.FreestylerChatUi(props);
+        renderElementIntoDOM(chat);
+        const featureCards = chat.shadowRoot?.querySelectorAll('.feature-card');
+        assert.isDefined(featureCards);
+        assert.strictEqual(featureCards?.length, 4);
+        assert.strictEqual(featureCards[0].querySelector('.feature-card-content h3')?.textContent, 'CSS styles');
+        assert.strictEqual(featureCards[1].querySelector('.feature-card-content h3')?.textContent, 'Network');
+        assert.strictEqual(featureCards[2].querySelector('.feature-card-content h3')?.textContent, 'Files');
+        assert.strictEqual(featureCards[3].querySelector('.feature-card-content h3')?.textContent, 'Performance');
 
-      stub.restore();
+        stub.restore();
+      });
+
+      it('should not show any feature cards if none of the entrypoints are available', () => {
+        const stub = getGetHostConfigStub({
+          devToolsFreestyler: {
+            enabled: false,
+          },
+          devToolsAiAssistanceNetworkAgent: {
+            enabled: false,
+          },
+          devToolsAiAssistanceFileAgent: {
+            enabled: false,
+          },
+          devToolsAiAssistancePerformanceAgent: {
+            enabled: false,
+          },
+        });
+        const props = getProp({
+          agentType: undefined,
+        });
+        const chat = new Freestyler.FreestylerChatUi(props);
+        renderElementIntoDOM(chat);
+        const featureCards = chat.shadowRoot?.querySelectorAll('.feature-card');
+        assert.isDefined(featureCards);
+        assert.strictEqual(featureCards?.length, 0);
+
+        stub.restore();
+      });
     });
   });
 });
diff --git a/front_end/panels/freestyler/components/FreestylerChatUi.ts b/front_end/panels/freestyler/components/FreestylerChatUi.ts
index 37adad7..42e6e34 100644
--- a/front_end/panels/freestyler/components/FreestylerChatUi.ts
+++ b/front_end/panels/freestyler/components/FreestylerChatUi.ts
@@ -140,6 +140,10 @@
    */
   emptyStateText: 'How can I help you?',
   /**
+   *@description Text for the empty state of the AI assistance panel when there is no agent selected.
+   */
+  noAgentStateText: 'Explore AI assistance',
+  /**
    * @description The error message when the LLM loop is stopped for some reason (Max steps reached or request to LLM failed)
    */
   systemError:
@@ -204,46 +208,6 @@
    *@description Aria label for the cancel icon to be read by screen reader
    */
   canceled: 'Canceled',
-  /*
-   * @description Header text for instructions on how to use the AI assistance feature.
-   */
-  getStarted: 'Hi! Here’s how to get started:',
-  /**
-   * @description AI assistance for CSS.
-   */
-  cssHelp: 'CSS help:',
-  /**
-   * @description Explanation on how to use AI assistance for DOM elements.
-   */
-  cssHelpExplainer:
-      '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.',
-  /**
-   * @description AI assistance for files.
-   */
-  fileHelp: 'File insights:',
-  /**
-   * @description Explanation on how to use AI assistance for files in the Sources panel.
-   */
-  fileHelpExplainer:
-      'Open the Sources panel, right-click a file, and select "Ask AI". I can provide insights into its purpose or origin.',
-  /**
-   * @description AI assistance for network requests.
-   */
-  networkHelp: 'Network request insights:',
-  /**
-   * @description Explanation on how to use AI assistance for network requests.
-   */
-  networkHelpExplainer:
-      'In the Network panel, right-click any request and select "Ask AI assistant". I’ll help break down what’s happening with each request.',
-  /**
-   * @description AI assistance for performance traces.
-   */
-  performanceHelp: 'Performance analysis:',
-  /**
-   * @description Explanation on how to use AI assistance for performance traces.
-   */
-  performanceHelpExplainer:
-      '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.',
 };
 
 const str_ = i18n.i18n.registerUIStrings('panels/freestyler/components/FreestylerChatUi.ts', UIStrings);
@@ -858,7 +822,7 @@
         </div>
         <h1>${lockedString(UIStringsNotTranslate.emptyStateText)}</h1>
       </div>
-      <div class="suggestions">
+      <div class="empty-state-content">
         ${suggestions.map(suggestion => {
           return html`<devtools-button
             class="suggestion"
@@ -991,7 +955,11 @@
     // clang-format on
   }
 
-  #renderChatInput = (): LitHtml.TemplateResult => {
+  #renderChatInput = (): LitHtml.LitTemplate => {
+    if (!this.#props.agentType) {
+      return LitHtml.nothing;
+    }
+
     // clang-format off
     return html`
       <div class="chat-input-container">
@@ -1087,33 +1055,75 @@
 
   #renderNoAgentState(): LitHtml.TemplateResult {
     const config = Common.Settings.Settings.instance().getHostConfig();
+    const featureCards: {
+      icon: string,
+      heading: string,
+      content: LitHtml.TemplateResult,
+    }[] =
+        [
+          ...(config.devToolsFreestyler?.enabled ? [{
+            icon: 'brush-2',
+            heading: 'CSS styles',
+            content: html`Open <button class="link" role="link" jslog=${
+                VisualLogging.link('open-elements-panel').track({click: true})} @click=${() => {
+              void UI.ViewManager.ViewManager.instance().showView('elements');
+            }}>Elements</button> to ask about CSS styles`,
+          }] :
+                                                   []),
+          ...(config.devToolsAiAssistanceNetworkAgent?.enabled) ? [{
+            icon: 'arrow-up-down',
+            heading: 'Network',
+            content: html`Open <button class="link" role="link" jslog=${
+                VisualLogging.link('open-network-panel').track({click: true})} @click=${() => {
+              void UI.ViewManager.ViewManager.instance().showView('network');
+            }}>Network</button> to ask about a request's details`,
+          }] :
+                                                                  [],
+          ...(config.devToolsAiAssistanceFileAgent?.enabled) ? [{
+            icon: 'document',
+            heading: 'Files',
+            content: html`Open <button class="link" role="link" jslog=${
+                VisualLogging.link('open-sources-panel').track({click: true})} @click=${() => {
+              void UI.ViewManager.ViewManager.instance().showView('sources');
+            }}>Sources</button> to ask about a file's content`,
+          }] :
+                                                               [],
+          ...(config.devToolsAiAssistancePerformanceAgent?.enabled ? [{
+            icon: 'performance',
+            heading: 'Performance',
+            content: html`Open <button class="link" role="link" jslog=${
+                VisualLogging.link('open-performance-panel').track({click: true})} @click=${() => {
+              void UI.ViewManager.ViewManager.instance().showView('timeline');
+            }}>Performance</button> to ask about a trace item`,
+          }] :
+                                                                     []),
+        ];
 
     // clang-format off
     return html`
-      <div class="messages-container">
-        <section class="no-agent-message" jslog=${VisualLogging.section('no-agent-entrypoint')}>
-          <div class="header">
-            <devtools-icon name="smart-assistant"></devtools-icon>
-            <h2>${lockedString(UIStringsNotTranslate.ai)}</h2>
+      <div class="empty-state-container">
+        <div class="header">
+          <div class="icon">
+            <devtools-icon
+              name="smart-assistant"
+            ></devtools-icon>
           </div>
-          <div class="instructions">
-            <p>${lockedString(UIStringsNotTranslate.getStarted)}</p>
-            ${config.devToolsFreestyler?.enabled ? html`
-              <p><strong>${lockedString(UIStringsNotTranslate.cssHelp)}</strong> ${lockedString(UIStringsNotTranslate.cssHelpExplainer)}</p>
-            ` : LitHtml.nothing}
-            ${(config.devToolsAiAssistanceFileAgent?.enabled) ? html`
-              <p><strong>${lockedString(UIStringsNotTranslate.fileHelp)}</strong> ${lockedString(UIStringsNotTranslate.fileHelpExplainer)}</p>
-            ` : LitHtml.nothing}
-            ${(config.devToolsAiAssistanceNetworkAgent?.enabled) ? html`
-              <p><strong>${lockedString(UIStringsNotTranslate.networkHelp)}</strong> ${lockedString(UIStringsNotTranslate.networkHelpExplainer)}</p>
-            ` : LitHtml.nothing}
-            ${(config.devToolsAiAssistancePerformanceAgent?.enabled) ? html`
-              <p><strong>${lockedString(UIStringsNotTranslate.performanceHelp)}</strong> ${lockedString(UIStringsNotTranslate.performanceHelpExplainer)}</p>
-            ` : LitHtml.nothing}
-          </div>
-        </section>
-      </div>
-    `;
+          <h1>${lockedString(UIStringsNotTranslate.noAgentStateText)}</h1>
+        </div>
+        <div class="empty-state-content">
+          ${featureCards.map(featureCard => html`
+            <div class="feature-card">
+              <div class="feature-card-icon">
+                <devtools-icon name=${featureCard.icon}></devtools-icon>
+              </div>
+              <div class="feature-card-content">
+                <h3>${featureCard.heading}</h3>
+                <p>${featureCard.content}</p>
+              </div>
+            </div>
+          `)}
+        </div>
+      </div>`;
     // clang-format on
   }
 
diff --git a/front_end/panels/freestyler/components/freestylerChatUi.css b/front_end/panels/freestyler/components/freestylerChatUi.css
index 344ba8e..9c84a8c 100644
--- a/front_end/panels/freestyler/components/freestylerChatUi.css
+++ b/front_end/panels/freestyler/components/freestylerChatUi.css
@@ -264,35 +264,6 @@
   }
 }
 
-.no-agent-message {
-  user-select: text;
-  cursor: initial;
-  display: flex;
-  flex-direction: column;
-  gap: var(--sys-size-5);
-  width: 100%;
-  padding: var(--sys-size-7) var(--sys-size-5);
-  height: 100%;
-
-  .header {
-    display: flex;
-    align-items: center;
-    height: var(--sys-size-11);
-    gap: var(--sys-size-4);
-
-    h2 {
-      font: var(--sys-typescale-body4-bold);
-    }
-  }
-
-  .instructions {
-    display: flex;
-    flex-direction: column;
-    gap: var(--sys-size-6);
-    line-height: 18px;
-  }
-}
-
 .indicator {
   color: var(--sys-color-green-bright);
 }
@@ -530,7 +501,7 @@
     }
   }
 
-  .suggestions {
+  .empty-state-content {
     display: flex;
     flex-direction: column;
     gap: var(--sys-size-5);
@@ -540,6 +511,42 @@
   }
 }
 
+.feature-card {
+  display: flex;
+  padding: var(--sys-size-4) var(--sys-size-6);
+  gap: 10px;
+  background-color: var(--sys-color-surface2);
+  border-radius: var(--sys-shape-corner-medium-small);
+  width: var(--sys-size-32);
+  align-items: center;
+
+  .feature-card-icon {
+    width: var(--sys-size-12);
+    height: var(--sys-size-12);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    background-color: var(--sys-color-tonal-container);
+    border-radius: var(--sys-shape-corner-full);
+
+    devtools-icon {
+      width: 18px;
+      height: 18px;
+    }
+  }
+
+  .feature-card-content {
+    h3 {
+      font: var(--sys-typescale-body3-medium);
+    }
+
+    p {
+      font: var(--sys-typescale-body4-regular);
+      line-height: 18px;
+    }
+  }
+}
+
 .disabled-view {
   display: flex;
   max-width: var(--sys-size-34);
diff --git a/front_end/ui/visual_logging/KnownContextValues.ts b/front_end/ui/visual_logging/KnownContextValues.ts
index bca7aa8..6e0bee1 100644
--- a/front_end/ui/visual_logging/KnownContextValues.ts
+++ b/front_end/ui/visual_logging/KnownContextValues.ts
@@ -2171,12 +2171,16 @@
   'only-show-third-party',
   'opacity',
   'open-ai-settings',
+  'open-elements-panel',
   'open-folder',
   'open-in-animations-panel',
   'open-in-containing-folder',
   'open-in-new-tab',
   'open-link-handler',
   'open-memory-inspector',
+  'open-network-panel',
+  'open-performance-panel',
+  'open-sources-panel',
   'open-using',
   'opened-windows',
   'opera-mac',