Repository: SAP/inquirer-gui
Pull request #707: feat: support show icon for error
Author: login: LucyGit
Created: 2025-03-10T06:21:05Z | Merged: 2025-03-12T07:53:42Z



Diff:
diff --git a/examples/sample-navigator/package.json b/examples/sample-navigator/package.json
index b608c6bc8..32814aa17 100644
--- a/examples/sample-navigator/package.json
+++ b/examples/sample-navigator/package.json
@@ -1,6 +1,6 @@
 {
   "name": "sample-navigator",
-  "version": "3.0.6",
+  "version": "3.0.7",
   "private": true,
   "scripts": {
     "dev": "vite",
diff --git a/examples/sample-navigator/src/App.vue b/examples/sample-navigator/src/App.vue
index 8bdb7d6a0..48b5d1535 100644
--- a/examples/sample-navigator/src/App.vue
+++ b/examples/sample-navigator/src/App.vue
@@ -5,6 +5,7 @@
         <v-radio-group v-model="navigationType" inline style="margin-top: 10px; margin-bottom: 0px">
           <v-radio label="tab" value="tab"></v-radio>
           <v-radio label="stepper" value="stepper"></v-radio>
+          <v-radio label="tab with error icon" value="tabWithErrorIcon"></v-radio>
         </v-radio-group>
         <v-divider />
         <NavigatorControl
@@ -16,6 +17,16 @@
           navigation-type="tab"
           @on-goto-step="gotoTab"
         />
+        <NavigatorControl
+          v-if="navigationType === 'tabWithErrorIcon'"
+          :prompt-index="promptIndex"
+          :prompts="prompts"
+          :all-answers="allAnswers"
+          :prompt-answers="{}"
+          navigation-type="tab"
+          show-icon-for-error="true"
+          @on-goto-step="gotoTab"
+        />
         <NavigatorControl
           v-if="navigationType === 'stepper'"
           :prompt-index="promptIndex"
diff --git a/packages/controls-navigator/README.md b/packages/controls-navigator/README.md
index 9f6508061..4ab91ef65 100644
--- a/packages/controls-navigator/README.md
+++ b/packages/controls-navigator/README.md
@@ -85,6 +85,10 @@ It can display the groups in a way like wizard steps or tabs control
   }
 ```
 
+- showIconForError<br/>
+  If showIconForError equals true, we will use icon to represent the error type and we use the error value as the icon's tooltip. If showIconForError equals false, we display the error value with text in red.
+  The default value is false.
+
 ## Control Event
 
 - on-goto-step<br/>
@@ -104,6 +108,7 @@ If writing a Vue application, simply add the following line to your `<template>`
   :prompt-answers="{}"
   navigation-type="tab"
   @on-goto-step="gotoStep"
+  :showIconForError="true"
 />
 ```
 
diff --git a/packages/controls-navigator/__tests__/navigator.spec.js b/packages/controls-navigator/__tests__/navigator.spec.js
index faa14abf9..469803b10 100644
--- a/packages/controls-navigator/__tests__/navigator.spec.js
+++ b/packages/controls-navigator/__tests__/navigator.spec.js
@@ -141,4 +141,31 @@ describe("Test navigator common control", () => {
     confirm.trigger("click");
     expect(wrapper.emitted().onGotoStep).toBeTruthy();
   });
+  test("Navigator Tabs with show error in icon", async () => {
+    wrapper.setProps({
+      promptIndex: 0,
+      prompts: [{ name: "group1" }, { name: "group2" }],
+      allAnswers: {
+        group1: [
+          { label: "akey1", value: "aType" },
+          { label: "akey2", value: "a", type: "warning" },
+        ],
+        group2: [
+          { label: "bkey1", value: "bType" },
+          { label: "", value: "b" },
+        ],
+      },
+      promptAnswers: {},
+      navigationType: "tab",
+      showIconForError: true,
+    });
+
+    await nextTick();
+
+    let itemWarnings = document.body.querySelectorAll(".NavigatorSummaryWarningValueClass");
+    expect(itemWarnings).toHaveLength(1);
+    expect(itemWarnings[0].textContent).toEqual("");
+    itemWarnings = document.body.querySelectorAll(".mdi-close-circle-outline");
+    expect(itemWarnings).toHaveLength(1);
+  });
 });
diff --git a/packages/controls-navigator/package.json b/packages/controls-navigator/package.json
index 45084c4b2..9b60dfecd 100644
--- a/packages/controls-navigator/package.json
+++ b/packages/controls-navigator/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@sap-devx/controls-navigator",
   "displayName": "Navigator control",
-  "version": "3.0.6",
+  "version": "3.0.7",
   "description": "Navigator control",
   "repository": {
     "type": "git",
diff --git a/packages/controls-navigator/src/BreadcrumbsContainer.vue b/packages/controls-navigator/src/BreadcrumbsContainer.vue
index 0d77ad8bb..1e19ce20d 100644
--- a/packages/controls-navigator/src/BreadcrumbsContainer.vue
+++ b/packages/controls-navigator/src/BreadcrumbsContainer.vue
@@ -8,8 +8,18 @@
       data-test="answerBox"
     >
       <div v-for="(item, index) in breadcrumbs" class="answer" data-test="breadcrumbs" :key="`answer-${index}`">
-        <span class="NavigatorSummaryKeyClass">{{ item.label ? item.label + ":" : "" }} </span
-        ><span :class="getValueClass(item.type)">{{ item.value }}</span>
+        <span class="NavigatorSummaryKeyClass">{{ item.label ? item.label + ":" : "" }} </span>
+
+        <span v-if="showIconForError && isErrorType(item.type)" :class="getValueClass(item.type)">
+          <v-tooltip location="top" max-width="350px">
+            <template v-slot:activator="{ props }">
+              <v-icon v-bind="props">mdi-close-circle-outline</v-icon>
+            </template>
+            <span>{{ item.value }}</span>
+          </v-tooltip>
+        </span>
+
+        <span v-else :class="getValueClass(item.type)">{{ item.value }}</span>
       </div>
     </div>
     <div v-if="showMoreLess" class="more" data-test="moreLessButton" @click="showMore = !showMore">
@@ -32,6 +42,10 @@ const props = defineProps({
     type: Array,
     default: () => [],
   },
+  showIconForError: {
+    type: Boolean,
+    default: false,
+  },
 });
 
 const { breadcrumbs } = toRefs(props);
@@ -64,6 +78,9 @@ const getValueClass = (type) => {
     return "NavigatorSummaryValueClass";
   }
 };
+const isErrorType = (type) => {
+  return type === "warning";
+};
 defineExpose({
   calcIsMore,
   showMoreLess,
diff --git a/packages/controls-navigator/src/NavigatorControl.vue b/packages/controls-navigator/src/NavigatorControl.vue
index 9c7ad1846..a3b294d91 100644
--- a/packages/controls-navigator/src/NavigatorControl.vue
+++ b/packages/controls-navigator/src/NavigatorControl.vue
@@ -14,6 +14,7 @@
             :id="`breadcrumbs-${index}`"
             class="breadcrumbs"
             :breadcrumbs="answers[prompts[index - 1] ? prompts[index - 1].name : undefined]"
+            :showIconForError="showIconForError"
           />
         </div>
       </template>
@@ -46,9 +47,13 @@ const props = defineProps({
     type: String,
     default: "tab",
   },
+  showIconForError: {
+    type: Boolean,
+    default: false,
+  },
 });
 
-const { promptIndex, prompts, allAnswers, promptAnswers, navigationType } = toRefs(props);
+const { promptIndex, prompts, allAnswers, promptAnswers, navigationType, showIconForError } = toRefs(props);
 
 const emits = defineEmits(["onGotoStep"]);
 


Reviews:
user: login: alex-gilin
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T08:46:42Z
user: login: LucyGit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T08:51:05Z
user: login: LucyGit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T08:56:13Z
user: login: LucyGit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T09:02:49Z
user: login: LucyGit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T09:06:34Z
user: login: alex-gilin
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-10T10:21:55Z
user: login: LucyGit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T05:47:56Z
user: login: alex-gilin
body: please document extended functionality in `controls-navigator/README.md`
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T05:55:56Z
user: login: alex-gilin
body: The `master` branch is protected to ensure stability. To contribute your changes, please create a new branch and submit your pull request there.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T06:39:31Z
user: login: LucyGit
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T08:06:28Z
user: login: alex-gilin
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T05:01:21Z

Review comments:
diff_hunk: @@ -64,6 +78,9 @@ const getValueClass = (type) => {
     return "NavigatorSummaryValueClass";
   }
 };
+const isErrorType = (type) => {
+  return type === "warning";
path: packages/controls-navigator/src/BreadcrumbsContainer.vue
user: login: alex-gilin
body: Do you plan to support multiple notification levels (error | warning | info)? If not, consider changing the type value to `error` to match the property name. 
created_at: 2025-03-10T08:26:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -64,6 +78,9 @@ const getValueClass = (type) => {
     return "NavigatorSummaryValueClass";
path: packages/controls-navigator/src/BreadcrumbsContainer.vue
user: login: alex-gilin
body: IMHO, there is already a special tab like `warning`. Isn't that enough to understand whether to show/hide the additional icon? 
created_at: 2025-03-10T08:41:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -64,6 +78,9 @@ const getValueClass = (type) => {
     return "NavigatorSummaryValueClass";
   }
 };
+const isErrorType = (type) => {
+  return type === "warning";
path: packages/controls-navigator/src/BreadcrumbsContainer.vue
user: login: LucyGit
body: Currently only support error/info. Here warning is error , they are the same.
created_at: 2025-03-10T08:51:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -64,6 +78,9 @@ const getValueClass = (type) => {
     return "NavigatorSummaryValueClass";
path: packages/controls-navigator/src/BreadcrumbsContainer.vue
user: login: LucyGit
body: The showIconForError property is to specify whether we show icon for the error.
created_at: 2025-03-10T08:56:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -64,6 +78,9 @@ const getValueClass = (type) => {
     return "NavigatorSummaryValueClass";
   }
 };
+const isErrorType = (type) => {
+  return type === "warning";
path: packages/controls-navigator/src/BreadcrumbsContainer.vue
user: login: LucyGit
body: Since our client users already used "warning" for the type , so we use warning for error to be compatible with the existent clients.
created_at: 2025-03-10T09:02:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -64,6 +78,9 @@ const getValueClass = (type) => {
     return "NavigatorSummaryValueClass";
path: packages/controls-navigator/src/BreadcrumbsContainer.vue
user: login: LucyGit
body: If showIconForError equals true, we will use icon to represent the error type and we use the error value as the icon's tooltip. If showIconForError equals false, we display the error value with text in red (our previous design)
created_at: 2025-03-10T09:06:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -141,4 +141,29 @@ describe("Test navigator common control", () => {
     confirm.trigger("click");
     expect(wrapper.emitted().onGotoStep).toBeTruthy();
   });
+  test("Navigator Tabs with show error in icon", async () => {
+    wrapper.setProps({
+      promptIndex: 0,
+      prompts: [{ name: "group1" }, { name: "group2" }],
+      allAnswers: {
+        group1: [
+          { label: "akey1", value: "aType" },
+          { label: "akey2", value: "a", type: "warning" },
+        ],
+        group2: [
+          { label: "bkey1", value: "bType" },
+          { label: "", value: "b" },
+        ],
+      },
+      promptAnswers: {},
+      navigationType: "tab",
+      showIconForError: true,
+    });
+
+    await nextTick();
+
+    let itemWarnings = document.body.querySelectorAll(".NavigatorSummaryWarningValueClass");
+    expect(itemWarnings).toHaveLength(1);
+    expect(itemWarnings[0].textContent).toEqual("");
path: packages/controls-navigator/__tests__/navigator.spec.js
user: login: alex-gilin
body: Did the test verify that the icon is displayed?
created_at: 2025-03-10T10:21:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -141,4 +141,29 @@ describe("Test navigator common control", () => {
     confirm.trigger("click");
     expect(wrapper.emitted().onGotoStep).toBeTruthy();
   });
+  test("Navigator Tabs with show error in icon", async () => {
+    wrapper.setProps({
+      promptIndex: 0,
+      prompts: [{ name: "group1" }, { name: "group2" }],
+      allAnswers: {
+        group1: [
+          { label: "akey1", value: "aType" },
+          { label: "akey2", value: "a", type: "warning" },
+        ],
+        group2: [
+          { label: "bkey1", value: "bType" },
+          { label: "", value: "b" },
+        ],
+      },
+      promptAnswers: {},
+      navigationType: "tab",
+      showIconForError: true,
+    });
+
+    await nextTick();
+
+    let itemWarnings = document.body.querySelectorAll(".NavigatorSummaryWarningValueClass");
+    expect(itemWarnings).toHaveLength(1);
+    expect(itemWarnings[0].textContent).toEqual("");
path: packages/controls-navigator/__tests__/navigator.spec.js
user: login: LucyGit
body: Thanks Alex, I have added codes to test the error icon
created_at: 2025-03-11T05:47:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -85,6 +85,10 @@ It can display the groups in a way like wizard steps or tabs control
   }
 ```
 
+- showIconForError<br/>
+  If showIconForError equals true, we will use icon to represent the error type and we use the error value as the icon's tooltip. If showIconForError equals false, we display the error value with text in red.
+  The default value is false.
+
path: packages/controls-navigator/README.md
user: login: alex-gilin
body: consider to update the `Usage` section below with the correct example of how to turn on the show error icon 
created_at: 2025-03-11T06:22:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -85,6 +85,10 @@ It can display the groups in a way like wizard steps or tabs control
   }
 ```
 
+- showIconForError<br/>
+  If showIconForError equals true, we will use icon to represent the error type and we use the error value as the icon's tooltip. If showIconForError equals false, we display the error value with text in red.
+  The default value is false.
+
path: packages/controls-navigator/README.md
user: login: LucyGit
body: Added the Usage of showing error icon
created_at: 2025-03-11T08:06:28Z
author_association: CONTRIBUTOR

PR comments:
user: login: veredcon
created_at: 2025-03-10T06:37:50Z
body: Hi @LucyGit looks good. Can you add maybe this new property addition to the `sample-navigator` example project?
author_association: MEMBER
user: login: LucyGit
created_at: 2025-03-10T07:20:37Z
body: > Hi @LucyGit looks good. Can you add maybe this new property addition to the `sample-navigator` example project?

Thanks Vered. I have added the sample for it.
author_association: CONTRIBUTOR
user: login: LucyGit
created_at: 2025-03-11T06:11:33Z
body: > please document extended functionality in `controls-navigator/README.md`

I have added document in readme
author_association: CONTRIBUTOR
user: login: alex-gilin
created_at: 2025-03-11T17:42:21Z
body: > The `master` branch is protected to ensure stability. To contribute your changes, please create a new branch and submit your pull request there.

Edit the target branch of the PR (it can't be `inquirer-gui/master`) or rename the branch of your forked repository and open another PR.
author_association: CONTRIBUTOR
user: login: LucyGit
created_at: 2025-03-12T02:15:14Z
body: > > The `master` branch is protected to ensure stability. To contribute your changes, please create a new branch and submit your pull request there.
> 
> Edit the target branch of the PR (it can't be `inquirer-gui/master`) or rename the branch of your forked repository and open another PR.

Hi Alexander, I don't have right to create a branch in SAP/inquirer-gui .

author_association: CONTRIBUTOR