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 17cc6ee2ec4 YARN-11928: Capacity Scheduler UI improvements (#8258)
17cc6ee2ec4 is described below
commit 17cc6ee2ec42d8dbb7479ace2c6942222bbbb3a8
Author: Benjamin Teke <[email protected]>
AuthorDate: Mon Feb 23 12:43:10 2026 +0100
YARN-11928: Capacity Scheduler UI improvements (#8258)
---
LICENSE-binary | 1 +
.../src/main/webapp/package-lock.json | 12 ++-
.../src/main/webapp/package.json | 1 +
.../src/main/webapp/src/app/app.css | 110 ++++++++++++++++++++-
.../src/main/webapp/src/app/routes/layout.tsx | 6 +-
.../webapp/src/components/layouts/app-sidebar.tsx | 18 ++--
.../src/components/search/SearchBar.test.tsx | 6 +-
.../webapp/src/components/search/SearchBar.tsx | 13 ++-
.../main/webapp/src/components/ui/accordion.tsx | 4 +-
.../src/main/webapp/src/components/ui/alert.tsx | 6 +-
.../src/main/webapp/src/components/ui/badge.tsx | 18 ++--
.../src/main/webapp/src/components/ui/button.tsx | 12 ++-
.../src/main/webapp/src/components/ui/card.tsx | 4 +-
.../src/main/webapp/src/components/ui/checkbox.tsx | 6 +-
.../main/webapp/src/components/ui/context-menu.tsx | 4 +-
.../src/main/webapp/src/components/ui/dialog.tsx | 6 +-
.../webapp/src/components/ui/dropdown-menu.tsx | 4 +-
.../src/main/webapp/src/components/ui/input.tsx | 5 +-
.../src/main/webapp/src/components/ui/popover.tsx | 2 +-
.../src/main/webapp/src/components/ui/progress.tsx | 4 +-
.../main/webapp/src/components/ui/scroll-area.tsx | 4 +-
.../src/main/webapp/src/components/ui/select.tsx | 2 +-
.../src/main/webapp/src/components/ui/skeleton.tsx | 6 +-
.../src/main/webapp/src/components/ui/sonner.tsx | 15 ++-
.../src/main/webapp/src/components/ui/switch.tsx | 6 +-
.../src/main/webapp/src/components/ui/table.tsx | 5 +-
.../src/main/webapp/src/components/ui/tabs.tsx | 5 +-
.../src/main/webapp/src/components/ui/tooltip.tsx | 2 +-
.../node-labels/components/NodesPanel.test.tsx | 8 +-
.../components/ValidationIssuesPopover.tsx | 7 +-
.../components/dialogs/UnsavedChangesDialog.tsx | 6 +-
.../components/QueueCapacityProgress.tsx | 23 +++--
.../components/QueueCardContextMenu.tsx | 2 +-
.../components/QueueCardNode.test.tsx | 4 +-
.../queue-management/components/QueueCardNode.tsx | 62 ++++++++----
.../components/QueueStatusBadges.tsx | 12 +++
.../components/QueueValidationBadges.tsx | 4 +-
.../components/dialogs/AddQueueDialog.test.tsx | 6 +-
.../components/dialogs/AddQueueDialog.tsx | 15 ++-
.../components/dialogs/DeleteQueueDialog.test.tsx | 24 ++++-
.../components/dialogs/DeleteQueueDialog.tsx | 29 +++++-
.../components/StagedChangesPanel.tsx | 22 +++--
42 files changed, 386 insertions(+), 125 deletions(-)
diff --git a/LICENSE-binary b/LICENSE-binary
index 7607659ce6f..3a2d1f70af6 100644
--- a/LICENSE-binary
+++ b/LICENSE-binary
@@ -440,6 +440,7 @@ atlaskit/pragmatic-drag-and-drop 1.7.4
atlaskit/pragmatic-drag-and-drop-auto-scroll 2.1.1
atlaskit/pragmatic-drag-and-drop-hitbox 1.1.0
typescript 5.8.3
+baseline-browser-mapping 2.10.0
--------------------------------------------------------------------------------
This product bundles various third-party components under other open source
licenses. This section summarizes those components and their licenses.
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/package-lock.json
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/package-lock.json
index 2b52c5a1f22..1996f07758b 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/package-lock.json
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/package-lock.json
@@ -67,6 +67,7 @@
"@vitejs/plugin-react": "^4.4.1",
"@vitest/coverage-v8": "^3.2.4",
"babel-plugin-react-compiler": "^1.0.0",
+ "baseline-browser-mapping": "^2.10.0",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.1.0",
"eslint-plugin-react-compiler": "^19.1.0-rc.2",
@@ -5250,13 +5251,16 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
- "version": "2.9.19",
- "resolved":
"https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
- "integrity":
"sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==",
+ "version": "2.10.0",
+ "resolved":
"https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
+ "integrity":
"sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==",
"dev": true,
"license": "Apache-2.0",
"bin": {
- "baseline-browser-mapping": "dist/cli.js"
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
}
},
"node_modules/basic-auth": {
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/package.json
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/package.json
index c8c3b427a2b..4c9e0cb13d1 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/package.json
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/package.json
@@ -91,6 +91,7 @@
"@vitejs/plugin-react": "^4.4.1",
"@vitest/coverage-v8": "^3.2.4",
"babel-plugin-react-compiler": "^1.0.0",
+ "baseline-browser-mapping": "^2.10.0",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.1.0",
"eslint-plugin-react-compiler": "^19.1.0-rc.2",
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/app/app.css
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/app/app.css
index 5589e3ea202..ba0def0301c 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/app/app.css
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/app/app.css
@@ -41,6 +41,7 @@ body {
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
+ --radius-2xl: calc(var(--radius) + 8px);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
@@ -81,7 +82,27 @@ body {
}
:root {
- --radius: 0.65rem;
+ /* Base radius - increased for bolder look */
+ --radius: 0.75rem;
+
+ /* Typography scale */
+ --font-display: 1.875rem;
+ --font-heading-1: 1.5rem;
+ --font-heading-2: 1.25rem;
+ --font-heading-3: 1.125rem;
+
+ /* Animation tokens */
+ --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
+ --transition-normal: 250ms cubic-bezier(0.4, 0, 0.2, 1);
+ --transition-slow: 400ms cubic-bezier(0.4, 0, 0.2, 1);
+ --spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
+
+ /* Enhanced shadows */
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 /
0.1);
+ --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 /
0.1);
+ --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 /
0.1);
+ --shadow-glow: 0 0 20px -5px var(--primary);
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0);
@@ -116,14 +137,21 @@ body {
/* Queue state colors for light mode */
--queue-new: oklch(0.648 0.2 131.684); /* Green */
- --queue-modified: oklch(0.646 0.222 41.116); /* Orange */
+ --queue-modified: oklch(0.75 0.17 70); /* Amber - clearly distinct from red
*/
--queue-deleted: oklch(0.577 0.245 27.325); /* Red */
--queue-running: oklch(0.648 0.2 131.684); /* Green */
--queue-stopped: oklch(0.577 0.245 27.325); /* Red */
- --queue-draining: oklch(0.646 0.222 41.116); /* Orange */
+ --queue-draining: oklch(0.75 0.17 70); /* Amber - clearly distinct from red
*/
}
.dark {
+ /* Dark mode shadows - softer */
+ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.2);
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.3), 0 2px 4px -2px rgb(0 0 0 /
0.2);
+ --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.35), 0 4px 6px -4px rgb(0 0 0 /
0.25);
+ --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.4), 0 8px 10px -6px rgb(0 0 0 /
0.3);
+ --shadow-glow: 0 0 25px -5px var(--primary);
+
--background: oklch(0.141 0.005 285.823);
--foreground: oklch(0.985 0 0);
--card: oklch(0.21 0.006 285.885);
@@ -165,3 +193,79 @@ body {
@apply bg-background text-foreground;
}
}
+
+/* Shimmer animation for skeleton loading */
+@keyframes shimmer {
+ 0% {
+ background-position: -200% 0;
+ }
+ 100% {
+ background-position: 200% 0;
+ }
+}
+
+.animate-shimmer {
+ background: linear-gradient(
+ 90deg,
+ transparent 0%,
+ rgba(255, 255, 255, 0.1) 50%,
+ transparent 100%
+ );
+ background-size: 200% 100%;
+ animation: shimmer 1.5s infinite;
+}
+
+.dark .animate-shimmer {
+ background: linear-gradient(
+ 90deg,
+ transparent 0%,
+ rgba(255, 255, 255, 0.05) 50%,
+ transparent 100%
+ );
+ background-size: 200% 100%;
+}
+
+/* Float animation for empty states and decorative elements */
+@keyframes float {
+ 0%,
+ 100% {
+ transform: translateY(0);
+ }
+ 50% {
+ transform: translateY(-10px);
+ }
+}
+
+.animate-float {
+ animation: float 3s ease-in-out infinite;
+}
+
+/* Subtle pulse for attention without being distracting */
+@keyframes subtle-pulse {
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.7;
+ }
+}
+
+.animate-subtle-pulse {
+ animation: subtle-pulse 2s ease-in-out infinite;
+}
+
+/* Gradient text utility */
+.text-gradient {
+ background: linear-gradient(135deg, var(--primary) 0%, var(--ring) 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+}
+
+/* Decorative background pattern for empty states */
+.empty-state-bg {
+ background-image: radial-gradient(circle at 1px 1px, var(--muted-foreground)
1px, transparent 0);
+ background-size: 24px 24px;
+ opacity: 0.1;
+}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/app/routes/layout.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/app/routes/layout.tsx
index a8587c5fb30..83ae52ce061 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/app/routes/layout.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/app/routes/layout.tsx
@@ -175,13 +175,13 @@ export default function Layout() {
{/* Main content area */}
<div className="flex-1 flex flex-col">
{/* Header with page title */}
- <header className="flex h-16 items-center gap-4 border-b px-6">
+ <header className="flex h-20 items-center gap-4 border-b
bg-gradient-to-r from-background to-muted/20 px-6">
<SidebarTrigger />
<div className="flex-1">
- <h1 className="text-xl font-semibold">{pageInfo.title}</h1>
+ <h1 className="text-2xl font-bold
tracking-tight">{pageInfo.title}</h1>
<p className="text-sm
text-muted-foreground">{pageInfo.description}</p>
</div>
- <SearchBar className="w-64" placeholder="Search" />
+ <SearchBar className="w-72" placeholder="Search" />
{isReadOnly && (
<TooltipProvider>
<Tooltip>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/layouts/app-sidebar.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/layouts/app-sidebar.tsx
index 6bad64fef07..b1ca0903ba6 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/layouts/app-sidebar.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/layouts/app-sidebar.tsx
@@ -57,22 +57,28 @@ export function AppSidebar() {
return (
<Sidebar variant="inset">
<SidebarHeader>
- <div className="flex h-14 items-center px-4">
- <h1 className="text-lg font-semibold">Capacity Scheduler UI</h1>
+ <div className="flex h-16 items-center px-4 border-b
border-sidebar-border/50">
+ <h1 className="text-lg font-bold tracking-tight bg-gradient-to-r
from-foreground to-foreground/70 bg-clip-text">
+ Capacity Scheduler UI
+ </h1>
</div>
</SidebarHeader>
- <SidebarContent>
- <SidebarMenu>
+ <SidebarContent className="px-2 pt-4">
+ <SidebarMenu className="space-y-1">
{navigation.map((item) => {
const Icon = item.icon;
const isActive = location.pathname === item.path;
return (
<SidebarMenuItem key={item.path}>
- <SidebarMenuButton asChild isActive={isActive}>
+ <SidebarMenuButton
+ asChild
+ isActive={isActive}
+ className="transition-all duration-200 hover:translate-x-0.5"
+ >
<Link to={item.path}>
<Icon className="h-4 w-4" />
- <span>{item.title}</span>
+ <span className="font-medium">{item.title}</span>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
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 3e2eaf12ba2..f32523c502c 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
@@ -269,16 +269,16 @@ describe('SearchBar', () => {
render(<SearchBar />);
expect(screen.getByText(/⌘G/)).toBeInTheDocument();
- expect(screen.getByText(/to focus/)).toBeInTheDocument();
+ expect(screen.getByText(/focus/)).toBeInTheDocument();
expect(screen.getByText(/Esc/)).toBeInTheDocument();
- expect(screen.getByText(/to clear/)).toBeInTheDocument();
+ expect(screen.getByText(/clear/)).toBeInTheDocument();
});
it('should not display keyboard shortcuts hint when not focused', () => {
render(<SearchBar />);
expect(screen.queryByText(/⌘G/)).not.toBeInTheDocument();
- expect(screen.queryByText(/to focus/)).not.toBeInTheDocument();
+ expect(screen.queryByText(/focus/)).not.toBeInTheDocument();
});
});
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 60e3d1ae450..a019639026d 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
@@ -121,8 +121,9 @@ export const SearchBar: React.FC<SearchBarProps> = ({
placeholder = 'Search...',
<div className="relative">
<Search
className={cn(
- 'absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2
text-muted-foreground transition-all duration-200',
- isSearching && 'animate-pulse',
+ 'absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2
text-muted-foreground transition-all duration-300',
+ isSearching && 'animate-pulse text-primary',
+ isSearchFocused && 'text-primary scale-110',
)}
/>
<Input
@@ -158,9 +159,11 @@ export const SearchBar: React.FC<SearchBarProps> = ({
placeholder = 'Search...',
</div>
{isSearchFocused && (
- <div className="absolute right-0 top-full mt-1 text-xs
text-muted-foreground z-50 bg-background p-1 rounded shadow-sm
transition-opacity duration-200">
- <kbd className="rounded border px-1">⌘G</kbd> to focus •
- <kbd className="rounded border px-1 ml-1">Esc</kbd> to clear
+ <div className="absolute right-0 top-full mt-2 text-xs
text-muted-foreground z-50 bg-popover/95 backdrop-blur-sm p-2 rounded-lg
shadow-lg border transition-all duration-200 animate-in fade-in-0
slide-in-from-top-1">
+ <kbd className="rounded-md border bg-muted px-1.5 py-0.5 font-mono
text-[10px]">⌘G</kbd>
+ <span className="mx-1.5">focus</span>
+ <kbd className="rounded-md border bg-muted px-1.5 py-0.5 font-mono
text-[10px]">Esc</kbd>
+ <span className="ml-1.5">clear</span>
</div>
)}
</div>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/accordion.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/accordion.tsx
index 5215a8fba28..550816cff57 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/accordion.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/accordion.tsx
@@ -46,13 +46,13 @@ function AccordionTrigger({
<AccordionPrimitive.Trigger
data-slot="accordion-trigger"
className={cn(
- 'focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1
items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium
transition-all outline-none hover:underline focus-visible:ring-[3px]
disabled:pointer-events-none disabled:opacity-50
[&[data-state=open]>svg]:rotate-180',
+ 'focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1
items-start justify-between gap-4 rounded-lg py-4 text-left text-sm
font-semibold transition-all duration-200 outline-none hover:bg-muted/50
focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50
[&[data-state=open]>svg]:rotate-180',
className,
)}
{...props}
>
{children}
- <ChevronDownIcon className="text-muted-foreground pointer-events-none
size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
+ <ChevronDownIcon className="text-muted-foreground pointer-events-none
size-4 shrink-0 translate-y-0.5 transition-transform duration-300 ease-out" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/alert.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/alert.tsx
index 4e709ee15ec..13d36ca1256 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/alert.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/alert.tsx
@@ -23,13 +23,13 @@ import { cva, type VariantProps } from
'class-variance-authority';
import { cn } from '~/utils/cn';
const alertVariants = cva(
- 'relative w-full rounded-lg border px-4 py-3 text-sm grid
has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr]
has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5
[&>svg]:text-current',
+ 'relative w-full rounded-lg border px-4 py-3 text-sm grid
has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr]
has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5
[&>svg]:text-current shadow-sm',
{
variants: {
variant: {
- default: 'bg-card text-card-foreground',
+ default: 'bg-card text-card-foreground border-l-4 border-l-primary',
destructive:
- 'text-destructive bg-card [&>svg]:text-current
*:data-[slot=alert-description]:text-destructive/90',
+ 'text-destructive bg-gradient-to-r from-destructive/5 to-card
border-l-4 border-l-destructive [&>svg]:text-current
*:data-[slot=alert-description]:text-destructive/90',
secondary: 'bg-secondary text-secondary-foreground border-transparent',
},
},
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/badge.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/badge.tsx
index 64d7f4bd931..0b473ad197e 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/badge.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/badge.tsx
@@ -24,18 +24,22 @@ import { cva, type VariantProps } from
'class-variance-authority';
import { cn } from '~/utils/cn';
const badgeVariants = cva(
- 'inline-flex items-center justify-center rounded-md border px-2 py-0.5
text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1
[&>svg]:pointer-events-none focus-visible:border-ring
focus-visible:ring-ring/50 focus-visible:ring-[3px]
aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden',
+ 'inline-flex items-center justify-center rounded-md border px-2 py-0.5
text-xs font-semibold w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1
[&>svg]:pointer-events-none focus-visible:border-ring
focus-visible:ring-ring/50 focus-visible:ring-[3px]
aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
aria-invalid:border-destructive transition-all duration-200 overflow-hidden
shadow-sm',
{
variants: {
variant: {
- default: 'border-transparent bg-primary text-primary-foreground
[a&]:hover:bg-primary/90',
+ default:
+ 'border-transparent bg-gradient-to-r from-primary to-primary/85
text-primary-foreground [a&]:hover:from-primary/95 [a&]:hover:to-primary/80',
secondary:
- 'border-transparent bg-secondary text-secondary-foreground
[a&]:hover:bg-secondary/90',
+ 'border-transparent bg-secondary text-secondary-foreground
[a&]:hover:bg-secondary/80',
destructive:
- 'border-transparent bg-destructive text-white
[a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20
dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
- outline: 'text-foreground [a&]:hover:bg-accent
[a&]:hover:text-accent-foreground',
- success: 'border-transparent bg-queue-running text-white
[a&]:hover:bg-queue-running/90',
- warning: 'border-transparent bg-queue-draining text-white
[a&]:hover:bg-queue-draining/90',
+ 'border-transparent bg-gradient-to-r from-destructive
to-destructive/85 text-white [a&]:hover:from-destructive/95
[a&]:hover:to-destructive/80 focus-visible:ring-destructive/20
dark:focus-visible:ring-destructive/40 dark:from-destructive/70
dark:to-destructive/55',
+ outline:
+ 'text-foreground [a&]:hover:bg-accent
[a&]:hover:text-accent-foreground shadow-none',
+ success:
+ 'border-transparent bg-gradient-to-r from-queue-running
to-queue-running/85 text-white [a&]:hover:from-queue-running/95
[a&]:hover:to-queue-running/80',
+ warning:
+ 'border-transparent bg-gradient-to-r from-queue-draining
to-queue-draining/85 text-white [a&]:hover:from-queue-draining/95
[a&]:hover:to-queue-draining/80',
},
},
defaultVariants: {
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/button.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/button.tsx
index b4686ec9e63..17f4252e990 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/button.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/button.tsx
@@ -24,16 +24,18 @@ import { cva, type VariantProps } from
'class-variance-authority';
import { cn } from '~/utils/cn';
const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md
text-sm font-medium transition-all disabled:pointer-events-none
disabled:opacity-50 [&_svg]:pointer-events-none
[&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none
focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]
aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
aria-invalid:border-destructive",
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md
text-sm font-medium transition-all duration-200 disabled:pointer-events-none
disabled:opacity-50 [&_svg]:pointer-events-none
[&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none
focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]
aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
aria-invalid:border-destructive active:scale-[0.98]",
{
variants: {
variant: {
- default: 'bg-primary text-primary-foreground shadow-xs
hover:bg-primary/90',
+ default:
+ 'bg-gradient-to-r from-primary to-primary/85 text-primary-foreground
shadow-md hover:shadow-lg hover:shadow-primary/25 hover:from-primary/95
hover:to-primary/80',
destructive:
- 'bg-destructive text-white shadow-xs hover:bg-destructive/90
focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40
dark:bg-destructive/60',
+ 'bg-gradient-to-r from-destructive to-destructive/85 text-white
shadow-md hover:shadow-lg hover:shadow-destructive/25 hover:from-destructive/95
hover:to-destructive/80 focus-visible:ring-destructive/20
dark:focus-visible:ring-destructive/40 dark:from-destructive/70
dark:to-destructive/55',
outline:
- 'border bg-background shadow-xs hover:bg-accent
hover:text-accent-foreground dark:bg-input/30 dark:border-input
dark:hover:bg-input/50',
- secondary: 'bg-secondary text-secondary-foreground shadow-xs
hover:bg-secondary/80',
+ 'border bg-background shadow-sm hover:bg-accent
hover:text-accent-foreground hover:shadow-md dark:bg-input/30 dark:border-input
dark:hover:bg-input/50',
+ secondary:
+ 'bg-secondary text-secondary-foreground shadow-sm
hover:bg-secondary/80 hover:shadow-md',
ghost: 'hover:bg-accent hover:text-accent-foreground
dark:hover:bg-accent/50',
link: 'text-primary underline-offset-4 hover:underline',
},
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/card.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/card.tsx
index 6ae89a77022..bef88e33bf2 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/card.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/card.tsx
@@ -26,7 +26,7 @@ function Card({ className, ...props }:
React.ComponentProps<'div'>) {
<div
data-slot="card"
className={cn(
- 'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border
py-6 shadow-sm',
+ 'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border
py-6 shadow-md transition-all duration-200 hover:shadow-lg',
className,
)}
{...props}
@@ -51,7 +51,7 @@ function CardTitle({ className, ...props }:
React.ComponentProps<'div'>) {
return (
<div
data-slot="card-title"
- className={cn('leading-none font-semibold', className)}
+ className={cn('leading-none font-semibold tracking-tight', className)}
{...props}
/>
);
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/checkbox.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/checkbox.tsx
index 52d80d2bd7a..3d4807cf687 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/checkbox.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/checkbox.tsx
@@ -28,14 +28,16 @@ function Checkbox({ className, ...props }:
React.ComponentProps<typeof CheckboxP
<CheckboxPrimitive.Root
data-slot="checkbox"
className={cn(
- 'peer border-input dark:bg-input/30 data-[state=checked]:bg-primary
data-[state=checked]:text-primary-foreground
dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary
focus-visible:border-ring focus-visible:ring-ring/50
aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs
transition-shadow outline-none focus-visible:ring-[3px]
disabled:cursor-not-allowed disabled:op [...]
+ 'peer border-input dark:bg-input/30 data-[state=checked]:bg-primary
data-[state=checked]:text-primary-foreground
dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary
focus-visible:border-ring focus-visible:ring-ring/50
aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40
aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-sm
transition-all duration-200 outline-none focus-visible:ring-[3px]
disabled:cursor-not-allowed d [...]
+ 'data-[state=checked]:shadow-md data-[state=checked]:shadow-primary/25
data-[state=checked]:scale-105',
+ 'hover:border-ring/50',
className,
)}
{...props}
>
<CheckboxPrimitive.Indicator
data-slot="checkbox-indicator"
- className="flex items-center justify-center text-current
transition-none"
+ className="flex items-center justify-center text-current animate-in
zoom-in-50 duration-150"
>
<CheckIcon className="size-3.5" />
</CheckboxPrimitive.Indicator>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/context-menu.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/context-menu.tsx
index 2bcd99583bd..68ad8854e3a 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/context-menu.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/context-menu.tsx
@@ -100,7 +100,7 @@ function ContextMenuContent({
<ContextMenuPrimitive.Content
data-slot="context-menu-content"
className={cn(
- 'bg-popover text-popover-foreground data-[state=open]:animate-in
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2
data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2
data-[side=top]:slide-in-from-bottom-2 z-50
max-h-(--radix-context-menu-content-available-height) min-w-[8rem]
origin-(--radix-context-menu-content- [...]
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2
data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2
data-[side=top]:slide-in-from-bottom-2 z-50
max-h-(--radix-context-menu-content-available-height) min-w-[8rem]
origin-(--radix-context-menu-content- [...]
className,
)}
{...props}
@@ -124,7 +124,7 @@ function ContextMenuItem({
data-inset={inset}
data-variant={variant}
className={cn(
- "focus:bg-accent focus:text-accent-foreground
data-[variant=destructive]:text-destructive
data-[variant=destructive]:focus:bg-destructive/10
dark:data-[variant=destructive]:focus:bg-destructive/20
data-[variant=destructive]:focus:text-destructive
data-[variant=destructive]:*:[svg]:!text-destructive
[&_svg:not([class*='text-'])]:text-muted-foreground relative flex
cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden
select-none data-[disabled]:pointer-ev [...]
+ "focus:bg-accent focus:text-accent-foreground
data-[variant=destructive]:text-destructive
data-[variant=destructive]:focus:bg-destructive/10
dark:data-[variant=destructive]:focus:bg-destructive/20
data-[variant=destructive]:focus:text-destructive
data-[variant=destructive]:*:[svg]:!text-destructive
[&_svg:not([class*='text-'])]:text-muted-foreground relative flex
cursor-default items-center gap-2 rounded-lg px-2 py-1.5 text-sm outline-hidden
select-none transition-colors duration [...]
className,
)}
{...props}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/dialog.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/dialog.tsx
index cac45ca1069..7057fbdde76 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/dialog.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/dialog.tsx
@@ -49,7 +49,7 @@ function DialogOverlay({
<DialogPrimitive.Overlay
data-slot="dialog-overlay"
className={cn(
- 'data-[state=open]:animate-in data-[state=closed]:animate-out
data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50
bg-black/50',
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out
data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50
bg-black/60 backdrop-blur-sm',
className,
)}
{...props}
@@ -71,7 +71,7 @@ function DialogContent({
<DialogPrimitive.Content
data-slot="dialog-content"
className={cn(
- 'bg-background data-[state=open]:animate-in
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full
max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg
border p-6 shadow-lg duration-200 sm:max-w-lg',
+ 'bg-background data-[state=open]:animate-in
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-top-[2%]
data-[state=open]:slide-in-from-top-[2%] fixed top-[50%] left-[50%] z-50 grid
w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4
rounded-xl border p-6 shadow-xl duration-300 sm:max-w-lg',
className,
)}
{...props}
@@ -115,7 +115,7 @@ function DialogTitle({ className, ...props }:
React.ComponentProps<typeof Dialog
return (
<DialogPrimitive.Title
data-slot="dialog-title"
- className={cn('text-lg leading-none font-semibold', className)}
+ className={cn('text-lg leading-none font-semibold tracking-tight',
className)}
{...props}
/>
);
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/dropdown-menu.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/dropdown-menu.tsx
index 461a3ddeb19..e0cd861e0c1 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/dropdown-menu.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/dropdown-menu.tsx
@@ -52,7 +52,7 @@ function DropdownMenuContent({
data-slot="dropdown-menu-content"
sideOffset={sideOffset}
className={cn(
- 'bg-popover text-popover-foreground data-[state=open]:animate-in
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2
data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2
data-[side=top]:slide-in-from-bottom-2 z-50
max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem]
origin-(--radix-dropdown-menu-conten [...]
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2
data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2
data-[side=top]:slide-in-from-bottom-2 z-50
max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem]
origin-(--radix-dropdown-menu-conten [...]
className,
)}
{...props}
@@ -80,7 +80,7 @@ function DropdownMenuItem({
data-inset={inset}
data-variant={variant}
className={cn(
- "focus:bg-accent focus:text-accent-foreground
data-[variant=destructive]:text-destructive
data-[variant=destructive]:focus:bg-destructive/10
dark:data-[variant=destructive]:focus:bg-destructive/20
data-[variant=destructive]:focus:text-destructive
data-[variant=destructive]:*:[svg]:!text-destructive
[&_svg:not([class*='text-'])]:text-muted-foreground relative flex
cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden
select-none data-[disabled]:pointer-ev [...]
+ "focus:bg-accent focus:text-accent-foreground
data-[variant=destructive]:text-destructive
data-[variant=destructive]:focus:bg-destructive/10
dark:data-[variant=destructive]:focus:bg-destructive/20
data-[variant=destructive]:focus:text-destructive
data-[variant=destructive]:*:[svg]:!text-destructive
[&_svg:not([class*='text-'])]:text-muted-foreground relative flex
cursor-default items-center gap-2 rounded-lg px-2 py-1.5 text-sm outline-hidden
select-none transition-colors duration [...]
className,
)}
{...props}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/input.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/input.tsx
index cc8f9352140..5befae6b511 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/input.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/input.tsx
@@ -27,8 +27,9 @@ function Input({ className, type, ...props }:
React.ComponentProps<'input'>) {
type={type}
data-slot="input"
className={cn(
- 'file:text-foreground placeholder:text-muted-foreground
selection:bg-primary selection:text-primary-foreground dark:bg-input/30
border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1
text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex
file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium
disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50
md:text-sm',
- 'focus-visible:border-ring focus-visible:ring-ring/50
focus-visible:ring-[3px]',
+ 'file:text-foreground placeholder:text-muted-foreground
selection:bg-primary selection:text-primary-foreground dark:bg-input/30
border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1
text-base shadow-sm transition-all duration-200 outline-none file:inline-flex
file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium
disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50
md:text-sm',
+ 'hover:border-ring/50 hover:shadow-md',
+ 'focus-visible:border-ring focus-visible:ring-ring/50
focus-visible:ring-[3px] focus-visible:shadow-md focus-visible:shadow-ring/10',
'aria-invalid:ring-destructive/20
dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
className,
)}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/popover.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/popover.tsx
index b6ef8c70107..5b168adab5e 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/popover.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/popover.tsx
@@ -43,7 +43,7 @@ function PopoverContent({
align={align}
sideOffset={sideOffset}
className={cn(
- 'bg-popover text-popover-foreground data-[state=open]:animate-in
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2
data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2
data-[side=top]:slide-in-from-bottom-2 z-50 w-72
origin-(--radix-popover-content-transform-origin) rounded-md border p-4
shadow-md outline-hidden',
+ 'bg-popover text-popover-foreground data-[state=open]:animate-in
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2
data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2
data-[side=top]:slide-in-from-bottom-2 z-50 w-72
origin-(--radix-popover-content-transform-origin) rounded-xl border p-4
shadow-xl outline-hidden ba [...]
className,
)}
{...props}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/progress.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/progress.tsx
index 932e5bb4553..1b15e8869fd 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/progress.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/progress.tsx
@@ -30,12 +30,12 @@ function Progress({
return (
<ProgressPrimitive.Root
data-slot="progress"
- className={cn('bg-primary/20 relative h-2 w-full overflow-hidden
rounded-full', className)}
+ className={cn('bg-primary/20 relative h-2 w-full overflow-hidden
rounded-full shadow-inner', className)}
{...props}
>
<ProgressPrimitive.Indicator
data-slot="progress-indicator"
- className="bg-primary h-full w-full flex-1 transition-all"
+ className="bg-gradient-to-r from-primary to-primary/80 h-full w-full
flex-1 transition-all duration-500 ease-out"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/scroll-area.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/scroll-area.tsx
index 9fc4fe5269e..6398ba88e67 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/scroll-area.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/scroll-area.tsx
@@ -55,7 +55,7 @@ function ScrollBar({
data-slot="scroll-area-scrollbar"
orientation={orientation}
className={cn(
- 'flex touch-none p-px transition-colors select-none',
+ 'flex touch-none p-px transition-all duration-200 select-none
hover:bg-muted/30',
orientation === 'vertical' && 'h-full w-2.5 border-l
border-l-transparent',
orientation === 'horizontal' && 'h-2.5 flex-col border-t
border-t-transparent',
className,
@@ -64,7 +64,7 @@ function ScrollBar({
>
<ScrollAreaPrimitive.ScrollAreaThumb
data-slot="scroll-area-thumb"
- className="bg-border relative flex-1 rounded-full"
+ className="bg-border hover:bg-muted-foreground/50 relative flex-1
rounded-full transition-colors duration-200"
/>
</ScrollAreaPrimitive.ScrollAreaScrollbar>
);
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/select.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/select.tsx
index cc2ab614e1e..9d2cae5d1f1 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/select.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/select.tsx
@@ -115,7 +115,7 @@ function SelectItem({
<SelectPrimitive.Item
data-slot="select-item"
className={cn(
- "focus:bg-accent focus:text-accent-foreground
[&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full
cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm
outline-hidden select-none data-[disabled]:pointer-events-none
data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0
[&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex
*:[span]:last:items-center *:[span]:last:gap-2",
+ "focus:bg-accent focus:text-accent-foreground
[&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full
cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-sm
outline-hidden select-none transition-colors duration-150
data-[disabled]:pointer-events-none data-[disabled]:opacity-50
[&_svg]:pointer-events-none [&_svg]:shrink-0
[&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex
*:[span]:last:items-center *:[span]:last:gap-2",
className,
)}
{...props}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/skeleton.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/skeleton.tsx
index 2ecbbdc2c4b..37334250ff7 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/skeleton.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/skeleton.tsx
@@ -23,7 +23,11 @@ function Skeleton({ className, ...props }:
React.ComponentProps<'div'>) {
return (
<div
data-slot="skeleton"
- className={cn('bg-accent animate-pulse rounded-md', className)}
+ className={cn(
+ 'bg-muted/60 rounded-md relative overflow-hidden',
+ 'after:absolute after:inset-0 after:animate-shimmer',
+ className,
+ )}
{...props}
/>
);
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/sonner.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/sonner.tsx
index fa988b5dd22..b8f4ef78e1e 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/sonner.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/sonner.tsx
@@ -27,10 +27,19 @@ export function Toaster() {
toastOptions={{
classNames: {
toast:
- 'group toast group-[.toaster]:bg-background
group-[.toaster]:text-foreground group-[.toaster]:border-border
group-[.toaster]:shadow-lg',
+ 'group toast group-[.toaster]:bg-background
group-[.toaster]:text-foreground group-[.toaster]:border-border
group-[.toaster]:shadow-xl group-[.toaster]:rounded-xl',
description: 'group-[.toast]:text-muted-foreground',
- actionButton: 'group-[.toast]:bg-primary
group-[.toast]:text-primary-foreground',
- cancelButton: 'group-[.toast]:bg-muted
group-[.toast]:text-muted-foreground',
+ actionButton:
+ 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground
group-[.toast]:shadow-md group-[.toast]:font-medium',
+ cancelButton:
+ 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground
group-[.toast]:font-medium',
+ success:
+ 'group-[.toaster]:border-l-4 group-[.toaster]:border-l-green-500
group-[.toaster]:bg-gradient-to-r group-[.toaster]:from-green-50
group-[.toaster]:to-background dark:group-[.toaster]:from-green-950/30',
+ error:
+ 'group-[.toaster]:border-l-4 group-[.toaster]:border-l-destructive
group-[.toaster]:bg-gradient-to-r group-[.toaster]:from-red-50
group-[.toaster]:to-background dark:group-[.toaster]:from-red-950/30',
+ warning:
+ 'group-[.toaster]:border-l-4 group-[.toaster]:border-l-amber-500
group-[.toaster]:bg-gradient-to-r group-[.toaster]:from-amber-50
group-[.toaster]:to-background dark:group-[.toaster]:from-amber-950/30',
+ info: 'group-[.toaster]:border-l-4
group-[.toaster]:border-l-blue-500 group-[.toaster]:bg-gradient-to-r
group-[.toaster]:from-blue-50 group-[.toaster]:to-background
dark:group-[.toaster]:from-blue-950/30',
},
}}
/>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/switch.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/switch.tsx
index 143d2131b06..9acceef0ebc 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/switch.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/switch.tsx
@@ -27,7 +27,8 @@ function Switch({ className, ...props }:
React.ComponentProps<typeof SwitchPrimi
<SwitchPrimitive.Root
data-slot="switch"
className={cn(
- 'peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input
focus-visible:border-ring focus-visible:ring-ring/50
dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0
items-center rounded-full border border-transparent shadow-xs transition-all
outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed
disabled:opacity-50',
+ 'peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input
focus-visible:border-ring focus-visible:ring-ring/50
dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0
items-center rounded-full border border-transparent shadow-sm transition-all
duration-200 outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed
disabled:opacity-50',
+ 'data-[state=checked]:shadow-md
data-[state=checked]:shadow-primary/25',
className,
)}
{...props}
@@ -35,7 +36,8 @@ function Switch({ className, ...props }:
React.ComponentProps<typeof SwitchPrimi
<SwitchPrimitive.Thumb
data-slot="switch-thumb"
className={cn(
- 'bg-background dark:data-[state=unchecked]:bg-foreground
dark:data-[state=checked]:bg-primary-foreground pointer-events-none block
size-4 rounded-full ring-0 transition-transform
data-[state=checked]:translate-x-[calc(100%-2px)]
data-[state=unchecked]:translate-x-0',
+ 'bg-background dark:data-[state=unchecked]:bg-foreground
dark:data-[state=checked]:bg-primary-foreground pointer-events-none block
size-4 rounded-full ring-0 shadow-sm transition-all duration-200
data-[state=checked]:translate-x-[calc(100%-2px)]
data-[state=unchecked]:translate-x-0',
+ 'data-[state=checked]:shadow-md',
)}
/>
</SwitchPrimitive.Root>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/table.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/table.tsx
index be2efa60eef..f2577ed8979 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/table.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/table.tsx
@@ -62,7 +62,8 @@ function TableRow({ className, ...props }:
React.ComponentProps<'tr'>) {
<tr
data-slot="table-row"
className={cn(
- 'hover:bg-muted/50 data-[state=selected]:bg-muted border-b
transition-colors',
+ 'hover:bg-muted/50 data-[state=selected]:bg-muted border-b
transition-all duration-150',
+ 'odd:bg-muted/20',
className,
)}
{...props}
@@ -75,7 +76,7 @@ function TableHead({ className, ...props }:
React.ComponentProps<'th'>) {
<th
data-slot="table-head"
className={cn(
- 'text-foreground h-10 px-2 text-left align-middle font-medium
whitespace-nowrap [&:has([role=checkbox])]:pr-0
[&>[role=checkbox]]:translate-y-[2px]',
+ 'text-foreground h-11 px-2 text-left align-middle font-semibold
text-sm tracking-tight whitespace-nowrap bg-muted/30
[&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',
className,
)}
{...props}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/tabs.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/tabs.tsx
index 1714bcb8515..1f4965e553f 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/tabs.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/tabs.tsx
@@ -37,7 +37,7 @@ function TabsList({ className, ...props }:
React.ComponentProps<typeof TabsPrimi
<TabsPrimitive.List
data-slot="tabs-list"
className={cn(
- 'bg-muted text-muted-foreground inline-flex h-9 w-fit items-center
justify-center rounded-lg p-[3px]',
+ 'bg-muted text-muted-foreground inline-flex h-10 w-fit items-center
justify-center rounded-xl p-1 shadow-inner',
className,
)}
{...props}
@@ -50,7 +50,8 @@ function TabsTrigger({ className, ...props }:
React.ComponentProps<typeof TabsPr
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
- "data-[state=active]:bg-background
dark:data-[state=active]:text-foreground focus-visible:border-ring
focus-visible:ring-ring/50 focus-visible:outline-ring
dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30
text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)]
flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent
px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow]
focus-visible:ring-[3 [...]
+ "data-[state=active]:bg-background
dark:data-[state=active]:text-foreground focus-visible:border-ring
focus-visible:ring-ring/50 focus-visible:outline-ring
dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30
text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-2px)]
flex-1 items-center justify-center gap-1.5 rounded-lg border border-transparent
px-3 py-1.5 text-sm font-medium whitespace-nowrap transition-all duration-200
focus-visible:ring-[3 [...]
+ 'hover:text-foreground',
className,
)}
{...props}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/tooltip.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/tooltip.tsx
index 0f6e3f3f4be..eecaaa79a8c 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/tooltip.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/components/ui/tooltip.tsx
@@ -59,7 +59,7 @@ function TooltipContent({
data-slot="tooltip-content"
sideOffset={sideOffset}
className={cn(
- 'bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2
data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2
data-[side=top]:slide-in-from-bottom-2 z-50 w-fit
origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5
text-xs text-balance',
+ 'bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2
data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2
data-[side=top]:slide-in-from-bottom-2 z-50 w-fit
origin-(--radix-tooltip-content-transform-origin) rounded-lg px-3 py-1.5
text-xs text-balance shadow-lg',
className,
)}
{...props}
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 5ee7eac8741..495d356b8f8 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
@@ -266,8 +266,9 @@ describe('NodesPanel', () => {
const shutdownBadge = screen.getByText('SHUTDOWN');
expect(runningBadge).toHaveAttribute('data-slot', 'badge');
- expect(runningBadge.className).toContain('bg-primary');
- expect(unhealthyBadge.className).toContain('bg-destructive');
+ // Badges use gradient styling
+ expect(runningBadge.className).toContain('from-primary');
+ expect(unhealthyBadge.className).toContain('from-destructive');
expect(shutdownBadge.className).toContain('bg-secondary');
});
@@ -435,7 +436,8 @@ describe('NodesPanel', () => {
expect(gpuBadgeText).toBeDefined();
const gpuBadge = gpuBadgeText!.closest('[data-slot="badge"]');
- expect(gpuBadge).toHaveClass('bg-primary');
+ // Badge uses gradient styling
+ expect(gpuBadge).toHaveClass('from-primary');
});
});
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/ValidationIssuesPopover.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/ValidationIssuesPopover.tsx
index d22de96a6bd..fa18ee5d170 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/ValidationIssuesPopover.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/ValidationIssuesPopover.tsx
@@ -72,6 +72,7 @@ export const ValidationIssuesPopover:
React.FC<ValidationIssuesPopoverProps> = (
size="sm"
variant={errorIssues.length ? 'destructive' : 'secondary'}
className="h-6 px-2 gap-1"
+ aria-label={`View validation issues: ${summaryLabel}`}
>
{errorIssues.length > 0 ? (
<AlertCircle className="h-3.5 w-3.5" />
@@ -93,8 +94,9 @@ export const ValidationIssuesPopover:
React.FC<ValidationIssuesPopoverProps> = (
key={issue.key}
className="w-full text-left text-xs px-2 py-1 rounded-md
hover:bg-muted flex items-start gap-2"
onClick={() => onIssueSelect(issue.field)}
+ aria-label={`Navigate to error: ${issue.field} -
${issue.message}`}
>
- <span className="mt-1 h-2 w-2 rounded-full bg-destructive
flex-shrink-0" />
+ <span aria-hidden="true" className="mt-1 h-2 w-2
rounded-full bg-destructive flex-shrink-0" />
<span>
<span className="font-medium">{issue.field}</span>
<span className="block
text-muted-foreground">{issue.message}</span>
@@ -113,8 +115,9 @@ export const ValidationIssuesPopover:
React.FC<ValidationIssuesPopoverProps> = (
key={issue.key}
className="w-full text-left text-xs px-2 py-1 rounded-md
hover:bg-muted flex items-start gap-2"
onClick={() => onIssueSelect(issue.field)}
+ aria-label={`Navigate to warning: ${issue.field} -
${issue.message}`}
>
- <span className="mt-1 h-2 w-2 rounded-full bg-amber-500
flex-shrink-0" />
+ <span aria-hidden="true" className="mt-1 h-2 w-2
rounded-full bg-amber-500 flex-shrink-0" />
<span>
<span className="font-medium">{issue.field}</span>
<span className="block
text-muted-foreground">{issue.message}</span>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/dialogs/UnsavedChangesDialog.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/dialogs/UnsavedChangesDialog.tsx
index 9a3bf7c8fbd..bd4e4995a1c 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/dialogs/UnsavedChangesDialog.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/property-editor/components/dialogs/UnsavedChangesDialog.tsx
@@ -57,12 +57,12 @@ export const UnsavedChangesDialog:
React.FC<UnsavedChangesDialogProps> = ({
</DialogDescription>
</DialogHeader>
<DialogFooter className="gap-2">
- <Button variant="outline" onClick={onDiscard} disabled={isSaving}>
- Discard Changes
- </Button>
<Button variant="outline" onClick={() => onOpenChange(false)}
disabled={isSaving}>
Cancel
</Button>
+ <Button variant="destructive" onClick={onDiscard}
disabled={isSaving}>
+ Discard Changes
+ </Button>
<Button onClick={onSave} disabled={isSaving}>
{isSaving ? (
<>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCapacityProgress.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCapacityProgress.tsx
index 103a7ab8750..f976413ca44 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCapacityProgress.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCapacityProgress.tsx
@@ -41,11 +41,17 @@ export const QueueCapacityProgress:
React.FC<QueueCapacityProgressProps> = ({
}) => {
const getUsageColor = (used: number): string => {
if (capacity === 0) return 'bg-muted-foreground/30';
- if (used >= 90) return 'bg-destructive';
- if (used >= 75) return 'bg-orange-500';
- if (used >= 50) return 'bg-yellow-500';
- if (used > 0) return 'bg-green-500';
- return 'bg-green-600';
+ if (used >= 90) return 'bg-gradient-to-r from-destructive to-red-400';
+ if (used >= 75) return 'bg-gradient-to-r from-orange-500 to-orange-400';
+ if (used >= 50) return 'bg-gradient-to-r from-yellow-500 to-yellow-400';
+ if (used > 0) return 'bg-gradient-to-r from-green-500 to-emerald-400';
+ return 'bg-gradient-to-r from-green-600 to-green-500';
+ };
+
+ const getGlowClass = (used: number): string => {
+ if (used >= 90) return 'shadow-[0_0_8px_-2px] shadow-destructive/50';
+ if (used >= 75) return 'shadow-[0_0_6px_-2px] shadow-orange-500/40';
+ return '';
};
const showCapacityMarker = capacity > 5 && capacity < 95;
@@ -61,18 +67,19 @@ export const QueueCapacityProgress:
React.FC<QueueCapacityProgressProps> = ({
</div>
)}
- <div className="relative h-4 bg-secondary rounded-full overflow-visible
mt-1">
+ <div className="relative h-4 bg-secondary rounded-full overflow-visible
mt-1 shadow-inner">
{/* Capacity bar (semi-transparent) */}
<div
- className="absolute h-full bg-primary/30 rounded-full transition-all
duration-300"
+ className="absolute h-full bg-gradient-to-r from-primary/25
to-primary/20 rounded-full transition-all duration-500 ease-out"
style={{ width: `${capacity}%` }}
/>
{/* Usage bar (solid color based on usage level) */}
<div
className={cn(
- 'absolute h-full rounded-full transition-all duration-300',
+ 'absolute h-full rounded-full transition-all duration-500
ease-out',
getUsageColor(usedCapacity),
+ getGlowClass(usedCapacity),
)}
style={{ width: `${usedCapacity}%` }}
/>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardContextMenu.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardContextMenu.tsx
index 071d687f914..14632afd744 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardContextMenu.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardContextMenu.tsx
@@ -93,7 +93,7 @@ export const QueueCardContextMenu:
React.FC<QueueCardContextMenuProps> = ({
};
const contextMenuContent = (
- <ContextMenuContent className="w-48">
+ <ContextMenuContent className="w-48" aria-label={`Queue options for
${queuePath}`}>
<ContextMenuItem
onClick={(e) => {
e.stopPropagation();
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.test.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.test.tsx
index 03d1a12c4f8..016dd5f1eb3 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.test.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueCardNode.test.tsx
@@ -487,7 +487,9 @@ describe('QueueCardNode', () => {
const card = screen.getByText('default').closest('.relative');
if (!card) throw new Error('Card not found');
- expect(card).toHaveClass('bg-blue-200');
+ // Selected state uses gradient background and subtle scale
+ expect(card).toHaveClass('scale-[1.01]');
+ expect(card).toHaveClass('ring-primary');
});
it('should show comparison state when queue is in comparison', () => {
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 8683c9db1fa..30eb6dcc0f8 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
@@ -200,28 +200,56 @@ export const QueueCardNode: React.FC<NodeProps> = ({ data
}) => {
const cardContent = (
<Card
className={cn(
- 'relative transition-all duration-200 flex flex-col',
- // Enhanced background and border for better contrast
- 'bg-gray-50 dark:bg-gray-900 border-gray-300 dark:border-gray-700',
+ '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
bg-amber-50/70 dark:bg-amber-900/30',
- // Shadow for depth - stronger in light mode
- 'shadow-lg hover:shadow-xl dark:shadow-md dark:hover:shadow-lg',
+ '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
- stagedStatus === 'new' && 'ring-2 ring-queue-new',
- stagedStatus === 'deleted' && 'ring-2 ring-queue-deleted',
- stagedStatus === 'modified' && 'ring-2 ring-queue-modified',
- !stagedStatus && isSelectedQueue && 'ring-2 ring-primary',
- // Validation error styling
+ // 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',
- isAffectedByErrors && !validationErrors && 'ring-2 ring-amber-500',
+ // 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 && 'bg-blue-200 dark:bg-gray-800',
- isSelectedForComparison && !isSelectedQueue && 'bg-gray-200
dark:bg-gray-700',
+ 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',
@@ -304,14 +332,14 @@ export const QueueCardNode: React.FC<NodeProps> = ({ data
}) => {
/>
) : (
<>
- <div className="flex items-baseline gap-1">
- <span className="text-2xl font-bold">
+ <div className="flex items-baseline gap-1.5">
+ <span className="text-2xl font-bold tracking-tight">
{parsedCapacityDisplay.type === 'percentage' ||
parsedCapacityDisplay.type === 'weight'
? parsedCapacityDisplay.formatted
: 'N/A'}
</span>
- <span className="text-sm
text-muted-foreground">capacity</span>
+ <span className="text-sm text-muted-foreground
font-medium">capacity</span>
</div>
<div className="text-xs text-muted-foreground">
Maximum capacity:{' '}
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueStatusBadges.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueStatusBadges.tsx
index dcc836f19f2..056da07684e 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueStatusBadges.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueStatusBadges.tsx
@@ -126,6 +126,13 @@ export const QueueStatusBadges:
React.FC<QueueStatusBadgesProps> = ({
'min-w-[28px] justify-center',
getCapacityModeBadgeClass(),
)}
+ aria-label={
+ capacityMode === 'weight'
+ ? 'Weight-based capacity'
+ : capacityMode === 'absolute'
+ ? 'Absolute capacity'
+ : 'Percentage capacity'
+ }
>
{getCapacityModeIcon()}
</Badge>
@@ -145,6 +152,7 @@ export const QueueStatusBadges:
React.FC<QueueStatusBadgesProps> = ({
<Badge
variant={getStateVariant()}
className={cn(baseIconBadgeClasses, 'min-w-[28px] justify-center')}
+ aria-label={`Queue is ${state.toLowerCase()}`}
>
{getStateIcon(state)}
</Badge>
@@ -162,6 +170,7 @@ export const QueueStatusBadges:
React.FC<QueueStatusBadgesProps> = ({
baseIconBadgeClasses,
'flex items-center gap-1 text-queue-modified
border-queue-modified/30',
)}
+ aria-label={`Will change to ${stagedState.toLowerCase()}`}
>
<ArrowRight className="w-4 h-4" />
{getStateIcon(stagedState)}
@@ -184,6 +193,7 @@ export const QueueStatusBadges:
React.FC<QueueStatusBadgesProps> = ({
? 'text-queue-running border-queue-running/30'
: 'text-queue-modified border-queue-modified/30',
)}
+ aria-label={`${autoCreationStatus.status === 'flexible' ?
'Flexible auto-queue creation' : 'Legacy auto-queue
creation'}${autoCreationStatus.isStaged ? ' (staged)' : ''}`}
>
{autoCreationStatus.status === 'flexible' ? (
<Sparkles className="w-4 h-4" />
@@ -247,6 +257,7 @@ export const QueueStatusBadges:
React.FC<QueueStatusBadgesProps> = ({
? 'text-queue-modified border-queue-modified/30'
: 'text-queue-deleted border-queue-deleted/30',
)}
+ aria-label={`Queue ${stagedStatus === 'new' ? 'will be created'
: stagedStatus === 'modified' ? 'has modifications' : 'will be deleted'}`}
>
{getModificationIcon()}
</Badge>
@@ -269,6 +280,7 @@ export const QueueStatusBadges:
React.FC<QueueStatusBadgesProps> = ({
<Badge
variant="outline"
className={cn(baseIconBadgeClasses, 'flex items-center gap-1
text-sm')}
+ aria-label={`Showing capacity for partition: ${labelInfo.label}`}
>
<Tag className="w-4 h-4" />
<span className="text-xs">{labelInfo.label}</span>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueValidationBadges.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueValidationBadges.tsx
index f4707ea25e0..e4431ab41f7 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueValidationBadges.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/QueueValidationBadges.tsx
@@ -56,7 +56,7 @@ export const QueueValidationBadges:
React.FC<QueueValidationBadgesProps> = ({
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
- <Badge variant="destructive" className="h-6 px-2">
+ <Badge variant="destructive" className="h-6 px-2"
aria-label={`${errors.length} validation error${errors.length === 1 ? '' :
's'}`}>
<AlertCircle className="h-3 w-3 mr-1" />
{errors.length}
</Badge>
@@ -81,6 +81,7 @@ export const QueueValidationBadges:
React.FC<QueueValidationBadgesProps> = ({
<Badge
variant="outline"
className="h-6 px-2 border-amber-500 text-amber-600
dark:text-amber-400 bg-amber-50 dark:bg-amber-950/30"
+ aria-label={`${warnings.length} validation
warning${warnings.length === 1 ? '' : 's'}`}
>
<AlertTriangle className="h-3 w-3 mr-1" />
{warnings.length}
@@ -106,6 +107,7 @@ export const QueueValidationBadges:
React.FC<QueueValidationBadgesProps> = ({
<Badge
variant="outline"
className="h-6 px-2 border-orange-500 text-orange-600
dark:text-orange-400 bg-orange-50 dark:bg-orange-950/30"
+ aria-label={`Affected by validation issues from
${errorSource ? `queue "${errorSource}"` : 'child queues'}`}
>
<AlertTriangle className="h-3 w-3 mr-1" />
Child
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/AddQueueDialog.test.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/AddQueueDialog.test.tsx
index d159899dbb9..af4e11bbba7 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/AddQueueDialog.test.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/AddQueueDialog.test.tsx
@@ -105,7 +105,7 @@ describe('AddQueueDialog', () => {
render(<AddQueueDialog open={true} parentQueuePath="root"
onClose={vi.fn()} />);
const nameInput = screen.getByLabelText(/queue name/i);
- const submitButton = screen.getByRole('button', { name: /adjust
capacities/i });
+ const submitButton = screen.getByRole('button', { name: /create queue/i });
// Initially button should be disabled (no name entered)
expect(submitButton).toBeDisabled();
@@ -128,7 +128,7 @@ describe('AddQueueDialog', () => {
render(<AddQueueDialog open={true} parentQueuePath="root"
onClose={vi.fn()} />);
const nameInput = screen.getByLabelText(/queue name/i);
- const submitButton = screen.getByRole('button', { name: /adjust
capacities/i });
+ const submitButton = screen.getByRole('button', { name: /create queue/i });
await user.type(nameInput, 'queue@#$%');
@@ -151,7 +151,7 @@ describe('AddQueueDialog', () => {
// Fill all required fields
await user.type(nameInput, 'newqueue');
- const submitButton = screen.getByRole('button', { name: /adjust
capacities/i });
+ const submitButton = screen.getByRole('button', { name: /create queue/i });
expect(submitButton).not.toBeDisabled();
await user.click(submitButton);
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/AddQueueDialog.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/AddQueueDialog.tsx
index 59723015528..c49482a5977 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/AddQueueDialog.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/AddQueueDialog.tsx
@@ -38,7 +38,7 @@ import {
SelectTrigger,
SelectValue,
} from '~/components/ui/select';
-import { Plus, SlidersHorizontal } from 'lucide-react';
+import { Plus, Info } from 'lucide-react';
import { useQueueActions } from
'~/features/queue-management/hooks/useQueueActions';
import { useCapacityEditor } from
'~/features/queue-management/hooks/useCapacityEditor';
@@ -163,6 +163,15 @@ export function AddQueueDialog({ open, parentQueuePath,
onClose }: AddQueueDialo
<input type="hidden" {...register('capacity')} />
<input type="hidden" {...register('maxCapacity')} />
+ {/* Workflow help text */}
+ <div className="flex items-start gap-2 p-3 rounded-md bg-muted/50
text-sm text-muted-foreground">
+ <Info className="h-4 w-4 mt-0.5 flex-shrink-0" />
+ <span>
+ After creating the queue, you will be able to set capacity for
this queue and
+ adjust sibling capacities in the capacity editor.
+ </span>
+ </div>
+
{/* State */}
<Field>
<FieldLabel htmlFor="state">State</FieldLabel>
@@ -187,8 +196,8 @@ export function AddQueueDialog({ open, parentQueuePath,
onClose }: AddQueueDialo
Cancel
</Button>
<Button type="submit" disabled={!isValid}>
- <SlidersHorizontal className="mr-2 h-4 w-4" />
- Adjust capacities
+ <Plus className="mr-2 h-4 w-4" />
+ Create Queue
</Button>
</DialogFooter>
</form>
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/DeleteQueueDialog.test.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/DeleteQueueDialog.test.tsx
index 9005f811683..1c9c1ec8d4e 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/DeleteQueueDialog.test.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/DeleteQueueDialog.test.tsx
@@ -52,8 +52,11 @@ describe('DeleteQueueDialog', () => {
expect(screen.getByRole('dialog')).toBeInTheDocument();
expect(screen.getByRole('heading', { name: /delete queue/i
})).toBeInTheDocument();
expect(screen.getByText(/Are you sure you want to delete the
queue/)).toBeInTheDocument();
- expect(screen.getByText('team1')).toBeInTheDocument();
+ // Queue name appears twice: in the prompt and in the confirmation label
+ expect(screen.getAllByText('team1')).toHaveLength(2);
expect(screen.getByText(/This action cannot be
undone/)).toBeInTheDocument();
+ // Confirmation input should exist
+ expect(screen.getByLabelText(/Type.*team1.*to
confirm/)).toBeInTheDocument();
});
it('should stage queue removal on confirmation', async () => {
@@ -63,6 +66,15 @@ describe('DeleteQueueDialog', () => {
render(<DeleteQueueDialog open={true} queuePath="root.production.team1"
onClose={onClose} />);
const deleteButton = screen.getByRole('button', { name: /delete queue/i });
+ // Button should be disabled until confirmation text is entered
+ expect(deleteButton).toBeDisabled();
+
+ // Type the queue name to confirm
+ const confirmInput = screen.getByLabelText(/Type.*team1.*to confirm/);
+ await user.type(confirmInput, 'team1');
+
+ // Now button should be enabled
+ expect(deleteButton).not.toBeDisabled();
await user.click(deleteButton);
expect(mockDeleteQueue).toHaveBeenCalledWith('root.production.team1');
@@ -127,10 +139,16 @@ describe('DeleteQueueDialog', () => {
).toBeInTheDocument();
});
- it('should use danger variant for delete button', () => {
+ it('should use danger variant for delete button', async () => {
+ const user = userEvent.setup();
render(<DeleteQueueDialog open={true} queuePath="root.default"
onClose={vi.fn()} />);
+ // Type confirmation to enable the button for class check
+ const confirmInput = screen.getByLabelText(/Type.*default.*to confirm/);
+ await user.type(confirmInput, 'default');
+
const deleteButton = screen.getByRole('button', { name: /delete queue/i });
- expect(deleteButton).toHaveClass('bg-destructive');
+ // Destructive buttons use gradient styling
+ expect(deleteButton).toHaveClass('from-destructive');
});
});
diff --git
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/DeleteQueueDialog.tsx
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/DeleteQueueDialog.tsx
index 0dd7e32b6e1..dc50508c188 100644
---
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/DeleteQueueDialog.tsx
+++
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-capacity-scheduler-ui/src/main/webapp/src/features/queue-management/components/dialogs/DeleteQueueDialog.tsx
@@ -17,6 +17,7 @@
*/
+import { useState, useEffect } from 'react';
import {
Dialog,
DialogContent,
@@ -26,6 +27,8 @@ import {
DialogTitle,
} from '~/components/ui/dialog';
import { Button } from '~/components/ui/button';
+import { Input } from '~/components/ui/input';
+import { Field, FieldControl, FieldLabel } from '~/components/ui/field';
import { Alert, AlertDescription } from '~/components/ui/alert';
import { Trash2, AlertTriangle } from 'lucide-react';
import { useQueueActions } from
'~/features/queue-management/hooks/useQueueActions';
@@ -40,11 +43,21 @@ interface DeleteQueueDialogProps {
export function DeleteQueueDialog({ open, queuePath, onClose }:
DeleteQueueDialogProps) {
const { deleteQueue, canDeleteQueue } = useQueueActions();
const queueName = queuePath.split('.').pop() || queuePath;
+ const [confirmText, setConfirmText] = useState('');
const canDelete = canDeleteQueue(queuePath);
const isRoot = queuePath === SPECIAL_VALUES.ROOT_QUEUE_NAME;
+ const isConfirmationValid = confirmText === queueName;
+
+ // Reset confirmation text when dialog opens/closes
+ useEffect(() => {
+ if (!open) {
+ setConfirmText('');
+ }
+ }, [open]);
const handleDelete = () => {
+ if (!isConfirmationValid) return;
try {
deleteQueue(queuePath);
onClose();
@@ -90,6 +103,20 @@ export function DeleteQueueDialog({ open, queuePath,
onClose }: DeleteQueueDialo
removed.
</AlertDescription>
</Alert>
+ <Field>
+ <FieldLabel htmlFor="confirmDelete">
+ Type <strong>{queueName}</strong> to confirm
+ </FieldLabel>
+ <FieldControl>
+ <Input
+ id="confirmDelete"
+ placeholder={queueName}
+ value={confirmText}
+ onChange={(e) => setConfirmText(e.target.value)}
+ autoComplete="off"
+ />
+ </FieldControl>
+ </Field>
</>
)}
</div>
@@ -99,7 +126,7 @@ export function DeleteQueueDialog({ open, queuePath, onClose
}: DeleteQueueDialo
Cancel
</Button>
{canDelete && !isRoot && (
- <Button onClick={handleDelete} variant="destructive">
+ <Button onClick={handleDelete} variant="destructive"
disabled={!isConfirmationValid}>
<Trash2 className="mr-2 h-4 w-4" />
Delete Queue
</Button>
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 fc0c9b49e2b..7da2968777e 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
@@ -116,17 +116,21 @@ export function StagedChangesPanel({ open, onClose,
onOpen }: StagedChangesPanel
// Show floating button when panel is closed and there are staged changes
if (!open && stagedChanges.length > 0) {
return (
- <div className="fixed bottom-4 left-1/2 -translate-x-1/2 z-50">
+ <div className="fixed bottom-6 left-1/2 -translate-x-1/2 z-50">
<Button
variant="default"
size="lg"
- className="relative shadow-lg rounded-full px-6"
+ className="relative shadow-xl hover:shadow-2xl rounded-full px-8
py-6 backdrop-blur-sm bg-primary/95 hover:bg-primary transition-all
duration-300 hover:scale-105 animate-in fade-in slide-in-from-bottom-4"
onClick={onOpen}
data-staged-changes-trigger
>
- <Gauge className="h-5 w-5 mr-2" />
- View Staged Changes
- <Badge variant="destructive" className="absolute -top-2 -right-2">
+ <span className="absolute inset-0 rounded-full bg-primary/20
animate-pulse" />
+ <Gauge className="h-5 w-5 mr-2 relative z-10" />
+ <span className="relative z-10 font-semibold">View Staged
Changes</span>
+ <Badge
+ variant="destructive"
+ className="absolute -top-2 -right-2 shadow-lg animate-bounce"
+ >
{stagedChanges.length}
</Badge>
</Button>
@@ -139,7 +143,7 @@ export function StagedChangesPanel({ open, onClose, onOpen
}: StagedChangesPanel
<DrawerContent className="max-h-[85vh]">
<div className="flex flex-col h-full max-h-[85vh]">
{/* Header */}
- <DrawerHeader className="border-b pb-4">
+ <DrawerHeader className="border-b pb-4 bg-gradient-to-r
from-muted/30 to-transparent">
<div className="space-y-3">
{applyError && (
<Alert variant="destructive">
@@ -150,8 +154,10 @@ export function StagedChangesPanel({ open, onClose, onOpen
}: StagedChangesPanel
)}
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
- <DrawerTitle>Staged Changes</DrawerTitle>
- <Badge variant="secondary">
+ <DrawerTitle className="text-xl font-bold tracking-tight">
+ Staged Changes
+ </DrawerTitle>
+ <Badge variant="secondary" className="font-semibold">
{stagedChanges.length} {stagedChanges.length === 1 ?
'change' : 'changes'}
</Badge>
</div>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]