diff --git a/frontend-modern/src/features/platformPage/sharedPlatformPage.tsx b/frontend-modern/src/features/platformPage/sharedPlatformPage.tsx
index 39c3ddf544..a6306d9638 100644
--- a/frontend-modern/src/features/platformPage/sharedPlatformPage.tsx
+++ b/frontend-modern/src/features/platformPage/sharedPlatformPage.tsx
@@ -132,18 +132,20 @@ export function PlatformErrorState(props: {
// 'running' vs 'online', 'stopped' vs 'offline') collapse to one chip set.
export type PlatformResourceStatusFilter = 'all' | 'online' | 'degraded' | 'offline';
+const statusDot = (className: string) => ;
+
export const PLATFORM_STATUS_FILTER_OPTIONS: FilterOption[] = [
{ value: 'all', label: 'All' },
- { value: 'online', label: 'Online' },
- { value: 'degraded', label: 'Degraded' },
- { value: 'offline', label: 'Offline' },
+ { value: 'online', label: 'Online', tone: 'success', leading: statusDot('bg-emerald-500') },
+ { value: 'degraded', label: 'Degraded', tone: 'warning', leading: statusDot('bg-amber-500') },
+ { value: 'offline', label: 'Offline', tone: 'danger', leading: statusDot('bg-red-500') },
];
export const PLATFORM_HEALTH_FILTER_OPTIONS: FilterOption[] = [
{ value: 'all', label: 'All' },
- { value: 'online', label: 'Healthy' },
- { value: 'degraded', label: 'Degraded' },
- { value: 'offline', label: 'Offline' },
+ { value: 'online', label: 'Healthy', tone: 'success', leading: statusDot('bg-emerald-500') },
+ { value: 'degraded', label: 'Degraded', tone: 'warning', leading: statusDot('bg-amber-500') },
+ { value: 'offline', label: 'Offline', tone: 'danger', leading: statusDot('bg-red-500') },
];
const ONLINE_STATUSES = new Set(['online', 'running']);
@@ -289,6 +291,7 @@ export function PlatformTableToolbar(props: {
/>
{
);
}
+const statusDot = (className: string) => ;
+
const ARCHIVE_STATUS_FILTERS: FilterOption<'all' | 'protected' | 'verified' | 'unverified'>[] = [
{ value: 'all', label: 'All' },
- { value: 'protected', label: 'Protected' },
- { value: 'verified', label: 'Verified' },
- { value: 'unverified', label: 'Unverified' },
+ { value: 'protected', label: 'Protected', tone: 'info', leading: statusDot('bg-blue-500') },
+ { value: 'verified', label: 'Verified', tone: 'success', leading: statusDot('bg-emerald-500') },
+ { value: 'unverified', label: 'Unverified', tone: 'warning', leading: statusDot('bg-amber-500') },
];
const TASK_STATUS_FILTERS: FilterOption<'all' | 'ok' | 'failed' | 'running'>[] = [
{ value: 'all', label: 'All' },
- { value: 'ok', label: 'OK' },
- { value: 'failed', label: 'Failed' },
- { value: 'running', label: 'Running' },
+ { value: 'ok', label: 'OK', tone: 'success', leading: statusDot('bg-emerald-500') },
+ { value: 'failed', label: 'Failed', tone: 'danger', leading: statusDot('bg-red-500') },
+ { value: 'running', label: 'Running', tone: 'info', leading: statusDot('bg-blue-500') },
];
export const ProxmoxBackupsTable: Component<{
@@ -400,6 +402,7 @@ export const ProxmoxBackupsTable: Component<{
;
+
+const STATUS_FILTER_OPTIONS: FilterOption[] = [
{ value: 'all', label: 'All' },
- { value: 'healthy', label: 'Healthy' },
- { value: 'warning', label: 'Warning' },
- { value: 'critical', label: 'Critical' },
-] satisfies Array<{ value: CephStatusFilter; label: string }>;
+ { value: 'healthy', label: 'Healthy', tone: 'success', leading: statusDot('bg-emerald-500') },
+ { value: 'warning', label: 'Warning', tone: 'warning', leading: statusDot('bg-amber-500') },
+ { value: 'critical', label: 'Critical', tone: 'danger', leading: statusDot('bg-red-500') },
+];
function classify(resource: Resource): CephStatusFilter {
const raw = (resource.ceph?.healthStatus ?? resource.status ?? '').toUpperCase();
diff --git a/frontend-modern/src/features/proxmox/ProxmoxReplicationTable.tsx b/frontend-modern/src/features/proxmox/ProxmoxReplicationTable.tsx
index 153be3c42f..63bcf451da 100644
--- a/frontend-modern/src/features/proxmox/ProxmoxReplicationTable.tsx
+++ b/frontend-modern/src/features/proxmox/ProxmoxReplicationTable.tsx
@@ -23,6 +23,7 @@ import {
} from '@/components/shared/Table';
import { apiFetch } from '@/utils/apiClient';
import { formatRelativeTime } from '@/utils/format';
+import type { FilterOption } from '@/components/shared/FilterButtonGroup';
import {
PLATFORM_TABLE_BODY_CLASS,
PLATFORM_TABLE_CARD_CLASS,
@@ -42,13 +43,15 @@ import type { ReplicationJob, ReplicationJobsResponse } from '@/types/api';
type ReplicationStatusFilter = 'all' | 'healthy' | 'failed' | 'pending' | 'disabled';
-const STATUS_FILTER_OPTIONS = [
+const statusDot = (className: string) => ;
+
+const STATUS_FILTER_OPTIONS: FilterOption[] = [
{ value: 'all', label: 'All' },
- { value: 'healthy', label: 'Healthy' },
- { value: 'failed', label: 'Failed' },
- { value: 'pending', label: 'Pending' },
- { value: 'disabled', label: 'Disabled' },
-] satisfies Array<{ value: ReplicationStatusFilter; label: string }>;
+ { value: 'healthy', label: 'Healthy', tone: 'success', leading: statusDot('bg-emerald-500') },
+ { value: 'failed', label: 'Failed', tone: 'danger', leading: statusDot('bg-red-500') },
+ { value: 'pending', label: 'Pending', tone: 'warning', leading: statusDot('bg-amber-500') },
+ { value: 'disabled', label: 'Disabled', tone: 'muted', leading: statusDot('bg-slate-400') },
+];
interface ReplicationStatusIndicator {
variant: StatusIndicatorVariant;