This is an automated email from the ASF dual-hosted git repository.

mcgilman pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 8cc7f0d5184 NIFI-15920 improve accesibility around connector state 
text in listing (#11225)
8cc7f0d5184 is described below

commit 8cc7f0d5184ebbe047a03f61221857edba8cc5d7
Author: Scott Aslan <[email protected]>
AuthorDate: Wed May 13 17:20:24 2026 -0400

    NIFI-15920 improve accesibility around connector state text in listing 
(#11225)
    
    * NIFI-15920 improve accesibility around connector state text in listing
    
    * add status badge and status variant
    
    * address review feedback
---
 .../connector-table/connector-table.component.html | 13 ++--
 .../connector-table/connector-table.component.ts   | 16 ++++-
 .../libs/shared/src/assets/themes/material.scss    | 48 ++++++++++++++
 .../connector-detail-header.component.html         | 13 ++--
 .../connector-detail-header.component.spec.ts      | 76 ++--------------------
 .../connector-detail-header.component.ts           | 44 ++-----------
 .../frontend/libs/shared/src/components/index.ts   |  1 +
 .../status-badge/status-badge.component.html       | 28 ++++++++
 .../status-badge/status-badge.component.scss       | 42 ++++++++++++
 .../status-badge/status-badge.component.spec.ts    | 38 +++++++++++
 .../status-badge/status-badge.component.ts         | 32 +++++++++
 .../src/utils/connector-permissions.utils.spec.ts  | 47 ++++++++++++-
 .../src/utils/connector-permissions.utils.ts       | 22 ++++++-
 13 files changed, 292 insertions(+), 128 deletions(-)

diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-table/connector-table.component.html
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-table/connector-table.component.html
index b7b9df27448..91d2e95578e 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-table/connector-table.component.html
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-table/connector-table.component.html
@@ -74,11 +74,16 @@
                 <th mat-header-cell *matHeaderCellDef 
mat-sort-header>State</th>
                 <td mat-cell *matCellDef="let item" 
data-qa="connector-state-cell">
                     <div class="inline-flex items-center gap-x-2">
-                        <span [title]="formatState(item)">{{ formatState(item) 
}}</span>
+                        @if (canRead(item)) {
+                            <status-badge
+                                [label]="formatState(item)"
+                                
[variant]="getConnectorStateVariant(item.component.state)"
+                                data-qa="connector-state">
+                            </status-badge>
+                        }
                         @if (canRead(item) && canDiscardConfig(item)) {
-                            <span class="caution-color text-xs font-medium" 
data-qa="edits-not-applied-badge"
-                                >(Edits not applied)</span
-                            >
+                            <status-badge label="Edits not applied" 
variant="caution" data-qa="edits-not-applied-badge">
+                            </status-badge>
                         }
                     </div>
                 </td>
diff --git 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-table/connector-table.component.ts
 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-table/connector-table.component.ts
index e2d52960668..fb04927180a 100644
--- 
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-table/connector-table.component.ts
+++ 
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-table/connector-table.component.ts
@@ -26,11 +26,13 @@ import {
     ConnectorActionName,
     NifiTooltipDirective,
     NiFiCommon,
+    StatusBadge,
     canReadConnector,
     canModifyConnector,
     canOperateConnector,
     isConnectorActionAllowed,
-    getConnectorActionDisabledReason
+    getConnectorActionDisabledReason,
+    getConnectorStateVariant
 } from '@nifi/shared';
 import { ValidationErrorsTipInput } from '../../../../state/shared';
 import { FlowConfiguration } from '../../../../state/flow-configuration';
@@ -41,7 +43,15 @@ import { ValidationErrorsTip } from 
'../../../../ui/common/tooltips/validation-e
     selector: 'connector-table',
     standalone: true,
     templateUrl: './connector-table.component.html',
-    imports: [MatButtonModule, MatTableModule, MatSortModule, MatMenuModule, 
MatTooltipModule, NifiTooltipDirective],
+    imports: [
+        MatButtonModule,
+        MatTableModule,
+        MatSortModule,
+        MatMenuModule,
+        MatTooltipModule,
+        NifiTooltipDirective,
+        StatusBadge
+    ],
     styleUrls: ['./connector-table.component.scss']
 })
 export class ConnectorTable {
@@ -113,6 +123,8 @@ export class ConnectorTable {
         return getConnectorActionDisabledReason(entity, actionName);
     }
 
+    protected readonly getConnectorStateVariant = getConnectorStateVariant;
+
     canConfigure(entity: ConnectorEntity): boolean {
         return isConnectorActionAllowed(entity, 'CONFIGURE');
     }
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/assets/themes/material.scss 
b/nifi-frontend/src/main/frontend/libs/shared/src/assets/themes/material.scss
index be93da637a4..5f6e7b73c7c 100644
--- 
a/nifi-frontend/src/main/frontend/libs/shared/src/assets/themes/material.scss
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/assets/themes/material.scss
@@ -361,6 +361,30 @@
             )
         );
     }
+
+    // NOTE: The following styles are for the status badge and status banner 
components. The `.status-variant` class should only be applied to a div or span 
element that should adhear to the variant color and background.
+    .status-variant {
+        &.neutral {
+            color: var(--mat-sys-on-surface);
+            background-color: var(--mat-sys-surface-dim);
+        }
+        &.critical {
+            color: var(--mat-sys-on-error);
+            background-color: var(--mat-sys-error);
+        }
+        &.caution {
+            color: var(--nf-caution-contrast);
+            background-color: var(--nf-caution-default);
+        }
+        &.success {
+            color: var(--nf-success-contrast);
+            background-color: var(--nf-success-default);
+        }
+        &.info {
+            color: var(--nf-success-contrast);
+            background-color: var(--nf-success-variant);
+        }
+    }
 }
 
 // Note: Color palettes are generated from primary: #6750a4
@@ -854,4 +878,28 @@ html {
             )
         );
     }
+
+    // NOTE: The following styles are for the status badge and status banner 
components. The `.status-variant` class should only be applied to a div or span 
element that should adhear to the variant color and background.
+    .status-variant {
+        &.neutral {
+            color: var(--mat-sys-on-surface);
+            background-color: var(--mat-sys-surface-dim);
+        }
+        &.critical {
+            color: var(--mat-sys-on-error);
+            background-color: var(--mat-sys-error);
+        }
+        &.caution {
+            color: var(--nf-caution-contrast);
+            background-color: var(--nf-caution-default);
+        }
+        &.success {
+            color: var(--nf-success-contrast);
+            background-color: var(--nf-success-default);
+        }
+        &.info {
+            color: var(--nf-success-contrast);
+            background-color: var(--nf-success-variant);
+        }
+    }
 }
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.html
 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.html
index 7ecf984d0a3..4cb8a7fc210 100644
--- 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.html
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.html
@@ -16,16 +16,13 @@
   -->
 
 <ng-template #badges>
-    <span
-        class="connector-state-badge text-xs font-semibold uppercase"
-        [class]="getStateColorClass(connector().component.state)"
+    <status-badge
+        [label]="connector().component.state"
+        [variant]="getStateVariant(connector().component.state)"
         data-qa="connector-state">
-        {{ connector().component.state }}
-    </span>
+    </status-badge>
     @if (hasUnappliedEdits()) {
-        <span class="caution-color text-xs font-semibold uppercase" 
data-qa="edits-not-applied-badge">
-            Edits not applied
-        </span>
+        <status-badge label="Edits not applied" variant="caution" 
data-qa="edits-not-applied-badge"> </status-badge>
     }
 </ng-template>
 
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.spec.ts
 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.spec.ts
index 65321dd24b3..35961829f9c 100644
--- 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.spec.ts
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.spec.ts
@@ -18,6 +18,7 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { ConnectorDetailHeader } from './connector-detail-header.component';
 import { ConnectorEntity, ConnectorState, ConnectorStatus } from '../../types';
+import { getConnectorStateVariant } from 
'../../utils/connector-permissions.utils';
 
 interface SetupOptions {
     connector?: ConnectorEntity;
@@ -108,78 +109,9 @@ describe('ConnectorDetailHeader', () => {
         expect(stateBadge.textContent.trim()).toBe('RUNNING');
     });
 
-    describe('getStateVariant', () => {
-        it('should return success for RUNNING', async () => {
-            const { component } = await setup();
-            
expect(component.getStateVariant(ConnectorState.RUNNING)).toBe('success');
-        });
-
-        it('should return neutral for STOPPED', async () => {
-            const { component } = await setup();
-            
expect(component.getStateVariant(ConnectorState.STOPPED)).toBe('neutral');
-        });
-
-        it('should return neutral for DISABLED', async () => {
-            const { component } = await setup();
-            
expect(component.getStateVariant(ConnectorState.DISABLED)).toBe('neutral');
-        });
-
-        it('should return info for STARTING', async () => {
-            const { component } = await setup();
-            
expect(component.getStateVariant(ConnectorState.STARTING)).toBe('info');
-        });
-
-        it('should return info for UPDATING', async () => {
-            const { component } = await setup();
-            
expect(component.getStateVariant(ConnectorState.UPDATING)).toBe('info');
-        });
-
-        it('should return info for STOPPING', async () => {
-            const { component } = await setup();
-            
expect(component.getStateVariant(ConnectorState.STOPPING)).toBe('info');
-        });
-
-        it('should return info for DRAINING', async () => {
-            const { component } = await setup();
-            
expect(component.getStateVariant(ConnectorState.DRAINING)).toBe('info');
-        });
-
-        it('should return info for PREPARING_FOR_UPDATE', async () => {
-            const { component } = await setup();
-            
expect(component.getStateVariant(ConnectorState.PREPARING_FOR_UPDATE)).toBe('info');
-        });
-
-        it('should return critical for UPDATE_FAILED', async () => {
-            const { component } = await setup();
-            
expect(component.getStateVariant(ConnectorState.UPDATE_FAILED)).toBe('critical');
-        });
-
-        it('should return neutral for unknown state', async () => {
-            const { component } = await setup();
-            expect(component.getStateVariant('UNKNOWN')).toBe('neutral');
-        });
-    });
-
-    describe('getStateColorClass', () => {
-        it('should map success variant to success-color-default', async () => {
-            const { component } = await setup();
-            
expect(component.getStateColorClass(ConnectorState.RUNNING)).toBe('success-color-default');
-        });
-
-        it('should map neutral variant to neutral-color', async () => {
-            const { component } = await setup();
-            
expect(component.getStateColorClass(ConnectorState.STOPPED)).toBe('neutral-color');
-        });
-
-        it('should map info variant to primary-color', async () => {
-            const { component } = await setup();
-            
expect(component.getStateColorClass(ConnectorState.STARTING)).toBe('primary-color');
-        });
-
-        it('should map critical variant to error-color', async () => {
-            const { component } = await setup();
-            
expect(component.getStateColorClass(ConnectorState.UPDATE_FAILED)).toBe('error-color');
-        });
+    it('should delegate getStateVariant to getConnectorStateVariant', async () 
=> {
+        const { component } = await setup();
+        expect(component.getStateVariant).toBe(getConnectorStateVariant);
     });
 
     describe('hasUnappliedEdits', () => {
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.ts
 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.ts
index 6c55abceace..6ef715607be 100644
--- 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.ts
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/connector-detail-header/connector-detail-header.component.ts
@@ -17,14 +17,14 @@
 
 import { Component, computed, input } from '@angular/core';
 import { NgTemplateOutlet } from '@angular/common';
-import { ConnectorEntity, ConnectorState } from '../../types';
-
-export type ConnectorStateVariant = 'neutral' | 'critical' | 'caution' | 
'success' | 'info';
+import { ConnectorEntity } from '../../types';
+import { StatusBadge } from '../status-badge/status-badge.component';
+import { getConnectorStateVariant } from 
'../../utils/connector-permissions.utils';
 
 @Component({
     selector: 'connector-detail-header',
     standalone: true,
-    imports: [NgTemplateOutlet],
+    imports: [NgTemplateOutlet, StatusBadge],
     templateUrl: './connector-detail-header.component.html',
     styleUrls: ['./connector-detail-header.component.scss']
 })
@@ -48,39 +48,5 @@ export class ConnectorDetailHeader {
         return action?.allowed ?? false;
     });
 
-    getStateVariant(state: string): ConnectorStateVariant {
-        switch (state) {
-            case ConnectorState.RUNNING:
-                return 'success';
-            case ConnectorState.STOPPED:
-            case ConnectorState.DISABLED:
-                return 'neutral';
-            case ConnectorState.STARTING:
-            case ConnectorState.UPDATING:
-            case ConnectorState.STOPPING:
-            case ConnectorState.DRAINING:
-            case ConnectorState.PREPARING_FOR_UPDATE:
-                return 'info';
-            case ConnectorState.UPDATE_FAILED:
-                return 'critical';
-            default:
-                return 'neutral';
-        }
-    }
-
-    getStateColorClass(state: string): string {
-        switch (this.getStateVariant(state)) {
-            case 'success':
-                return 'success-color-default';
-            case 'critical':
-                return 'error-color';
-            case 'caution':
-                return 'caution-color';
-            case 'info':
-                return 'primary-color';
-            case 'neutral':
-            default:
-                return 'neutral-color';
-        }
-    }
+    protected readonly getStateVariant = getConnectorStateVariant;
 }
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/index.ts 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/index.ts
index 2ffa339d64a..112731a7a43 100644
--- a/nifi-frontend/src/main/frontend/libs/shared/src/components/index.ts
+++ b/nifi-frontend/src/main/frontend/libs/shared/src/components/index.ts
@@ -46,5 +46,6 @@ export * from 
'./side-panel-container/side-panel-container.component';
 export * from './connector-property-input/connector-property-input.component';
 export * from './connector-detail-header/connector-detail-header.component';
 export * from './searchable-select/searchable-select.component';
+export * from './status-badge/status-badge.component';
 export * from './multi-select-option/multi-select-option.component';
 export * from './asset-upload/asset-upload.component';
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.html
 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.html
new file mode 100644
index 00000000000..2a40397035b
--- /dev/null
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.html
@@ -0,0 +1,28 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+@if (label) {
+    <span
+        class="status-badge status-variant py-0.5 px-1.5 rounded-xs 
items-center inline-flex text-sm font-semibold max-h-fit max-w-fit gap-0.5 
cursor-default"
+        [class]="variant"
+        [matTooltip]="message">
+        {{ label }}
+        @if (message && message.length > 0) {
+            <i class="fa fa-info text-[16px]" [class]="variant"></i>
+        }
+    </span>
+}
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.scss
 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.scss
new file mode 100644
index 00000000000..1cead2c5dbe
--- /dev/null
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.scss
@@ -0,0 +1,42 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@use '@angular/material' as mat;
+
+.status-badge {
+    .fa {
+        &.neutral {
+            color: var(--mat-sys-on-surface);
+        }
+
+        &.critical {
+            color: var(--mat-sys-on-error);
+        }
+
+        &.caution {
+            color: var(--nf-caution-contrast);
+        }
+
+        &.success {
+            color: var(--nf-success-contrast);
+        }
+
+        &.info {
+            color: var(--nf-success-contrast);
+        }
+    }
+}
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.spec.ts
 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.spec.ts
new file mode 100644
index 00000000000..d147d37bc01
--- /dev/null
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.spec.ts
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { StatusBadge } from './status-badge.component';
+
+describe('StatusBadge', () => {
+    let component: StatusBadge;
+    let fixture: ComponentFixture<StatusBadge>;
+
+    beforeEach(async () => {
+        await TestBed.configureTestingModule({
+            imports: [StatusBadge]
+        }).compileComponents();
+
+        fixture = TestBed.createComponent(StatusBadge);
+        component = fixture.componentInstance;
+        fixture.detectChanges();
+    });
+
+    it('should create', () => {
+        expect(component).toBeTruthy();
+    });
+});
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.ts
 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.ts
new file mode 100644
index 00000000000..af1147b4f86
--- /dev/null
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/components/status-badge/status-badge.component.ts
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Component, Input } from '@angular/core';
+import { StatusVariant } from '../../types';
+import { MatTooltip } from '@angular/material/tooltip';
+
+@Component({
+    selector: 'status-badge',
+    imports: [MatTooltip],
+    templateUrl: './status-badge.component.html',
+    styleUrls: ['./status-badge.component.scss']
+})
+export class StatusBadge {
+    @Input() label: string | null = null;
+    @Input() variant: StatusVariant = 'neutral';
+    @Input() message: string | null | undefined = null;
+}
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/utils/connector-permissions.utils.spec.ts
 
b/nifi-frontend/src/main/frontend/libs/shared/src/utils/connector-permissions.utils.spec.ts
index dc8959f7f75..f4e61db6454 100644
--- 
a/nifi-frontend/src/main/frontend/libs/shared/src/utils/connector-permissions.utils.spec.ts
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/utils/connector-permissions.utils.spec.ts
@@ -15,14 +15,15 @@
  * limitations under the License.
  */
 
-import { ConnectorEntity } from '../types';
+import { ConnectorEntity, ConnectorState } from '../types';
 import {
     canReadConnector,
     canModifyConnector,
     canOperateConnector,
     getConnectorAction,
     isConnectorActionAllowed,
-    getConnectorActionDisabledReason
+    getConnectorActionDisabledReason,
+    getConnectorStateVariant
 } from './connector-permissions.utils';
 
 function createMockEntity(overrides: Partial<ConnectorEntity> = {}): 
ConnectorEntity {
@@ -182,4 +183,46 @@ describe('connector-permissions.utils', () => {
             expect(getConnectorActionDisabledReason(entity, 'START')).toBe('');
         });
     });
+
+    describe('getConnectorStateVariant', () => {
+        it('should return success for RUNNING', () => {
+            
expect(getConnectorStateVariant(ConnectorState.RUNNING)).toBe('success');
+        });
+
+        it('should return neutral for STOPPED', () => {
+            
expect(getConnectorStateVariant(ConnectorState.STOPPED)).toBe('neutral');
+        });
+
+        it('should return neutral for DISABLED', () => {
+            
expect(getConnectorStateVariant(ConnectorState.DISABLED)).toBe('neutral');
+        });
+
+        it('should return info for STARTING', () => {
+            
expect(getConnectorStateVariant(ConnectorState.STARTING)).toBe('info');
+        });
+
+        it('should return info for UPDATING', () => {
+            
expect(getConnectorStateVariant(ConnectorState.UPDATING)).toBe('info');
+        });
+
+        it('should return info for STOPPING', () => {
+            
expect(getConnectorStateVariant(ConnectorState.STOPPING)).toBe('info');
+        });
+
+        it('should return info for DRAINING', () => {
+            
expect(getConnectorStateVariant(ConnectorState.DRAINING)).toBe('info');
+        });
+
+        it('should return info for PREPARING_FOR_UPDATE', () => {
+            
expect(getConnectorStateVariant(ConnectorState.PREPARING_FOR_UPDATE)).toBe('info');
+        });
+
+        it('should return critical for UPDATE_FAILED', () => {
+            
expect(getConnectorStateVariant(ConnectorState.UPDATE_FAILED)).toBe('critical');
+        });
+
+        it('should return neutral for unknown state', () => {
+            expect(getConnectorStateVariant('UNKNOWN')).toBe('neutral');
+        });
+    });
 });
diff --git 
a/nifi-frontend/src/main/frontend/libs/shared/src/utils/connector-permissions.utils.ts
 
b/nifi-frontend/src/main/frontend/libs/shared/src/utils/connector-permissions.utils.ts
index bffe16bdc17..d78f5f31478 100644
--- 
a/nifi-frontend/src/main/frontend/libs/shared/src/utils/connector-permissions.utils.ts
+++ 
b/nifi-frontend/src/main/frontend/libs/shared/src/utils/connector-permissions.utils.ts
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import { ConnectorAction, ConnectorActionName, ConnectorEntity } from 
'../types';
+import { ConnectorAction, ConnectorActionName, ConnectorEntity, 
ConnectorState, StatusVariant } from '../types';
 
 export function canReadConnector(entity: ConnectorEntity): boolean {
     return entity.permissions.canRead;
@@ -45,3 +45,23 @@ export function getConnectorActionDisabledReason(entity: 
ConnectorEntity, action
     const action = getConnectorAction(entity, actionName);
     return action?.reasonNotAllowed ?? '';
 }
+
+export function getConnectorStateVariant(state: string): StatusVariant {
+    switch (state) {
+        case ConnectorState.RUNNING:
+            return 'success';
+        case ConnectorState.STOPPED:
+        case ConnectorState.DISABLED:
+            return 'neutral';
+        case ConnectorState.STARTING:
+        case ConnectorState.UPDATING:
+        case ConnectorState.STOPPING:
+        case ConnectorState.DRAINING:
+        case ConnectorState.PREPARING_FOR_UPDATE:
+            return 'info';
+        case ConnectorState.UPDATE_FAILED:
+            return 'critical';
+        default:
+            return 'neutral';
+    }
+}

Reply via email to