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

bteke pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/hadoop.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 780971a446a YARN-11929. Use useShallow in Zustand to minimize 
re-renders, remove dead code, split QueueCardNode, and update the handlers in 
PropertyPanel. (#8270)
780971a446a is described below

commit 780971a446ad840fe4ee4eb956ee9571a2a04514
Author: Benjamin Teke <[email protected]>
AuthorDate: Mon Feb 23 17:43:03 2026 +0100

    YARN-11929. Use useShallow in Zustand to minimize re-renders, remove dead 
code, split QueueCardNode, and update the handlers in PropertyPanel. (#8270)
---
 .../src/components/search/NodeLabelSelector.tsx    |  12 +-
 .../src/components/search/SearchBar.test.tsx       |  27 +--
 .../webapp/src/components/search/SearchBar.tsx     |  28 +--
 .../components/GlobalSettings.test.tsx             |  69 ++++++--
 .../global-settings/components/GlobalSettings.tsx  |  59 +++++--
 .../components/LegacyModeToggle.tsx                |  11 +-
 .../features/node-labels/components/NodeLabels.tsx |  13 +-
 .../components/NodeLabelsPanel.test.tsx            |  87 +++++----
 .../node-labels/components/NodeLabelsPanel.tsx     |  45 +++--
 .../node-labels/components/NodesPanel.test.tsx     |  90 ++++------
 .../features/node-labels/components/NodesPanel.tsx |  24 ++-
 .../components/MigrationDialog.test.tsx            |  14 +-
 .../placement-rules/components/MigrationDialog.tsx |  11 +-
 .../components/PlacementRuleDetail.tsx             |  12 +-
 .../components/PlacementRulesList.test.tsx         |  53 ++----
 .../components/PlacementRulesList.tsx              |  27 ++-
 .../property-editor/components/PropertyPanel.tsx   | 108 +++++++++---
 .../components/QueueCardNode.label-filter.test.tsx |  70 +++-----
 .../queue-management/components/QueueCardNode.tsx  | 196 ++++++---------------
 .../components/QueueVisualizationContainer.tsx     |  18 +-
 .../queue-management/hooks/useQueueCardHandlers.ts | 151 ++++++++++++++++
 .../queue-management/utils/queueCardStyles.ts      |  88 +++++++++
 .../components/StagedChangesPanel.tsx              |  16 +-
 .../src/main/webapp/src/lib/api/mocks/handlers.ts  |   6 -
 .../webapp/src/lib/api/mocks/server-handlers.ts    |   5 -
 .../main/webapp/src/stores/schedulerStore.test.ts  |  41 ++++-
 .../src/main/webapp/src/stores/schedulerStore.ts   |   3 +-
 .../stores/slices/__tests__/queueDataSlice.test.ts |  40 ++++-
 .../webapp/src/stores/slices/queueDataSlice.ts     |  38 +---
 .../webapp/src/stores/slices/stagedChangesSlice.ts |   2 -
 .../src/main/webapp/src/stores/slices/types.ts     |   2 -
 31 files changed, 878 insertions(+), 488 deletions(-)

diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/NodeLabelSelector.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/NodeLabelSelector.tsx
index c016395450c..52772bc2028 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/NodeLabelSelector.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/NodeLabelSelector.tsx
@@ -19,6 +19,7 @@
 
 import React from 'react';
 import { Tag } from 'lucide-react';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import {
   Select,
@@ -30,7 +31,16 @@ import {
 import { Badge } from '~/components/ui/badge';
 
 export const NodeLabelSelector: React.FC = () => {
-  const { nodeLabels, selectedNodeLabelFilter, selectNodeLabelFilter } = 
useSchedulerStore();
+  // State values (trigger re-renders only when these specific values change)
+  const { nodeLabels, selectedNodeLabelFilter } = useSchedulerStore(
+    useShallow((s) => ({
+      nodeLabels: s.nodeLabels,
+      selectedNodeLabelFilter: s.selectedNodeLabelFilter,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const selectNodeLabelFilter = useSchedulerStore((s) => 
s.selectNodeLabelFilter);
 
   const handleChange = (value: string) => {
     selectNodeLabelFilter(value === 'DEFAULT' ? '' : value);
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/SearchBar.test.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/SearchBar.test.tsx
index f32523c502c..ee3bae54c20 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/SearchBar.test.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/SearchBar.test.tsx
@@ -48,9 +48,16 @@ describe('SearchBar', () => {
     getFilteredSettings: mockGetFilteredSettings,
   };
 
+  function mockStore(overrides: Record<string, any> = {}) {
+    const state = { ...defaultStoreState, ...overrides };
+    vi.mocked(useSchedulerStore).mockImplementation((selector?: any) => {
+      return selector ? selector(state) : state;
+    });
+  }
+
   beforeEach(() => {
     vi.clearAllMocks();
-    vi.mocked(useSchedulerStore).mockReturnValue(defaultStoreState);
+    mockStore();
     vi.mocked(useDebounce).mockImplementation((value) => value);
     mockGetFilteredQueues.mockReturnValue(null);
     mockGetFilteredNodes.mockReturnValue([]);
@@ -78,8 +85,7 @@ describe('SearchBar', () => {
       vi.clearAllMocks();
 
       // Test nodes context
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         searchContext: 'nodes',
         getFilteredQueues: mockGetFilteredQueues,
         getFilteredNodes: mockGetFilteredNodes,
@@ -90,8 +96,7 @@ describe('SearchBar', () => {
       unmount1();
 
       // Test settings context
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         searchContext: 'settings',
         getFilteredQueues: mockGetFilteredQueues,
         getFilteredNodes: mockGetFilteredNodes,
@@ -109,8 +114,7 @@ describe('SearchBar', () => {
     it('should display clear button and match count when search has value', () 
=> {
       // Mock the store to have an active search with results
       // Use settings context to match the filtered settings we're providing
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         searchQuery: 'test',
         searchContext: 'settings',
         getFilteredQueues: () => null,
@@ -130,8 +134,7 @@ describe('SearchBar', () => {
     it('should display singular match for count of 1', () => {
       // Mock the store to have an active search with 1 result
       // Use settings context to match the filtered settings we're providing
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         searchQuery: 'test',
         searchContext: 'settings',
         getFilteredQueues: () => null,
@@ -225,8 +228,7 @@ describe('SearchBar', () => {
 
     it('should clear search on Escape when focused', async () => {
       const user = userEvent.setup();
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         isSearchFocused: true,
         getFilteredQueues: mockGetFilteredQueues,
         getFilteredNodes: mockGetFilteredNodes,
@@ -258,8 +260,7 @@ describe('SearchBar', () => {
     });
 
     it('should display keyboard shortcuts hint when focused', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         isSearchFocused: true,
         getFilteredQueues: mockGetFilteredQueues,
         getFilteredNodes: mockGetFilteredNodes,
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/SearchBar.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/SearchBar.tsx
index a019639026d..1a3a09ce7c4 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/SearchBar.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/search/SearchBar.tsx
@@ -27,6 +27,7 @@ import { Input } from '~/components/ui/input';
 import { Button } from '~/components/ui/button';
 import { Badge } from '~/components/ui/badge';
 import { cn } from '~/utils/cn';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import { useDebounce } from '~/hooks/useDebounce';
 import { calculateSearchResults } from '~/utils/searchUtils';
@@ -37,17 +38,22 @@ interface SearchBarProps {
 }
 
 export const SearchBar: React.FC<SearchBarProps> = ({ placeholder = 
'Search...', className }) => {
-  const {
-    searchQuery,
-    searchContext,
-    isSearchFocused,
-    setSearchQuery,
-    clearSearch,
-    setSearchFocused,
-    getFilteredQueues,
-    getFilteredNodes,
-    getFilteredSettings,
-  } = useSchedulerStore();
+  // State values (trigger re-renders only when these specific values change)
+  const { searchQuery, searchContext, isSearchFocused } = useSchedulerStore(
+    useShallow((s) => ({
+      searchQuery: s.searchQuery,
+      searchContext: s.searchContext,
+      isSearchFocused: s.isSearchFocused,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const setSearchQuery = useSchedulerStore((s) => s.setSearchQuery);
+  const clearSearch = useSchedulerStore((s) => s.clearSearch);
+  const setSearchFocused = useSchedulerStore((s) => s.setSearchFocused);
+  const getFilteredQueues = useSchedulerStore((s) => s.getFilteredQueues);
+  const getFilteredNodes = useSchedulerStore((s) => s.getFilteredNodes);
+  const getFilteredSettings = useSchedulerStore((s) => s.getFilteredSettings);
 
   const inputRef = useRef<HTMLInputElement>(null);
   const [localQuery, setLocalQuery] = useState(searchQuery);
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/GlobalSettings.test.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/GlobalSettings.test.tsx
index 90e15859e5e..f7e5d2fe609 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/GlobalSettings.test.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/GlobalSettings.test.tsx
@@ -17,7 +17,7 @@
  */
 
 
-import { render, screen, fireEvent } from '@testing-library/react';
+import { render, screen, fireEvent, within } from '@testing-library/react';
 import { describe, it, expect, beforeEach, vi, type Mock } from 'vitest';
 import type { ReactNode } from 'react';
 import { GlobalSettings } from './GlobalSettings';
@@ -162,8 +162,8 @@ describe('GlobalSettings', () => {
 
       renderWithValidation(<GlobalSettings />);
 
-      expect(screen.getByText('Core Settings')).toBeInTheDocument();
-      expect(screen.getByText('Security & Access 
Control')).toBeInTheDocument();
+      expect(screen.getAllByText('Core 
Settings').length).toBeGreaterThanOrEqual(1);
+      expect(screen.getAllByText('Security & Access 
Control').length).toBeGreaterThanOrEqual(1);
     });
 
     it('should render all properties within their categories', () => {
@@ -284,11 +284,13 @@ describe('GlobalSettings', () => {
       renderWithValidation(<GlobalSettings />, { stagedChanges });
 
       // Find the general category heading and its badge
-      const generalHeading = screen.getByText('Core Settings').closest('div');
+      const generalHeading = screen.getByRole('heading', { name: 'Core 
Settings' }).closest('div');
       expect(generalHeading).toHaveTextContent('Has Changes');
 
       // Security category should not have the badge
-      const securityHeading = screen.getByText('Security & Access 
Control').closest('div');
+      const securityHeading = screen
+        .getByRole('heading', { name: 'Security & Access Control' })
+        .closest('div');
       expect(securityHeading).not.toHaveTextContent('Has Changes');
     });
 
@@ -300,7 +302,7 @@ describe('GlobalSettings', () => {
       (globalPropertyDefinitions as PropertyDescriptor[]).push(...properties);
       renderWithValidation(<GlobalSettings />);
 
-      const generalHeading = screen.getByText('Core Settings').closest('div');
+      const generalHeading = screen.getByRole('heading', { name: 'Core 
Settings' }).closest('div');
       expect(generalHeading).not.toHaveTextContent('Has Changes');
     });
   });
@@ -421,6 +423,53 @@ describe('GlobalSettings', () => {
     });
   });
 
+  describe('quick-jump navigation', () => {
+    it('should render quick-jump links when multiple categories exist', () => {
+      const properties = [
+        getMockPropertyDescriptor({ name: 'prop1', category: 'core' }),
+        getMockPropertyDescriptor({ name: 'prop2', category: 'security' }),
+      ];
+      (globalPropertyDefinitions as PropertyDescriptor[]).push(...properties);
+
+      renderWithValidation(<GlobalSettings />);
+
+      const nav = screen.getByRole('navigation', { name: /settings sections/i 
});
+      expect(nav).toBeInTheDocument();
+
+      const links = within(nav).getAllByRole('link');
+      expect(links).toHaveLength(2);
+      expect(links[0]).toHaveTextContent('Core Settings');
+      expect(links[1]).toHaveTextContent('Security & Access Control');
+    });
+
+    it('should not render quick-jump nav when only one category exists', () => 
{
+      const properties = [
+        getMockPropertyDescriptor({ name: 'prop1', category: 'core' }),
+        getMockPropertyDescriptor({ name: 'prop2', category: 'core' }),
+      ];
+      (globalPropertyDefinitions as PropertyDescriptor[]).push(...properties);
+
+      renderWithValidation(<GlobalSettings />);
+
+      expect(
+        screen.queryByRole('navigation', { name: /settings sections/i }),
+      ).not.toBeInTheDocument();
+    });
+
+    it('should add id attributes to accordion sections', () => {
+      const properties = [
+        getMockPropertyDescriptor({ name: 'prop1', category: 'core' }),
+        getMockPropertyDescriptor({ name: 'prop2', category: 'security' }),
+      ];
+      (globalPropertyDefinitions as PropertyDescriptor[]).push(...properties);
+
+      renderWithValidation(<GlobalSettings />);
+
+      expect(document.getElementById('section-core')).toBeInTheDocument();
+      expect(document.getElementById('section-security')).toBeInTheDocument();
+    });
+  });
+
   describe('accordion behavior', () => {
     it('should render all category accordions', () => {
       const properties = [
@@ -432,10 +481,10 @@ describe('GlobalSettings', () => {
 
       renderWithValidation(<GlobalSettings />);
 
-      // Verify all category accordions are rendered
-      expect(screen.getByText('Core Settings')).toBeInTheDocument();
-      expect(screen.getByText('Security & Access 
Control')).toBeInTheDocument();
-      expect(screen.getByText('Scheduling Policy')).toBeInTheDocument();
+      // Verify all category accordions are rendered (labels also appear in 
quick-jump nav)
+      expect(screen.getAllByText('Core 
Settings').length).toBeGreaterThanOrEqual(1);
+      expect(screen.getAllByText('Security & Access 
Control').length).toBeGreaterThanOrEqual(1);
+      expect(screen.getAllByText('Scheduling 
Policy').length).toBeGreaterThanOrEqual(1);
 
       // Verify correct number of accordion items
       const accordionItems = screen.getAllByTestId('accordion-item');
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/GlobalSettings.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/GlobalSettings.tsx
index 89dc956c268..d7503d280ba 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/GlobalSettings.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/GlobalSettings.tsx
@@ -18,6 +18,7 @@
 
 
 import React from 'react';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import { globalPropertyDefinitions } from 
'~/config/properties/global-properties';
 import { SPECIAL_VALUES, type PropertyCategory } from '~/types';
@@ -41,17 +42,22 @@ import {
 } from '~/features/property-editor/constants/categoryConfig';
 
 export const GlobalSettings: React.FC = () => {
-  const {
-    getGlobalPropertyValue,
-    getQueuePropertyValue,
-    stageGlobalChange,
-    stagedChanges,
-    searchQuery,
-    getFilteredSettings,
-    applyError,
-    configData,
-    schedulerData,
-  } = useSchedulerStore();
+  // State values (trigger re-renders only when these specific values change)
+  const { stagedChanges, searchQuery, applyError, configData, schedulerData } 
= useSchedulerStore(
+    useShallow((s) => ({
+      stagedChanges: s.stagedChanges,
+      searchQuery: s.searchQuery,
+      applyError: s.applyError,
+      configData: s.configData,
+      schedulerData: s.schedulerData,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const getGlobalPropertyValue = useSchedulerStore((s) => 
s.getGlobalPropertyValue);
+  const getQueuePropertyValue = useSchedulerStore((s) => 
s.getQueuePropertyValue);
+  const stageGlobalChange = useSchedulerStore((s) => s.stageGlobalChange);
+  const getFilteredSettings = useSchedulerStore((s) => s.getFilteredSettings);
   const { validateGlobalProperty } = useGlobalPropertyValidation();
 
   // Use filtered settings if search is active
@@ -188,6 +194,30 @@ export const GlobalSettings: React.FC = () => {
         </Alert>
       )}
 
+      {categories.length > 1 && (
+        <nav className="flex flex-wrap gap-2" aria-label="Settings sections">
+          {categories.map((category) => {
+            const label = categoryConfig[category]?.label || `${category} 
Settings`;
+            return (
+              <a
+                key={category}
+                href={`#section-${category}`}
+                onClick={(e) => {
+                  e.preventDefault();
+                  document
+                    .getElementById(`section-${category}`)
+                    ?.scrollIntoView({ behavior: 'smooth' });
+                }}
+                className="inline-flex items-center gap-1.5 rounded-md border 
px-3 py-1.5 text-xs font-medium text-muted-foreground transition-colors 
hover:bg-accent hover:text-foreground"
+              >
+                {categoryConfig[category]?.icon}
+                {label}
+              </a>
+            );
+          })}
+        </nav>
+      )}
+
       {categories.length > 0 ? (
         <Accordion type="multiple" defaultValue={categories} 
className="space-y-4">
           {categories.map((category) => {
@@ -197,7 +227,12 @@ export const GlobalSettings: React.FC = () => {
             );
 
             return (
-              <AccordionItem key={category} value={category} className="border 
rounded-lg">
+              <AccordionItem
+                key={category}
+                value={category}
+                className="border rounded-lg"
+                id={`section-${category}`}
+              >
                 <AccordionTrigger className="px-6 hover:no-underline">
                   <div className="flex items-center gap-2">
                     {categoryConfig[category]?.icon}
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/LegacyModeToggle.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/LegacyModeToggle.tsx
index 7fa73ff151f..e9d457ecc93 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/LegacyModeToggle.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/global-settings/components/LegacyModeToggle.tsx
@@ -31,6 +31,7 @@ import {
   DialogTrigger,
 } from '~/components/ui/dialog';
 import { AlertCircle, AlertTriangle, ChevronDown, ChevronUp, Info } from 
'lucide-react';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import { validateQueue } from '~/features/validation/service';
 import type { ValidationIssue } from '~/types';
@@ -67,7 +68,15 @@ export const LegacyModeToggle: 
React.FC<LegacyModeToggleProps> = ({
   searchQuery,
 }) => {
   const [showPreview, setShowPreview] = useState(false);
-  const { schedulerData, configData, stagedChanges } = useSchedulerStore();
+
+  // State values (trigger re-renders only when these specific values change)
+  const { schedulerData, configData, stagedChanges } = useSchedulerStore(
+    useShallow((s) => ({
+      schedulerData: s.schedulerData,
+      configData: s.configData,
+      stagedChanges: s.stagedChanges,
+    })),
+  );
 
   const currentEnabled = value === 'true';
 
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabels.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabels.tsx
index 7e391d8dbb1..465c70ec7b8 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabels.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabels.tsx
@@ -19,6 +19,7 @@
 
 import React from 'react';
 import { AlertCircle } from 'lucide-react';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import { Alert, AlertDescription, AlertTitle } from '~/components/ui/alert';
 import { Card, CardContent, CardHeader, CardTitle } from 
'~/components/ui/card';
@@ -27,8 +28,18 @@ import { NodeLabelsPanel } from './NodeLabelsPanel';
 import { NodesPanel } from './NodesPanel';
 
 export const NodeLabels: React.FC = () => {
+  // State values (trigger re-renders only when these specific values change)
   const { isLoading, error, errorContext, applyError, nodeLabels, 
selectedNodeLabel } =
-    useSchedulerStore();
+    useSchedulerStore(
+      useShallow((s) => ({
+        isLoading: s.isLoading,
+        error: s.error,
+        errorContext: s.errorContext,
+        applyError: s.applyError,
+        nodeLabels: s.nodeLabels,
+        selectedNodeLabel: s.selectedNodeLabel,
+      })),
+    );
 
   if (isLoading && nodeLabels.length === 0) {
     return (
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabelsPanel.test.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabelsPanel.test.tsx
index f29d8551f88..f3fe94ae5a0 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabelsPanel.test.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabelsPanel.test.tsx
@@ -58,11 +58,18 @@ describe('NodeLabelsPanel', () => {
     nodeToLabels: [],
   };
 
+  function mockStore(overrides: Record<string, any> = {}) {
+    const state = { ...defaultStoreState, ...overrides };
+    vi.mocked(useSchedulerStore).mockImplementation((selector?: any) => {
+      return selector ? selector(state) : state;
+    });
+    vi.mocked(useSchedulerStore).getState = mockGetState;
+  }
+
   beforeEach(() => {
     vi.clearAllMocks();
     mockConsoleError.mockClear();
-    vi.mocked(useSchedulerStore).mockReturnValue(defaultStoreState);
-    vi.mocked(useSchedulerStore).getState = mockGetState;
+    mockStore();
     mockGetState.mockReturnValue({ nodeToLabels: [] });
     vi.mocked(validateLabelRemoval).mockReturnValue({ valid: true });
   });
@@ -76,7 +83,30 @@ describe('NodeLabelsPanel', () => {
       render(<NodeLabelsPanel />);
 
       expect(screen.getByText('No node labels found')).toBeInTheDocument();
-      expect(screen.getByText('Click "Add" to create the first 
label')).toBeInTheDocument();
+      expect(
+        screen.getByText(
+          'Node labels let you partition cluster nodes for dedicated resource 
allocation.',
+        ),
+      ).toBeInTheDocument();
+    });
+
+    it('should show CTA button in empty state', () => {
+      render(<NodeLabelsPanel />);
+
+      const ctaButton = screen.getByRole('button', { name: /create first 
label/i });
+      expect(ctaButton).toBeInTheDocument();
+      expect(ctaButton).not.toBeDisabled();
+    });
+
+    it('should open add dialog when CTA button is clicked', async () => {
+      render(<NodeLabelsPanel />);
+
+      const ctaButton = screen.getByRole('button', { name: /create first 
label/i });
+      await userEvent.click(ctaButton as HTMLElement);
+
+      await waitFor(() => {
+        expect(screen.getByRole('dialog')).toBeInTheDocument();
+      });
     });
 
     it('should show correct label count for empty state', () => {
@@ -94,8 +124,7 @@ describe('NodeLabelsPanel', () => {
     ];
 
     it('should display all node labels', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
@@ -107,8 +136,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should show correct label count', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
@@ -118,8 +146,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should display exclusive badge for exclusive labels', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
@@ -130,8 +157,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should show shield icon for exclusive labels', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
@@ -146,8 +172,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should handle singular vs plural label text', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: [getMockNodeLabel()],
       });
 
@@ -164,8 +189,7 @@ describe('NodeLabelsPanel', () => {
     ];
 
     it('should call selectNodeLabel when clicking on a label', async () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
@@ -178,8 +202,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should deselect label when clicking on selected label', async () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
         selectedNodeLabel: 'gpu',
       });
@@ -193,8 +216,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should highlight selected label', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
         selectedNodeLabel: 'highmem',
       });
@@ -219,8 +241,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should disable add button when loading', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         isLoading: true,
       });
 
@@ -247,8 +268,7 @@ describe('NodeLabelsPanel', () => {
         getMockNodeLabel({ name: 'highmem' }),
       ];
 
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
@@ -343,8 +363,7 @@ describe('NodeLabelsPanel', () => {
     ];
 
     beforeEach(() => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
     });
@@ -355,8 +374,7 @@ describe('NodeLabelsPanel', () => {
         getMockNodeLabel({ name: 'gpu', exclusivity: true }),
       ];
 
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabelsWithDefault,
       });
 
@@ -430,8 +448,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should disable delete button when loading', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
         isLoading: true,
       });
@@ -472,8 +489,7 @@ describe('NodeLabelsPanel', () => {
     ];
 
     it('should show hover effect on labels', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
@@ -488,8 +504,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should show cursor pointer on labels', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
@@ -510,8 +525,7 @@ describe('NodeLabelsPanel', () => {
     ];
 
     it('should have accessible list structure', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
@@ -525,8 +539,7 @@ describe('NodeLabelsPanel', () => {
     });
 
     it('should have accessible tooltips for delete buttons', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodeLabels: mockLabels,
       });
 
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabelsPanel.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabelsPanel.tsx
index dcd63a859e8..f4245e89672 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabelsPanel.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodeLabelsPanel.tsx
@@ -18,7 +18,8 @@
 
 
 import React, { useState } from 'react';
-import { Tag, Plus, Trash2, Shield } from 'lucide-react';
+import { Tag, Plus, Trash2, Shield, Tags } from 'lucide-react';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import { Button } from '~/components/ui/button';
 import { Badge } from '~/components/ui/badge';
@@ -26,14 +27,19 @@ import { Tooltip, TooltipContent, TooltipProvider, 
TooltipTrigger } from '~/comp
 import { AddLabelDialog } from '~/features/node-labels';
 
 export const NodeLabelsPanel: React.FC = () => {
-  const {
-    nodeLabels,
-    selectedNodeLabel,
-    selectNodeLabel,
-    addNodeLabel,
-    removeNodeLabel,
-    isLoading,
-  } = useSchedulerStore();
+  // State values (trigger re-renders only when these specific values change)
+  const { nodeLabels, selectedNodeLabel, isLoading } = useSchedulerStore(
+    useShallow((s) => ({
+      nodeLabels: s.nodeLabels,
+      selectedNodeLabel: s.selectedNodeLabel,
+      isLoading: s.isLoading,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const selectNodeLabel = useSchedulerStore((s) => s.selectNodeLabel);
+  const addNodeLabel = useSchedulerStore((s) => s.addNodeLabel);
+  const removeNodeLabel = useSchedulerStore((s) => s.removeNodeLabel);
 
   const [addDialogOpen, setAddDialogOpen] = useState(false);
 
@@ -142,11 +148,24 @@ export const NodeLabelsPanel: React.FC = () => {
 
           {nodeLabels.length === 0 && (
             <li>
-              <div className="py-8 text-center">
-                <p className="text-sm text-muted-foreground">No node labels 
found</p>
-                <p className="text-xs text-muted-foreground">
-                  Click "Add" to create the first label
+              <div className="flex flex-col items-center py-10 text-center">
+                <div className="mb-3 rounded-full bg-muted p-3">
+                  <Tags className="h-6 w-6 text-muted-foreground" />
+                </div>
+                <p className="mb-1 text-sm font-medium">No node labels 
found</p>
+                <p className="mb-4 max-w-[220px] text-xs 
text-muted-foreground">
+                  Node labels let you partition cluster nodes for dedicated 
resource allocation.
                 </p>
+                <Button
+                  variant="default"
+                  size="sm"
+                  onClick={() => setAddDialogOpen(true)}
+                  disabled={isLoading}
+                  className="gap-2"
+                >
+                  <Plus className="h-4 w-4" />
+                  Create First Label
+                </Button>
               </div>
             </li>
           )}
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodesPanel.test.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodesPanel.test.tsx
index 495d356b8f8..a85be382d98 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodesPanel.test.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodesPanel.test.tsx
@@ -96,10 +96,17 @@ describe('NodesPanel', () => {
     getFilteredNodes: vi.fn(() => []),
   };
 
+  function mockStore(overrides: Record<string, any> = {}) {
+    const state = { ...defaultStoreState, ...overrides };
+    vi.mocked(useSchedulerStore).mockImplementation((selector?: any) => {
+      return selector ? selector(state) : state;
+    });
+  }
+
   beforeEach(() => {
     vi.clearAllMocks();
     mockConsoleError.mockClear();
-    (useSchedulerStore as any).mockReturnValue(defaultStoreState);
+    mockStore();
     (formatMemory as any).mockImplementation((mb: number) => `${mb} MB`);
   });
 
@@ -135,8 +142,7 @@ describe('NodesPanel', () => {
     ];
 
     it('should display all nodes when no label is selected', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: mockNodes,
       });
 
@@ -148,8 +154,7 @@ describe('NodesPanel', () => {
     });
 
     it('should show correct header text for all nodes', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: mockNodes,
       });
 
@@ -174,8 +179,7 @@ describe('NodesPanel', () => {
     ];
 
     it('should filter nodes by selected label', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: mockNodes,
         nodeToLabels: mockNodeToLabels,
       });
@@ -188,8 +192,7 @@ describe('NodesPanel', () => {
     });
 
     it('should show correct header text for filtered nodes', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: mockNodes,
         nodeToLabels: mockNodeToLabels,
       });
@@ -207,8 +210,7 @@ describe('NodesPanel', () => {
     });
 
     it('should show empty state for label with no nodes', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: mockNodes,
         nodeToLabels: mockNodeToLabels,
       });
@@ -236,8 +238,7 @@ describe('NodesPanel', () => {
     });
 
     it('should display node basic information', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
       });
 
@@ -254,8 +255,7 @@ describe('NodesPanel', () => {
         createMockNode({ id: 'n3', state: 'SHUTDOWN' }),
       ];
 
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes,
       });
 
@@ -273,8 +273,7 @@ describe('NodesPanel', () => {
     });
 
     it('should display container count', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
       });
 
@@ -296,8 +295,7 @@ describe('NodesPanel', () => {
     });
 
     it('should display memory utilization', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
       });
 
@@ -309,8 +307,7 @@ describe('NodesPanel', () => {
     });
 
     it('should display CPU utilization', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
       });
 
@@ -320,8 +317,7 @@ describe('NodesPanel', () => {
     });
 
     it('should show progress bars for utilization', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
       });
 
@@ -345,8 +341,7 @@ describe('NodesPanel', () => {
         availableVirtualCores: 1,
       });
 
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [highUtilNode],
       });
 
@@ -366,8 +361,7 @@ describe('NodesPanel', () => {
         availableVirtualCores: 0,
       });
 
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [criticalNode],
       });
 
@@ -389,8 +383,7 @@ describe('NodesPanel', () => {
     it('should display assigned labels as badges', () => {
       const node = createMockNode({ id: 'node-1' });
 
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [node],
         nodeToLabels: mockNodeToLabels,
       });
@@ -407,8 +400,7 @@ describe('NodesPanel', () => {
     it('should display Default badge for nodes without labels', () => {
       const node = createMockNode({ id: 'node-2' });
 
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [node],
         nodeToLabels: mockNodeToLabels,
       });
@@ -421,8 +413,7 @@ describe('NodesPanel', () => {
     it('should highlight selected label badge', () => {
       const node = createMockNode({ id: 'node-1' });
 
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [node],
         nodeToLabels: mockNodeToLabels,
       });
@@ -446,8 +437,7 @@ describe('NodesPanel', () => {
     const mockNodeToLabels: NodeToLabelMapping[] = [{ nodeId: 'node-1', 
nodeLabels: ['gpu'] }];
 
     beforeEach(() => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
         nodeToLabels: mockNodeToLabels,
       });
@@ -506,8 +496,7 @@ describe('NodesPanel', () => {
     });
 
     it('should disable select when loading', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
         nodeToLabels: mockNodeToLabels,
         isLoading: true,
@@ -540,8 +529,7 @@ describe('NodesPanel', () => {
     const mockNodeToLabels: NodeToLabelMapping[] = [{ nodeId: 'node-1', 
nodeLabels: ['gpu'] }];
 
     it('should show remove button for nodes with labels', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
         nodeToLabels: mockNodeToLabels,
       });
@@ -560,8 +548,7 @@ describe('NodesPanel', () => {
     it('should not show remove button for nodes without labels', () => {
       const nodeToLabels: NodeToLabelMapping[] = [{ nodeId: 'node-1', 
nodeLabels: [] }];
 
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
         nodeToLabels,
       });
@@ -580,8 +567,7 @@ describe('NodesPanel', () => {
     it('should call assignNodeToLabel with null when remove is clicked', async 
() => {
       mockAssignNodeToLabel.mockResolvedValue(undefined);
 
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
         nodeToLabels: mockNodeToLabels,
       });
@@ -599,8 +585,7 @@ describe('NodesPanel', () => {
     });
 
     it('should disable remove button when loading', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
         nodeToLabels: mockNodeToLabels,
         isLoading: true,
@@ -624,8 +609,7 @@ describe('NodesPanel', () => {
     ];
 
     it('should render table with correct headers', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: mockNodes,
       });
 
@@ -641,8 +625,7 @@ describe('NodesPanel', () => {
     });
 
     it('should render correct number of rows', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: mockNodes,
       });
 
@@ -657,8 +640,7 @@ describe('NodesPanel', () => {
     const mockNode = createMockNode({ id: 'node-1' });
 
     it('should have accessible table structure', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
       });
 
@@ -672,8 +654,7 @@ describe('NodesPanel', () => {
     });
 
     it('should have accessible progress bars', () => {
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
       });
 
@@ -696,8 +677,7 @@ describe('NodesPanel', () => {
     it('should have accessible tooltips', () => {
       const mockNodeToLabels: NodeToLabelMapping[] = [{ nodeId: 'node-1', 
nodeLabels: ['gpu'] }];
 
-      (useSchedulerStore as any).mockReturnValue({
-        ...defaultStoreState,
+      mockStore({
         nodes: [mockNode],
         nodeToLabels: mockNodeToLabels,
       });
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodesPanel.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodesPanel.tsx
index e0e34bf9d8b..d2df995d50f 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodesPanel.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/node-labels/components/NodesPanel.tsx
@@ -19,6 +19,7 @@
 
 import React from 'react';
 import { Monitor, HardDrive, Cpu, X } from 'lucide-react';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import { Badge } from '~/components/ui/badge';
 import { Button } from '~/components/ui/button';
@@ -48,15 +49,20 @@ interface NodesPanelProps {
 }
 
 export const NodesPanel: React.FC<NodesPanelProps> = ({ selectedLabel }) => {
-  const {
-    nodes,
-    nodeToLabels,
-    nodeLabels,
-    assignNodeToLabel,
-    isLoading,
-    searchQuery,
-    getFilteredNodes,
-  } = useSchedulerStore();
+  // State values (trigger re-renders only when these specific values change)
+  const { nodes, nodeToLabels, nodeLabels, isLoading, searchQuery } = 
useSchedulerStore(
+    useShallow((s) => ({
+      nodes: s.nodes,
+      nodeToLabels: s.nodeToLabels,
+      nodeLabels: s.nodeLabels,
+      isLoading: s.isLoading,
+      searchQuery: s.searchQuery,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const assignNodeToLabel = useSchedulerStore((s) => s.assignNodeToLabel);
+  const getFilteredNodes = useSchedulerStore((s) => s.getFilteredNodes);
 
   // Create a map of nodeId -> labels for quick lookup
   const nodeLabelsMap = new Map<string, string[]>();
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/MigrationDialog.test.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/MigrationDialog.test.tsx
index de2e9d58804..4ee6a1f32a5 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/MigrationDialog.test.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/MigrationDialog.test.tsx
@@ -33,6 +33,13 @@ describe('PlacementRulesMigrationDialog', () => {
     migrateLegacyRules: vi.fn(),
   };
 
+  function mockStore(overrides: Record<string, any> = {}) {
+    const state = { ...mockStoreState, ...overrides };
+    vi.mocked(useSchedulerStore).mockImplementation((selector?: any) => {
+      return selector ? selector(state) : state;
+    });
+  }
+
   const defaultProps = {
     open: true,
     onOpenChange: vi.fn(),
@@ -40,7 +47,7 @@ describe('PlacementRulesMigrationDialog', () => {
 
   beforeEach(() => {
     vi.clearAllMocks();
-    vi.mocked(useSchedulerStore).mockReturnValue(mockStoreState);
+    mockStore();
   });
 
   it('should render when open is true', () => {
@@ -138,10 +145,7 @@ describe('PlacementRulesMigrationDialog', () => {
   });
 
   it('should handle missing legacy rules', async () => {
-    vi.mocked(useSchedulerStore).mockReturnValue({
-      ...mockStoreState,
-      legacyRules: null,
-    });
+    mockStore({ legacyRules: null });
 
     render(<PlacementRulesMigrationDialog {...defaultProps} />);
 
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/MigrationDialog.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/MigrationDialog.tsx
index 50bd0f6346e..e048e062600 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/MigrationDialog.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/MigrationDialog.tsx
@@ -33,6 +33,7 @@ import {
 } from '~/components/ui/dialog';
 import { Alert, AlertDescription } from '~/components/ui/alert';
 import { AlertCircle, CheckCircle2 } from 'lucide-react';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import type { MigrationResult } from '~/types/features/placement-rules';
 
@@ -45,7 +46,15 @@ export const PlacementRulesMigrationDialog = ({
   open,
   onOpenChange,
 }: PlacementRulesMigrationDialogProps) => {
-  const { legacyRules, migrateLegacyRules: storeMigrateLegacyRules } = 
useSchedulerStore();
+  // State values (trigger re-renders only when these specific values change)
+  const { legacyRules } = useSchedulerStore(
+    useShallow((s) => ({
+      legacyRules: s.legacyRules,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const storeMigrateLegacyRules = useSchedulerStore((s) => 
s.migrateLegacyRules);
 
   const [migrationResult, setMigrationResult] = useState<MigrationResult | 
null>(null);
   const [isMigrating, setIsMigrating] = useState(false);
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRuleDetail.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRuleDetail.tsx
index 34f49cc34c2..12a973657cc 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRuleDetail.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRuleDetail.tsx
@@ -22,13 +22,23 @@ import { Card, CardContent, CardDescription, CardHeader, 
CardTitle } from '~/com
 import { Button } from '~/components/ui/button';
 import { Separator } from '~/components/ui/separator';
 import { Badge } from '~/components/ui/badge';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import { PlacementRuleForm } from './PlacementRuleForm';
 import { getPolicyDescription } from 
'~/features/placement-rules/constants/policy-descriptions';
 import type { PlacementRule } from '~/types/features/placement-rules';
 
 export function PlacementRuleDetail() {
-  const { rules, selectedRuleIndex, updateRule } = useSchedulerStore();
+  // State values (trigger re-renders only when these specific values change)
+  const { rules, selectedRuleIndex } = useSchedulerStore(
+    useShallow((s) => ({
+      rules: s.rules,
+      selectedRuleIndex: s.selectedRuleIndex,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const updateRule = useSchedulerStore((s) => s.updateRule);
   const [isEditing, setIsEditing] = useState(false);
 
   if (selectedRuleIndex === null || !rules[selectedRuleIndex]) {
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRulesList.test.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRulesList.test.tsx
index d12c243220f..877846e78d5 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRulesList.test.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRulesList.test.tsx
@@ -116,9 +116,16 @@ describe('PlacementRulesList', () => {
     applyError: null,
   };
 
+  function mockStore(overrides: Record<string, any> = {}) {
+    const state = { ...mockStoreFunctions, ...overrides };
+    vi.mocked(useSchedulerStore).mockImplementation((selector?: any) => {
+      return selector ? selector(state) : state;
+    });
+  }
+
   beforeEach(() => {
     vi.clearAllMocks();
-    vi.mocked(useSchedulerStore).mockReturnValue(mockStoreFunctions);
+    mockStore();
   });
 
   it('should render empty state when no rules exist', () => {
@@ -132,10 +139,7 @@ describe('PlacementRulesList', () => {
   });
 
   it('should render table view when rules exist', () => {
-    vi.mocked(useSchedulerStore).mockReturnValue({
-      ...mockStoreFunctions,
-      rules: mockRules,
-    });
+    mockStore({ rules: mockRules });
 
     render(<PlacementRulesList />);
 
@@ -185,10 +189,7 @@ describe('PlacementRulesList', () => {
 
   it('should call deleteRule when delete is clicked on a rule', async () => {
     const user = userEvent.setup();
-    vi.mocked(useSchedulerStore).mockReturnValue({
-      ...mockStoreFunctions,
-      rules: mockRules,
-    });
+    mockStore({ rules: mockRules });
 
     render(<PlacementRulesList />);
 
@@ -200,10 +201,7 @@ describe('PlacementRulesList', () => {
   });
 
   it('should display info alert about rule evaluation order', () => {
-    vi.mocked(useSchedulerStore).mockReturnValue({
-      ...mockStoreFunctions,
-      rules: mockRules,
-    });
+    mockStore({ rules: mockRules });
 
     render(<PlacementRulesList />);
 
@@ -215,10 +213,7 @@ describe('PlacementRulesList', () => {
   });
 
   it('should display apply error alert when present', () => {
-    vi.mocked(useSchedulerStore).mockReturnValue({
-      ...mockStoreFunctions,
-      applyError: 'HTTP 400: Invalid configuration',
-    });
+    mockStore({ applyError: 'HTTP 400: Invalid configuration' });
 
     render(<PlacementRulesList />);
 
@@ -229,10 +224,7 @@ describe('PlacementRulesList', () => {
   it('should call loadPlacementRules on mount when configData is available', 
() => {
     // Set up configData with some content
     const configWithData = new Map([['some.property', 'value']]);
-    vi.mocked(useSchedulerStore).mockReturnValue({
-      ...mockStoreFunctions,
-      configData: configWithData,
-    });
+    mockStore({ configData: configWithData });
 
     render(<PlacementRulesList />);
 
@@ -248,8 +240,7 @@ describe('PlacementRulesList', () => {
 
   describe('legacy mode behavior', () => {
     it('should show legacy mode UI when isLegacyMode is true', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...mockStoreFunctions,
+      mockStore({
         isLegacyMode: true,
         legacyRules: 'u:user1:root.default,u:user2:root.production',
       });
@@ -264,10 +255,7 @@ describe('PlacementRulesList', () => {
     });
 
     it('should show migrate button in legacy mode', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...mockStoreFunctions,
-        isLegacyMode: true,
-      });
+      mockStore({ isLegacyMode: true });
 
       render(<PlacementRulesList />);
 
@@ -276,10 +264,7 @@ describe('PlacementRulesList', () => {
     });
 
     it('should not show add form in legacy mode', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...mockStoreFunctions,
-        isLegacyMode: true,
-      });
+      mockStore({ isLegacyMode: true });
 
       render(<PlacementRulesList />);
 
@@ -288,11 +273,7 @@ describe('PlacementRulesList', () => {
     });
 
     it('should not show rules table in legacy mode', () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        ...mockStoreFunctions,
-        isLegacyMode: true,
-        rules: mockRules,
-      });
+      mockStore({ isLegacyMode: true, rules: mockRules });
 
       render(<PlacementRulesList />);
 
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRulesList.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRulesList.tsx
index 76a569bbad9..8a1bb32eeee 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRulesList.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/placement-rules/components/PlacementRulesList.tsx
@@ -26,25 +26,40 @@ import { PlacementRuleForm } from './PlacementRuleForm';
 import { PlacementRulesTable } from './PlacementRulesTable';
 import { PolicyReferenceDialog } from './PolicyReferenceDialog';
 import { PlacementRulesMigrationDialog } from './MigrationDialog';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import type { PlacementRule } from '~/types/features/placement-rules';
 
 export function PlacementRulesList() {
+  // State values (trigger re-renders only when these specific values change)
   const {
     rules,
     selectedRuleIndex,
-    addRule,
-    deleteRule,
-    reorderRules,
-    selectRule,
-    loadPlacementRules,
     isLegacyMode,
     legacyRules,
     configData,
     stagedChanges,
     formatWarning,
     applyError,
-  } = useSchedulerStore();
+  } = useSchedulerStore(
+    useShallow((s) => ({
+      rules: s.rules,
+      selectedRuleIndex: s.selectedRuleIndex,
+      isLegacyMode: s.isLegacyMode,
+      legacyRules: s.legacyRules,
+      configData: s.configData,
+      stagedChanges: s.stagedChanges,
+      formatWarning: s.formatWarning,
+      applyError: s.applyError,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const addRule = useSchedulerStore((s) => s.addRule);
+  const deleteRule = useSchedulerStore((s) => s.deleteRule);
+  const reorderRules = useSchedulerStore((s) => s.reorderRules);
+  const selectRule = useSchedulerStore((s) => s.selectRule);
+  const loadPlacementRules = useSchedulerStore((s) => s.loadPlacementRules);
 
   const [showAddForm, setShowAddForm] = useState(false);
   const [showMigrationDialog, setShowMigrationDialog] = useState(false);
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/PropertyPanel.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/PropertyPanel.tsx
index 07f96d82700..7a78f72e768 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/PropertyPanel.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/PropertyPanel.tsx
@@ -17,8 +17,9 @@
  */
 
 
-import React, { useState, useEffect, useRef } from 'react';
+import React, { useReducer, useState, useEffect, useRef } from 'react';
 import { Save, RotateCcw, GitBranch, Info, Settings, Edit, AlertTriangle } 
from 'lucide-react';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import { Sheet, SheetContent, SheetHeader, SheetTitle } from 
'~/components/ui/sheet';
 import { Tabs, TabsContent, TabsList, TabsTrigger } from 
'~/components/ui/tabs';
@@ -39,27 +40,83 @@ import { AUTO_CREATION_PROPS } from 
'~/types/constants/auto-creation';
 import { useKeyboardShortcuts, getModifierKey } from 
'~/hooks/useKeyboardShortcuts';
 import { Kbd } from '~/components/ui/kbd';
 
+// -- Form lifecycle reducer --------------------------------------------------
+// Replaces individual useState calls for hasChanges, isFormDirty, 
isSubmitting,
+// showUnsavedDialog, and pendingClose with a single reducer that prevents
+// impossible state combinations (e.g. confirming-close without pendingClose).
+
+type FormState =
+  | { status: 'idle'; hasChanges: boolean; isFormDirty: boolean }
+  | { status: 'submitting'; hasChanges: boolean; isFormDirty: boolean }
+  | { status: 'confirming-close'; hasChanges: boolean; isFormDirty: boolean };
+
+type FormAction =
+  | { type: 'SET_HAS_CHANGES'; value: boolean }
+  | { type: 'SET_FORM_DIRTY'; value: boolean }
+  | { type: 'START_SUBMIT' }
+  | { type: 'END_SUBMIT' }
+  | { type: 'REQUEST_CLOSE' }
+  | { type: 'CANCEL_CLOSE' }
+  | { type: 'RESET' };
+
+const INITIAL_FORM_STATE: FormState = {
+  status: 'idle',
+  hasChanges: false,
+  isFormDirty: false,
+};
+
+function formReducer(state: FormState, action: FormAction): FormState {
+  switch (action.type) {
+    case 'SET_HAS_CHANGES':
+      return { ...state, hasChanges: action.value };
+    case 'SET_FORM_DIRTY':
+      return { ...state, isFormDirty: action.value };
+    case 'START_SUBMIT':
+      return { ...state, status: 'submitting' };
+    case 'END_SUBMIT':
+      return { ...state, status: state.status === 'submitting' ? 'idle' : 
state.status };
+    case 'REQUEST_CLOSE':
+      return { ...state, status: 'confirming-close' };
+    case 'CANCEL_CLOSE':
+      return { ...state, status: state.status === 'confirming-close' ? 'idle' 
: state.status };
+    case 'RESET':
+      return INITIAL_FORM_STATE;
+    default:
+      return state;
+  }
+}
+
 export const PropertyPanel: React.FC = () => {
+  // State values (trigger re-renders only when these specific values change)
   const {
     selectedQueuePath,
     isPropertyPanelOpen,
-    setPropertyPanelOpen,
-    getQueueByPath,
-    selectQueue,
     propertyPanelInitialTab,
     shouldOpenTemplateConfig,
-    clearTemplateConfigRequest,
-  } = useSchedulerStore();
+    stagedChanges,
+  } = useSchedulerStore(
+    useShallow((s) => ({
+      selectedQueuePath: s.selectedQueuePath,
+      isPropertyPanelOpen: s.isPropertyPanelOpen,
+      propertyPanelInitialTab: s.propertyPanelInitialTab,
+      shouldOpenTemplateConfig: s.shouldOpenTemplateConfig,
+      stagedChanges: s.stagedChanges,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const setPropertyPanelOpen = useSchedulerStore((s) => 
s.setPropertyPanelOpen);
+  const getQueueByPath = useSchedulerStore((s) => s.getQueueByPath);
+  const selectQueue = useSchedulerStore((s) => s.selectQueue);
+  const clearTemplateConfigRequest = useSchedulerStore((s) => 
s.clearTemplateConfigRequest);
+  const getQueuePropertyValue = useSchedulerStore((s) => 
s.getQueuePropertyValue);
 
-  const getQueuePropertyValue = useSchedulerStore((state) => 
state.getQueuePropertyValue);
-  const stagedChanges = useSchedulerStore((state) => state.stagedChanges);
+  const [formState, dispatch] = useReducer(formReducer, INITIAL_FORM_STATE);
+  const { hasChanges, isFormDirty } = formState;
+  const isSubmitting = formState.status === 'submitting';
+  const showUnsavedDialog = formState.status === 'confirming-close';
 
   const [tabValue, setTabValue] = useState('overview');
-  const [hasChanges, setHasChanges] = useState(false);
-  const [isSubmitting, setIsSubmitting] = useState(false);
-  const [isFormDirty, setIsFormDirty] = useState(false);
-  const [showUnsavedDialog, setShowUnsavedDialog] = useState(false);
-  const [pendingClose, setPendingClose] = useState(false);
   const [isSummaryOpen, setIsSummaryOpen] = useState(false);
   const [isTemplateDialogOpen, setIsTemplateDialogOpen] = useState(false);
 
@@ -145,12 +202,10 @@ export const PropertyPanel: React.FC = () => {
 
   const handleClose = (force = false) => {
     if (!force && isFormDirty && tabValue === 'settings') {
-      setShowUnsavedDialog(true);
-      setPendingClose(true);
+      dispatch({ type: 'REQUEST_CLOSE' });
     } else {
       setPropertyPanelOpen(false);
       selectQueue(null); // Deselect queue when panel closes
-      setPendingClose(false);
     }
   };
 
@@ -181,15 +236,15 @@ export const PropertyPanel: React.FC = () => {
   };
 
   const handleHasChangesChange = (newHasChanges: boolean) => {
-    setHasChanges(newHasChanges);
+    dispatch({ type: 'SET_HAS_CHANGES', value: newHasChanges });
   };
 
   const handleFormDirtyChange = (newIsFormDirty: boolean) => {
-    setIsFormDirty(newIsFormDirty);
+    dispatch({ type: 'SET_FORM_DIRTY', value: newIsFormDirty });
   };
 
   const handleIsSubmittingChange = (newIsSubmitting: boolean) => {
-    setIsSubmitting(newIsSubmitting);
+    dispatch(newIsSubmitting ? { type: 'START_SUBMIT' } : { type: 'END_SUBMIT' 
});
   };
 
   const handleSaveAndClose = async () => {
@@ -201,23 +256,22 @@ export const PropertyPanel: React.FC = () => {
     }
 
     await handleSubmit();
-    if (pendingClose) {
+    if (showUnsavedDialog) {
       handleClose(true);
     }
-    setShowUnsavedDialog(false);
+    dispatch({ type: 'CANCEL_CLOSE' });
   };
 
   const handleDiscardAndClose = () => {
     handleReset();
     handleClose(true);
-    setShowUnsavedDialog(false);
+    dispatch({ type: 'CANCEL_CLOSE' });
   };
 
-  // Reset hasChanges and form dirty state when panel opens/closes or queue 
changes
+  // Reset form state when panel opens/closes or queue changes
   useEffect(() => {
     if (!isPropertyPanelOpen || !selectedQueuePath) {
-      setHasChanges(false);
-      setIsFormDirty(false);
+      dispatch({ type: 'RESET' });
       setIsSummaryOpen(false);
     }
   }, [isPropertyPanelOpen, selectedQueuePath]);
@@ -429,7 +483,9 @@ export const PropertyPanel: React.FC = () => {
 
       <UnsavedChangesDialog
         open={showUnsavedDialog}
-        onOpenChange={setShowUnsavedDialog}
+        onOpenChange={(open) => {
+          if (!open) dispatch({ type: 'CANCEL_CLOSE' });
+        }}
         onSave={handleSaveAndClose}
         onDiscard={handleDiscardAndClose}
         isSaving={isSubmitting}
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.label-filter.test.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.label-filter.test.tsx
index ecce090cd69..c2829a2aa09 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.label-filter.test.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.label-filter.test.tsx
@@ -83,23 +83,34 @@ describe('QueueCardNode - Node Label Filtering', () => {
     deletable: false,
   };
 
+  const defaultStoreState: Record<string, any> = {
+    comparisonQueues: [],
+    selectedQueuePath: null,
+    selectQueue: vi.fn(),
+    setPropertyPanelOpen: vi.fn(),
+    isPropertyPanelOpen: false,
+    propertyPanelInitialTab: 'overview',
+    setPropertyPanelInitialTab: vi.fn(),
+    toggleComparisonQueue: vi.fn(),
+    selectedNodeLabelFilter: '',
+    getQueueLabelCapacity: mockGetQueueLabelCapacity,
+    hasPendingDeletion: vi.fn().mockReturnValue(false),
+    clearQueueChanges: vi.fn(),
+    requestTemplateConfigOpen: vi.fn(),
+    searchQuery: '',
+    isComparisonModeActive: false,
+  };
+
+  function mockStore(overrides: Record<string, any> = {}) {
+    const state = { ...defaultStoreState, ...overrides };
+    vi.mocked(useSchedulerStore).mockImplementation((selector?: any) => {
+      return selector ? selector(state) : state;
+    });
+  }
+
   beforeEach(() => {
     vi.clearAllMocks();
-    vi.mocked(useSchedulerStore).mockReturnValue({
-      comparisonQueues: [],
-      selectedQueuePath: null,
-      selectQueue: vi.fn(),
-      setPropertyPanelOpen: vi.fn(),
-      isPropertyPanelOpen: false,
-      propertyPanelInitialTab: 'overview',
-      setPropertyPanelInitialTab: vi.fn(),
-      toggleComparisonQueue: vi.fn(),
-      selectedNodeLabelFilter: '',
-      getQueueLabelCapacity: mockGetQueueLabelCapacity,
-      hasPendingDeletion: vi.fn().mockReturnValue(false),
-      clearQueueChanges: vi.fn(),
-      requestTemplateConfigOpen: vi.fn(),
-    } as any);
+    mockStore();
   });
 
   describe('DEFAULT label (no filter)', () => {
@@ -144,21 +155,7 @@ describe('QueueCardNode - Node Label Filtering', () => {
 
   describe('Label-specific filtering', () => {
     beforeEach(() => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        comparisonQueues: [],
-        selectedQueuePath: null,
-        selectQueue: vi.fn(),
-        setPropertyPanelOpen: vi.fn(),
-        isPropertyPanelOpen: false,
-        propertyPanelInitialTab: 'overview',
-        setPropertyPanelInitialTab: vi.fn(),
-        toggleComparisonQueue: vi.fn(),
-        selectedNodeLabelFilter: 'gpu',
-        getQueueLabelCapacity: mockGetQueueLabelCapacity,
-        hasPendingDeletion: vi.fn().mockReturnValue(false),
-        clearQueueChanges: vi.fn(),
-        requestTemplateConfigOpen: vi.fn(),
-      } as any);
+      mockStore({ selectedNodeLabelFilter: 'gpu' });
     });
 
     it('should show label-specific capacity when queue has access', () => {
@@ -257,18 +254,7 @@ describe('QueueCardNode - Node Label Filtering', () => {
 
   describe('Label badge tooltip', () => {
     it('should show tooltip for label badge', async () => {
-      vi.mocked(useSchedulerStore).mockReturnValue({
-        comparisonQueues: [],
-        selectedQueuePath: null,
-        selectQueue: vi.fn(),
-        setPropertyPanelOpen: vi.fn(),
-        toggleComparisonQueue: vi.fn(),
-        selectedNodeLabelFilter: 'gpu',
-        getQueueLabelCapacity: mockGetQueueLabelCapacity,
-        hasPendingDeletion: vi.fn().mockReturnValue(false),
-        clearQueueChanges: vi.fn(),
-        requestTemplateConfigOpen: vi.fn(),
-      } as any);
+      mockStore({ selectedNodeLabelFilter: 'gpu' });
 
       mockGetQueueLabelCapacity.mockReturnValue({
         capacity: '80',
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.tsx
index 30eb6dcc0f8..233711329ae 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.tsx
@@ -19,6 +19,7 @@
 
 import React, { useState } from 'react';
 import { Handle, Position, type NodeProps } from '@xyflow/react';
+import { useShallow } from 'zustand/react/shallow';
 
 import {
   Card,
@@ -32,7 +33,6 @@ import { Checkbox } from '~/components/ui/checkbox';
 import type { QueueCardData } from 
'~/features/queue-management/hooks/useQueueTreeData';
 import { useQueueActions } from 
'~/features/queue-management/hooks/useQueueActions';
 import { useSchedulerStore } from '~/stores/schedulerStore';
-import { cn } from '~/utils/cn';
 import { HighlightedText } from '~/components/search/HighlightedText';
 import { AddQueueDialog } from './dialogs/AddQueueDialog';
 import { DeleteQueueDialog } from './dialogs/DeleteQueueDialog';
@@ -43,9 +43,9 @@ import { QueueValidationBadges } from 
'./QueueValidationBadges';
 import { QueueVectorCapacityDisplay } from './QueueVectorCapacityDisplay';
 import { QueueCardContextMenu } from './QueueCardContextMenu';
 import { getCapacityDisplay } from '../utils/capacityDisplay';
-import { QUEUE_STATES, SPECIAL_VALUES } from '~/types';
 import { parseCapacityValue } from '~/utils/capacityUtils';
-import { useCapacityEditor } from 
'~/features/queue-management/hooks/useCapacityEditor';
+import { getQueueCardClassName } from '../utils/queueCardStyles';
+import { useQueueCardHandlers } from '../hooks/useQueueCardHandlers';
 import { QUEUE_CARD_HEIGHT, QUEUE_CARD_WIDTH } from 
'~/features/queue-management/constants';
 
 export const QueueCardNode: React.FC<NodeProps> = ({ data }) => {
@@ -55,25 +55,30 @@ export const QueueCardNode: React.FC<NodeProps> = ({ data 
}) => {
   // Cast data to QueueCardData type
   const queueData = data as QueueCardData;
 
+  // State values (trigger re-renders only when these specific values change)
   const {
     comparisonQueues,
     selectedQueuePath,
-    selectQueue,
-    setPropertyPanelOpen,
     isPropertyPanelOpen,
-    setPropertyPanelInitialTab,
-    requestTemplateConfigOpen,
-    toggleComparisonQueue,
     selectedNodeLabelFilter,
-    getQueueLabelCapacity,
-    clearQueueChanges,
-    hasPendingDeletion,
     searchQuery,
     isComparisonModeActive,
-  } = useSchedulerStore();
+  } = useSchedulerStore(
+    useShallow((s) => ({
+      comparisonQueues: s.comparisonQueues,
+      selectedQueuePath: s.selectedQueuePath,
+      isPropertyPanelOpen: s.isPropertyPanelOpen,
+      selectedNodeLabelFilter: s.selectedNodeLabelFilter,
+      searchQuery: s.searchQuery,
+      isComparisonModeActive: s.isComparisonModeActive,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const getQueueLabelCapacity = useSchedulerStore((s) => 
s.getQueueLabelCapacity);
+  const hasPendingDeletion = useSchedulerStore((s) => s.hasPendingDeletion);
 
-  const { canAddChildQueue, canDeleteQueue, updateQueueProperty } = 
useQueueActions();
-  const { openCapacityEditor } = useCapacityEditor();
+  const { canAddChildQueue, canDeleteQueue } = useQueueActions();
 
   const {
     queuePath,
@@ -126,141 +131,42 @@ export const QueueCardNode: React.FC<NodeProps> = ({ 
data }) => {
   const isTemplateManageable =
     autoCreationStatus?.status === 'legacy' || autoCreationStatus?.status === 
'flexible';
 
-  const openPropertyPanel = (
-    event: React.MouseEvent,
-    initialTab: 'overview' | 'info' | 'settings' = 'overview',
-  ) => {
-    event.stopPropagation();
-
-    // Don't allow clicking on newly added queues that haven't been applied yet
-    if (stagedStatus === 'new') {
-      return;
-    }
-
-    const tabToOpen = isAutoCreatedQueue && initialTab === 'settings' ? 
'overview' : initialTab;
-    setPropertyPanelInitialTab(tabToOpen);
-    // Set selected queue and open property panel
-    selectQueue(queuePath);
-    setPropertyPanelOpen(true);
-  };
-
-  const handleOpenCapacityEditor = (event: React.MouseEvent) => {
-    event.stopPropagation();
-    if (!queuePath || queuePath === SPECIAL_VALUES.ROOT_QUEUE_NAME) {
-      return;
-    }
-
-    const parentPath = queuePath.split('.').slice(0, -1).join('.');
-    if (!parentPath) {
-      return;
-    }
-
-    openCapacityEditor({
-      origin: 'context-menu',
-      parentQueuePath: parentPath,
-      originQueuePath: queuePath,
-      originQueueName: queueName,
-      capacityValue: capacityConfig,
-      maxCapacityValue: maxCapacityConfig,
-      queueState: state,
-      markOriginAsNew: stagedStatus === 'new',
-    });
-  };
-
-  const handleRemoveStagedQueue = (event: React.MouseEvent) => {
-    event.stopPropagation();
-    event.preventDefault();
-    if (queuePath) {
-      clearQueueChanges(queuePath);
-    }
-  };
-
-  const handleComparisonToggle = () => {
-    toggleComparisonQueue(queuePath);
-  };
-
-  const handleToggleState = () => {
-    const newState = state === QUEUE_STATES.RUNNING ? QUEUE_STATES.STOPPED : 
QUEUE_STATES.RUNNING;
-    updateQueueProperty(queuePath, 'state', newState);
-  };
-
-  const handleManageTemplate = (event: React.MouseEvent) => {
-    event.stopPropagation();
-    setPropertyPanelInitialTab('settings');
-    selectQueue(queuePath);
-    requestTemplateConfigOpen();
-  };
+  const {
+    openPropertyPanel,
+    handleOpenCapacityEditor,
+    handleRemoveStagedQueue,
+    handleComparisonToggle,
+    handleToggleState,
+    handleManageTemplate,
+    handleContextMenuOpenChange,
+    handleCardClick,
+  } = useQueueCardHandlers({
+    queuePath,
+    queueName,
+    state,
+    capacityConfig,
+    maxCapacityConfig,
+    stagedStatus,
+    isAutoCreatedQueue,
+    isComparisonModeActive,
+    isSelectedQueue,
+    isPropertyPanelOpen,
+  });
 
-  const handleContextMenuOpenChange = (open: boolean) => {
-    if (!open && isSelectedQueue && !isPropertyPanelOpen) {
-      selectQueue(null);
-    }
-  };
+  const cardClassName = getQueueCardClassName({
+    isAutoCreatedQueue,
+    stagedStatus,
+    isSelectedQueue,
+    isSelectedForComparison,
+    validationErrors,
+    isAffectedByErrors,
+    shouldGrayOut,
+  });
 
   const cardContent = (
     <Card
-      className={cn(
-        'relative flex flex-col',
-        // Smooth transitions with spring-like feel
-        'transition-all duration-200 ease-out',
-        // Enhanced background with subtle gradient
-        'bg-gradient-to-br from-gray-50 to-white dark:from-gray-900 
dark:to-gray-950',
-        'border-gray-200 dark:border-gray-700/80',
-        // Auto-created queue styling
-        isAutoCreatedQueue &&
-          'border-amber-400 dark:border-amber-500 border-2 border-dashed 
from-amber-50/70 to-amber-50/50 dark:from-amber-900/30 dark:to-amber-950/20',
-        // Shadow for depth with hover enhancement
-        'shadow-lg hover:shadow-xl hover:-translate-y-0.5',
-        'dark:shadow-md dark:shadow-black/20 dark:hover:shadow-lg 
dark:hover:shadow-black/30',
-        // Cursor styling - not clickable for new queues
-        stagedStatus === 'new' ? 'opacity-75 cursor-default' : 
'cursor-pointer',
-        // Border styling based on status
-        // Left border for staged status (always visible regardless of errors)
-        stagedStatus === 'new' && 'border-l-4 border-l-queue-new',
-        stagedStatus === 'deleted' && 'border-l-4 border-l-queue-deleted',
-        stagedStatus === 'modified' && 'border-l-4 border-l-queue-modified',
-        // Ring for staged status (only if no validation errors)
-        stagedStatus === 'new' &&
-          !(validationErrors && validationErrors.some((e) => e.severity === 
'error')) &&
-          'ring-2 ring-queue-new',
-        stagedStatus === 'deleted' &&
-          !(validationErrors && validationErrors.some((e) => e.severity === 
'error')) &&
-          'ring-2 ring-queue-deleted',
-        stagedStatus === 'modified' &&
-          !(validationErrors && validationErrors.some((e) => e.severity === 
'error')) &&
-          'ring-2 ring-queue-modified',
-        !stagedStatus && isSelectedQueue && 'ring-2 ring-primary 
shadow-primary/10',
-        // Ring for validation errors (can coexist with staged status border)
-        validationErrors &&
-          validationErrors.some((e) => e.severity === 'error') &&
-          'ring-2 ring-destructive',
-        // Left border for affected queues only if no staged status
-        !stagedStatus &&
-          validationErrors &&
-          validationErrors.some((e) => e.severity === 'error') &&
-          'border-l-4 border-l-destructive',
-        isAffectedByErrors &&
-          !validationErrors &&
-          !stagedStatus &&
-          'ring-2 ring-amber-500 border-l-4 border-l-amber-500',
-        isAffectedByErrors && !validationErrors && stagedStatus && 'ring-2 
ring-amber-500',
-        // Background styling for states
-        isSelectedQueue &&
-          'from-primary/10 to-primary/5 dark:from-primary/15 dark:to-primary/5 
scale-[1.01]',
-        isSelectedForComparison &&
-          !isSelectedQueue &&
-          'from-gray-100 to-gray-50 dark:from-gray-800 dark:to-gray-900',
-        // Gray out inaccessible queues when filtered by label
-        shouldGrayOut && 'opacity-50 grayscale',
-        'gap-4 py-5',
-      )}
-      onClick={(event) => {
-        if (isComparisonModeActive) {
-          handleComparisonToggle();
-        } else {
-          openPropertyPanel(event, 'overview');
-        }
-      }}
+      className={cardClassName}
+      onClick={handleCardClick}
       style={{ width: QUEUE_CARD_WIDTH, height: QUEUE_CARD_HEIGHT }}
     >
       <CardHeader className="px-5 pb-3 gap-1">
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueVisualizationContainer.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueVisualizationContainer.tsx
index a758cde8c5c..3600fa0f9d9 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueVisualizationContainer.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueVisualizationContainer.tsx
@@ -31,6 +31,7 @@ import {
 import '@xyflow/react/dist/style.css';
 import { Alert, AlertDescription, AlertTitle } from '~/components/ui/alert';
 import { AlertCircle, Tag, Search, X, Info } from 'lucide-react';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import {
   useQueueTreeData,
@@ -61,15 +62,26 @@ const edgeTypes = {
 };
 
 const FlowInner: React.FC = () => {
+  // State values (trigger re-renders only when these specific values change)
   const {
-    selectQueue,
     stagedChanges,
     searchQuery,
     selectedNodeLabelFilter,
-    getSearchResults,
     configData,
     isComparisonModeActive,
-  } = useSchedulerStore();
+  } = useSchedulerStore(
+    useShallow((s) => ({
+      stagedChanges: s.stagedChanges,
+      searchQuery: s.searchQuery,
+      selectedNodeLabelFilter: s.selectedNodeLabelFilter,
+      configData: s.configData,
+      isComparisonModeActive: s.isComparisonModeActive,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const selectQueue = useSchedulerStore((s) => s.selectQueue);
+  const getSearchResults = useSchedulerStore((s) => s.getSearchResults);
   const { theme } = useTheme();
 
   // Get legacy mode status considering staged changes
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/hooks/useQueueCardHandlers.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/hooks/useQueueCardHandlers.ts
new file mode 100644
index 00000000000..465cb1664fa
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/hooks/useQueueCardHandlers.ts
@@ -0,0 +1,151 @@
+/**
+ * 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 React from 'react';
+import { useSchedulerStore } from '~/stores/schedulerStore';
+import { useQueueActions } from 
'~/features/queue-management/hooks/useQueueActions';
+import { useCapacityEditor } from 
'~/features/queue-management/hooks/useCapacityEditor';
+import { QUEUE_STATES, SPECIAL_VALUES } from '~/types';
+
+interface UseQueueCardHandlersParams {
+  queuePath: string;
+  queueName: string;
+  state: string;
+  capacityConfig: string;
+  maxCapacityConfig: string;
+  stagedStatus: string | undefined;
+  isAutoCreatedQueue: boolean;
+  isComparisonModeActive: boolean;
+  isSelectedQueue: boolean;
+  isPropertyPanelOpen: boolean;
+}
+
+export function useQueueCardHandlers(params: UseQueueCardHandlersParams) {
+  const {
+    queuePath,
+    queueName,
+    state,
+    capacityConfig,
+    maxCapacityConfig,
+    stagedStatus,
+    isAutoCreatedQueue,
+    isComparisonModeActive,
+    isSelectedQueue,
+    isPropertyPanelOpen,
+  } = params;
+
+  const selectQueue = useSchedulerStore((s) => s.selectQueue);
+  const setPropertyPanelOpen = useSchedulerStore((s) => 
s.setPropertyPanelOpen);
+  const setPropertyPanelInitialTab = useSchedulerStore((s) => 
s.setPropertyPanelInitialTab);
+  const requestTemplateConfigOpen = useSchedulerStore((s) => 
s.requestTemplateConfigOpen);
+  const toggleComparisonQueue = useSchedulerStore((s) => 
s.toggleComparisonQueue);
+  const clearQueueChanges = useSchedulerStore((s) => s.clearQueueChanges);
+
+  const { updateQueueProperty } = useQueueActions();
+  const { openCapacityEditor } = useCapacityEditor();
+
+  const openPropertyPanel = (
+    event: React.MouseEvent,
+    initialTab: 'overview' | 'info' | 'settings' = 'overview',
+  ) => {
+    event.stopPropagation();
+
+    // Don't allow clicking on newly added queues that haven't been applied yet
+    if (stagedStatus === 'new') {
+      return;
+    }
+
+    const tabToOpen = isAutoCreatedQueue && initialTab === 'settings' ? 
'overview' : initialTab;
+    setPropertyPanelInitialTab(tabToOpen);
+    selectQueue(queuePath);
+    setPropertyPanelOpen(true);
+  };
+
+  const handleOpenCapacityEditor = (event: React.MouseEvent) => {
+    event.stopPropagation();
+    if (!queuePath || queuePath === SPECIAL_VALUES.ROOT_QUEUE_NAME) {
+      return;
+    }
+
+    const parentPath = queuePath.split('.').slice(0, -1).join('.');
+    if (!parentPath) {
+      return;
+    }
+
+    openCapacityEditor({
+      origin: 'context-menu',
+      parentQueuePath: parentPath,
+      originQueuePath: queuePath,
+      originQueueName: queueName,
+      capacityValue: capacityConfig,
+      maxCapacityValue: maxCapacityConfig,
+      queueState: state,
+      markOriginAsNew: stagedStatus === 'new',
+    });
+  };
+
+  const handleRemoveStagedQueue = (event: React.MouseEvent) => {
+    event.stopPropagation();
+    event.preventDefault();
+    if (queuePath) {
+      clearQueueChanges(queuePath);
+    }
+  };
+
+  const handleComparisonToggle = () => {
+    toggleComparisonQueue(queuePath);
+  };
+
+  const handleToggleState = () => {
+    const newState = state === QUEUE_STATES.RUNNING ? QUEUE_STATES.STOPPED : 
QUEUE_STATES.RUNNING;
+    updateQueueProperty(queuePath, 'state', newState);
+  };
+
+  const handleManageTemplate = (event: React.MouseEvent) => {
+    event.stopPropagation();
+    setPropertyPanelInitialTab('settings');
+    selectQueue(queuePath);
+    requestTemplateConfigOpen();
+  };
+
+  const handleContextMenuOpenChange = (open: boolean) => {
+    if (!open && isSelectedQueue && !isPropertyPanelOpen) {
+      selectQueue(null);
+    }
+  };
+
+  const handleCardClick = (event: React.MouseEvent) => {
+    if (isComparisonModeActive) {
+      handleComparisonToggle();
+    } else {
+      openPropertyPanel(event, 'overview');
+    }
+  };
+
+  return {
+    openPropertyPanel,
+    handleOpenCapacityEditor,
+    handleRemoveStagedQueue,
+    handleComparisonToggle,
+    handleToggleState,
+    handleManageTemplate,
+    handleContextMenuOpenChange,
+    handleCardClick,
+  };
+}
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/utils/queueCardStyles.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/utils/queueCardStyles.ts
new file mode 100644
index 00000000000..8cfd1f1639d
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/utils/queueCardStyles.ts
@@ -0,0 +1,88 @@
+/**
+ * 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 { cn } from '~/utils/cn';
+
+interface QueueCardStyleParams {
+  isAutoCreatedQueue: boolean;
+  stagedStatus: string | undefined;
+  isSelectedQueue: boolean;
+  isSelectedForComparison: boolean;
+  validationErrors: Array<{ severity: string }> | undefined;
+  isAffectedByErrors: boolean | undefined;
+  shouldGrayOut: boolean;
+}
+
+export function getQueueCardClassName(params: QueueCardStyleParams): string {
+  const {
+    isAutoCreatedQueue,
+    stagedStatus,
+    isSelectedQueue,
+    isSelectedForComparison,
+    validationErrors,
+    isAffectedByErrors,
+    shouldGrayOut,
+  } = params;
+
+  const hasErrors = validationErrors && validationErrors.some((e) => 
e.severity === 'error');
+
+  return cn(
+    'relative flex flex-col',
+    // Smooth transitions with spring-like feel
+    'transition-all duration-200 ease-out',
+    // Enhanced background with subtle gradient
+    'bg-gradient-to-br from-gray-50 to-white dark:from-gray-900 
dark:to-gray-950',
+    'border-gray-200 dark:border-gray-700/80',
+    // Auto-created queue styling
+    isAutoCreatedQueue &&
+      'border-amber-400 dark:border-amber-500 border-2 border-dashed 
from-amber-50/70 to-amber-50/50 dark:from-amber-900/30 dark:to-amber-950/20',
+    // Shadow for depth with hover enhancement
+    'shadow-lg hover:shadow-xl hover:-translate-y-0.5',
+    'dark:shadow-md dark:shadow-black/20 dark:hover:shadow-lg 
dark:hover:shadow-black/30',
+    // Cursor styling - not clickable for new queues
+    stagedStatus === 'new' ? 'opacity-75 cursor-default' : 'cursor-pointer',
+    // Left border for staged status (always visible regardless of errors)
+    stagedStatus === 'new' && 'border-l-4 border-l-queue-new',
+    stagedStatus === 'deleted' && 'border-l-4 border-l-queue-deleted',
+    stagedStatus === 'modified' && 'border-l-4 border-l-queue-modified',
+    // Ring for staged status (only if no validation errors)
+    stagedStatus === 'new' && !hasErrors && 'ring-2 ring-queue-new',
+    stagedStatus === 'deleted' && !hasErrors && 'ring-2 ring-queue-deleted',
+    stagedStatus === 'modified' && !hasErrors && 'ring-2 ring-queue-modified',
+    !stagedStatus && isSelectedQueue && 'ring-2 ring-primary 
shadow-primary/10',
+    // Ring for validation errors (can coexist with staged status border)
+    hasErrors && 'ring-2 ring-destructive',
+    // Left border for affected queues only if no staged status
+    !stagedStatus && hasErrors && 'border-l-4 border-l-destructive',
+    isAffectedByErrors &&
+      !validationErrors &&
+      !stagedStatus &&
+      'ring-2 ring-amber-500 border-l-4 border-l-amber-500',
+    isAffectedByErrors && !validationErrors && stagedStatus && 'ring-2 
ring-amber-500',
+    // Background styling for states
+    isSelectedQueue &&
+      'from-primary/10 to-primary/5 dark:from-primary/15 dark:to-primary/5 
scale-[1.01]',
+    isSelectedForComparison &&
+      !isSelectedQueue &&
+      'from-gray-100 to-gray-50 dark:from-gray-800 dark:to-gray-900',
+    // Gray out inaccessible queues when filtered by label
+    shouldGrayOut && 'opacity-50 grayscale',
+    'gap-4 py-5',
+  );
+}
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/staged-changes/components/StagedChangesPanel.tsx
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/staged-changes/components/StagedChangesPanel.tsx
index 7da2968777e..e7c8fd3cab7 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/staged-changes/components/StagedChangesPanel.tsx
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/staged-changes/components/StagedChangesPanel.tsx
@@ -29,6 +29,7 @@ import {
 import { Button } from '~/components/ui/button';
 import { Badge } from '~/components/ui/badge';
 import { Alert, AlertDescription, AlertTitle } from '~/components/ui/alert';
+import { useShallow } from 'zustand/react/shallow';
 import { useSchedulerStore } from '~/stores/schedulerStore';
 import type { StagedChange } from '~/types';
 import { QueueChangeGroup } from './QueueChangeGroup';
@@ -46,8 +47,19 @@ interface StagedChangesPanelProps {
 export function StagedChangesPanel({ open, onClose, onOpen }: 
StagedChangesPanelProps) {
   const [isApplying, setIsApplying] = useState(false);
 
-  const { stagedChanges, revertChange, clearAllChanges, applyChanges, 
applyError, isReadOnly } =
-    useSchedulerStore();
+  // State values (trigger re-renders only when these specific values change)
+  const { stagedChanges, applyError, isReadOnly } = useSchedulerStore(
+    useShallow((s) => ({
+      stagedChanges: s.stagedChanges,
+      applyError: s.applyError,
+      isReadOnly: s.isReadOnly,
+    })),
+  );
+
+  // Actions (stable references, never trigger re-renders)
+  const revertChange = useSchedulerStore((s) => s.revertChange);
+  const clearAllChanges = useSchedulerStore((s) => s.clearAllChanges);
+  const applyChanges = useSchedulerStore((s) => s.applyChanges);
 
   // Group changes by queue path for organized display
   const changesByQueue = stagedChanges.reduce(
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/lib/api/mocks/handlers.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/lib/api/mocks/handlers.ts
index 816ec66ef55..ebd21700c04 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/lib/api/mocks/handlers.ts
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/lib/api/mocks/handlers.ts
@@ -91,12 +91,6 @@ const staticHandlers: HttpHandler[] = [
     return HttpResponse.json(data);
   }),
 
-  http.get(`${baseUrl}/get-labels-to-nodes`, async () => {
-    const response = await 
fetch(`${MOCK_ASSET_BASE}/get-labels-to-nodes.json`);
-    const data = await response.json();
-    return HttpResponse.json(data);
-  }),
-
   http.post(`${baseUrl}/add-node-labels`, async ({ request }) => {
     const body = await request.json();
     console.log('Mock: Adding node labels:', body);
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/lib/api/mocks/server-handlers.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/lib/api/mocks/server-handlers.ts
index 1af19973cfa..c5c0542cf71 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/lib/api/mocks/server-handlers.ts
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/lib/api/mocks/server-handlers.ts
@@ -91,11 +91,6 @@ export const serverHandlers = [
     return HttpResponse.json(data);
   }),
 
-  http.get('/ws/v1/cluster/get-labels-to-nodes', () => {
-    const data = loadMockData('get-labels-to-nodes.json');
-    return HttpResponse.json(data);
-  }),
-
   http.post('/ws/v1/cluster/add-node-labels', async ({ request }) => {
     const body = await request.json();
     console.log('Mock: Adding node labels:', body);
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/schedulerStore.test.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/schedulerStore.test.ts
index 3d170cc2c84..dac74653707 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/schedulerStore.test.ts
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/schedulerStore.test.ts
@@ -18,7 +18,7 @@
 
 
 import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
-import { createSchedulerStore, traverseQueueTree } from 
'~/stores/schedulerStore';
+import { createSchedulerStore } from '~/stores/schedulerStore';
 import { buildMutationRequest } from 
'~/features/staged-changes/utils/mutationBuilder';
 import type { YarnApiClient } from '~/lib/api/YarnApiClient';
 import type {
@@ -31,9 +31,46 @@ import type {
   VersionResponse,
   SchedulerResponse,
 } from '~/types';
-import { QUEUE_TYPES, SPECIAL_VALUES } from '~/types/constants';
+import { CONFIG_PREFIXES, QUEUE_TYPES, SPECIAL_VALUES } from 
'~/types/constants';
 import { AUTO_CREATION_PROPS } from '~/types/constants/auto-creation';
 
+/**
+ * Local helper: traverse queue tree and apply a visitor function.
+ * Combines queue info with configured properties from configData.
+ */
+function traverseQueueTree(
+  queueInfo: QueueInfo,
+  configData: Map<string, string>,
+  visitor: (queue: QueueInfo & { configured: Record<string, string> }) => void,
+): void {
+  const configured: Record<string, string> = {};
+
+  const prefix = `${CONFIG_PREFIXES.BASE}.${queueInfo.queuePath}.`;
+  for (const [key, value] of configData.entries()) {
+    if (key.startsWith(prefix)) {
+      const property = key.substring(prefix.length);
+      configured[property] = value;
+    }
+  }
+
+  const combinedQueue = {
+    ...queueInfo,
+    configured,
+  };
+
+  visitor(combinedQueue);
+
+  if (queueInfo.queues?.queue) {
+    const children = Array.isArray(queueInfo.queues.queue)
+      ? queueInfo.queues.queue
+      : [queueInfo.queues.queue];
+
+    for (const child of children) {
+      traverseQueueTree(child, configData, visitor);
+    }
+  }
+}
+
 const toEntryRecord = (entries?: Array<{ key: string; value: string }>) =>
   Object.fromEntries((entries ?? []).map(({ key, value }) => [key, value]));
 
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/schedulerStore.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/schedulerStore.ts
index eaf014d7fb0..94f483f332c 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/schedulerStore.ts
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/schedulerStore.ts
@@ -74,6 +74,5 @@ export const createSchedulerStore = (apiClient: 
YarnApiClient) => {
   return create(createStoreImplementation(apiClient));
 };
 
-// Re-export types and utilities
+// Re-export types
 export type { SchedulerStore } from './slices';
-export { traverseQueueTree } from './slices/queueDataSlice';
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/__tests__/queueDataSlice.test.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/__tests__/queueDataSlice.test.ts
index f2f2f568565..9822355d3ad 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/__tests__/queueDataSlice.test.ts
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/__tests__/queueDataSlice.test.ts
@@ -20,9 +20,45 @@
 import { describe, it, expect, beforeEach } from 'vitest';
 import { createSchedulerStore } from '~/stores/schedulerStore';
 import { YarnApiClient } from '~/lib/api/YarnApiClient';
-import { traverseQueueTree } from '~/stores/slices/queueDataSlice';
 import type { QueueInfo, SchedulerInfo } from '~/types';
-import { SPECIAL_VALUES } from '~/types';
+import { SPECIAL_VALUES, CONFIG_PREFIXES } from '~/types';
+
+/**
+ * Local helper: traverse queue tree and apply a visitor function.
+ * Combines queue info with configured properties from configData.
+ */
+function traverseQueueTree(
+  queueInfo: QueueInfo,
+  configData: Map<string, string>,
+  visitor: (queue: QueueInfo & { configured: Record<string, string> }) => void,
+): void {
+  const configured: Record<string, string> = {};
+
+  const prefix = `${CONFIG_PREFIXES.BASE}.${queueInfo.queuePath}.`;
+  for (const [key, value] of configData.entries()) {
+    if (key.startsWith(prefix)) {
+      const property = key.substring(prefix.length);
+      configured[property] = value;
+    }
+  }
+
+  const combinedQueue = {
+    ...queueInfo,
+    configured,
+  };
+
+  visitor(combinedQueue);
+
+  if (queueInfo.queues?.queue) {
+    const children = Array.isArray(queueInfo.queues.queue)
+      ? queueInfo.queues.queue
+      : [queueInfo.queues.queue];
+
+    for (const child of children) {
+      traverseQueueTree(child, configData, visitor);
+    }
+  }
+}
 
 describe('queueDataSlice', () => {
   const createTestStore = () => {
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/queueDataSlice.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/queueDataSlice.ts
index 4ea7d3b5200..827d6a58b9b 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/queueDataSlice.ts
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/queueDataSlice.ts
@@ -22,7 +22,7 @@
  */
 
 import type { StateCreator } from 'zustand';
-import { SPECIAL_VALUES, CONFIG_PREFIXES } from '~/types';
+import { SPECIAL_VALUES } from '~/types';
 import type { QueueInfo, CapacitySchedulerInfo, QueueCapacitiesByPartition } 
from '~/types';
 import { buildGlobalPropertyKey, buildPropertyKey } from 
'~/utils/propertyUtils';
 import { globalPropertyDefinitions } from 
'~/config/properties/global-properties';
@@ -218,39 +218,3 @@ export const createQueueDataSlice: StateCreator<
     return partition || null;
   },
 });
-
-/**
- * Helper function to traverse queue tree and apply a visitor function
- */
-export function traverseQueueTree(
-  queueInfo: QueueInfo,
-  configData: Map<string, string>,
-  visitor: (queue: QueueInfo & { configured: Record<string, string> }) => void,
-): void {
-  const configured: Record<string, string> = {};
-
-  const prefix = `${CONFIG_PREFIXES.BASE}.${queueInfo.queuePath}.`;
-  for (const [key, value] of configData.entries()) {
-    if (key.startsWith(prefix)) {
-      const property = key.substring(prefix.length);
-      configured[property] = value;
-    }
-  }
-
-  const combinedQueue = {
-    ...queueInfo,
-    configured,
-  };
-
-  visitor(combinedQueue);
-
-  if (queueInfo.queues?.queue) {
-    const children = Array.isArray(queueInfo.queues.queue)
-      ? queueInfo.queues.queue
-      : [queueInfo.queues.queue];
-
-    for (const child of children) {
-      traverseQueueTree(child, configData, visitor);
-    }
-  }
-}
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/stagedChangesSlice.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/stagedChangesSlice.ts
index 9ab87c5469b..d4b8fe02912 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/stagedChangesSlice.ts
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/stagedChangesSlice.ts
@@ -67,7 +67,6 @@ export const createStagedChangesSlice: StateCreator<
 > = (set, get) => ({
   stagedChanges: [],
   applyError: null,
-  orphanedValidationErrors: [],
 
   stageQueueChange: (queuePath, property, value, validationErrors) => {
     if (!queuePath || !queuePath.startsWith(SPECIAL_VALUES.ROOT_QUEUE_NAME)) {
@@ -513,7 +512,6 @@ export const createStagedChangesSlice: StateCreator<
     set((state) => {
       if (state.stagedChanges.length > 0) {
         state.stagedChanges = [];
-        state.orphanedValidationErrors = [];
         clearMutationError(state);
       }
     });
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/types.ts
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/types.ts
index 53183007a70..e9365641517 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/types.ts
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/stores/slices/types.ts
@@ -67,8 +67,6 @@ export interface NodeLabelsSlice {
 export interface StagedChangesSlice {
   stagedChanges: StagedChange[];
   applyError: string | null;
-  orphanedValidationErrors: ValidationIssue[];
-
   stageQueueChange: (
     queuePath: string,
     property: string,


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to