diff --git a/docs/release-control/v6/internal/subsystems/performance-and-scalability.md b/docs/release-control/v6/internal/subsystems/performance-and-scalability.md index e1a60a8ea..027568f5b 100644 --- a/docs/release-control/v6/internal/subsystems/performance-and-scalability.md +++ b/docs/release-control/v6/internal/subsystems/performance-and-scalability.md @@ -39,33 +39,38 @@ regression protection. 17. `frontend-modern/src/components/Dashboard/StackedMemoryBar.tsx` 18. `frontend-modern/src/components/Dashboard/stackedMemoryBarModel.ts` 19. `frontend-modern/src/components/Dashboard/useStackedMemoryBarState.ts` -20. `frontend-modern/src/components/Dashboard/DiskList.tsx` -21. `frontend-modern/src/components/Dashboard/diskListModel.ts` -22. `frontend-modern/src/components/Dashboard/useDiskListState.ts` -23. `frontend-modern/src/components/Dashboard/GuestRow.tsx` -24. `frontend-modern/src/components/Dashboard/guestRowModel.tsx` -25. `frontend-modern/src/components/Dashboard/useGuestRowState.ts` -26. `frontend-modern/src/components/Dashboard/GuestDrawer.tsx` -27. `frontend-modern/src/components/Dashboard/guestDrawerModel.ts` -28. `frontend-modern/src/components/Dashboard/useGuestDrawerState.ts` -29. `frontend-modern/src/components/Dashboard/workloadSelectors.ts` -30. `frontend-modern/src/components/Infrastructure/UnifiedResourceTable.tsx` -31. `frontend-modern/src/components/Infrastructure/useUnifiedResourceTableState.ts` -32. `frontend-modern/src/components/Infrastructure/infrastructureSelectors.ts` -33. `frontend-modern/src/components/Infrastructure/resourceDetailMappers.ts` -34. `frontend-modern/src/components/Dashboard/__tests__/Dashboard.performance.contract.test.tsx` -35. `frontend-modern/src/components/Dashboard/__tests__/DashboardFilter.test.tsx` -36. `frontend-modern/src/components/Dashboard/__tests__/useDashboardFilterState.test.ts` -37. `frontend-modern/src/components/Dashboard/ThresholdSlider.test.tsx` -38. `frontend-modern/src/components/Dashboard/__tests__/useThresholdSliderState.test.ts` -39. `frontend-modern/src/components/Dashboard/__tests__/StackedDiskBar.test.tsx` -40. `frontend-modern/src/components/Dashboard/__tests__/useStackedDiskBarState.test.tsx` -41. `frontend-modern/src/components/Dashboard/StackedMemoryBar.test.tsx` -42. `frontend-modern/src/components/Dashboard/__tests__/useStackedMemoryBarState.test.tsx` -43. `frontend-modern/src/components/Dashboard/__tests__/DiskList.test.tsx` -44. `frontend-modern/src/components/Dashboard/__tests__/GuestRow.test.tsx` -45. `frontend-modern/src/components/Dashboard/GuestDrawer.test.tsx` -46. `frontend-modern/src/components/Infrastructure/__tests__/UnifiedResourceTable.performance.contract.test.tsx` +20. `frontend-modern/src/components/Dashboard/MetricBar.tsx` +21. `frontend-modern/src/components/Dashboard/metricBarModel.ts` +22. `frontend-modern/src/components/Dashboard/useMetricBarState.ts` +23. `frontend-modern/src/components/Dashboard/DiskList.tsx` +24. `frontend-modern/src/components/Dashboard/diskListModel.ts` +25. `frontend-modern/src/components/Dashboard/useDiskListState.ts` +26. `frontend-modern/src/components/Dashboard/GuestRow.tsx` +27. `frontend-modern/src/components/Dashboard/guestRowModel.tsx` +28. `frontend-modern/src/components/Dashboard/useGuestRowState.ts` +29. `frontend-modern/src/components/Dashboard/GuestDrawer.tsx` +30. `frontend-modern/src/components/Dashboard/guestDrawerModel.ts` +31. `frontend-modern/src/components/Dashboard/useGuestDrawerState.ts` +32. `frontend-modern/src/components/Dashboard/workloadSelectors.ts` +33. `frontend-modern/src/components/Infrastructure/UnifiedResourceTable.tsx` +34. `frontend-modern/src/components/Infrastructure/useUnifiedResourceTableState.ts` +35. `frontend-modern/src/components/Infrastructure/infrastructureSelectors.ts` +36. `frontend-modern/src/components/Infrastructure/resourceDetailMappers.ts` +37. `frontend-modern/src/components/Dashboard/__tests__/Dashboard.performance.contract.test.tsx` +38. `frontend-modern/src/components/Dashboard/__tests__/DashboardFilter.test.tsx` +39. `frontend-modern/src/components/Dashboard/__tests__/useDashboardFilterState.test.ts` +40. `frontend-modern/src/components/Dashboard/MetricBar.test.tsx` +41. `frontend-modern/src/components/Dashboard/__tests__/useMetricBarState.test.tsx` +42. `frontend-modern/src/components/Dashboard/ThresholdSlider.test.tsx` +43. `frontend-modern/src/components/Dashboard/__tests__/useThresholdSliderState.test.ts` +44. `frontend-modern/src/components/Dashboard/__tests__/StackedDiskBar.test.tsx` +45. `frontend-modern/src/components/Dashboard/__tests__/useStackedDiskBarState.test.tsx` +46. `frontend-modern/src/components/Dashboard/StackedMemoryBar.test.tsx` +47. `frontend-modern/src/components/Dashboard/__tests__/useStackedMemoryBarState.test.tsx` +48. `frontend-modern/src/components/Dashboard/__tests__/DiskList.test.tsx` +49. `frontend-modern/src/components/Dashboard/__tests__/GuestRow.test.tsx` +50. `frontend-modern/src/components/Dashboard/GuestDrawer.test.tsx` +51. `frontend-modern/src/components/Infrastructure/__tests__/UnifiedResourceTable.performance.contract.test.tsx` ## Shared Boundaries @@ -92,6 +97,7 @@ regression protection. 13. Extend threshold-slider value-position math, title/label derivation, and drag scroll-lock runtime through `frontend-modern/src/components/Dashboard/thresholdSliderModel.ts` and `frontend-modern/src/components/Dashboard/useThresholdSliderState.ts` rather than rebuilding slider-local state and pointer lifecycle inside `frontend-modern/src/components/Dashboard/ThresholdSlider.tsx` 14. Extend stacked disk-bar capacity math, segment/tooltip derivation, and resize-observer runtime through `frontend-modern/src/components/Dashboard/stackedDiskBarModel.ts` and `frontend-modern/src/components/Dashboard/useStackedDiskBarState.ts` rather than rebuilding disk-bar-local state, mode branching, and tooltip shaping inside `frontend-modern/src/components/Dashboard/StackedDiskBar.tsx` 15. Extend stacked memory-bar capacity math, balloon/swap derivation, and resize-observer runtime through `frontend-modern/src/components/Dashboard/stackedMemoryBarModel.ts` and `frontend-modern/src/components/Dashboard/useStackedMemoryBarState.ts` rather than rebuilding memory-bar-local state, tooltip shaping, and label-fit logic inside `frontend-modern/src/components/Dashboard/StackedMemoryBar.tsx` +16. Extend metric-bar width, label-fit logic, and resize-observer runtime through `frontend-modern/src/components/Dashboard/metricBarModel.ts` and `frontend-modern/src/components/Dashboard/useMetricBarState.ts` rather than rebuilding metric-local state and threshold mapping inside `frontend-modern/src/components/Dashboard/MetricBar.tsx` ## Forbidden Paths @@ -183,6 +189,14 @@ resize-observer plus tooltip lifecycle live in Future memory-bar runtime changes must extend through those owners instead of reintroducing mixed resize state, balloon branching, and tooltip shaping into the shell. +The dashboard metric bar now follows that same pattern: the shell stays in +`frontend-modern/src/components/Dashboard/MetricBar.tsx`, while width, +show-label, sublabel-fit, and threshold-color derivation live in +`frontend-modern/src/components/Dashboard/metricBarModel.ts` and +resize-observer lifecycle lives in +`frontend-modern/src/components/Dashboard/useMetricBarState.ts`. Future +metric-bar runtime changes must extend through those owners instead of +reintroducing mixed resize state and label-fit logic into the shell. The unified resource table hot path is now also governed as explicit performance-owned runtime, with shared ownership against the unified-resource diff --git a/docs/release-control/v6/internal/subsystems/registry.json b/docs/release-control/v6/internal/subsystems/registry.json index 2ac0aa61a..79795e7c3 100644 --- a/docs/release-control/v6/internal/subsystems/registry.json +++ b/docs/release-control/v6/internal/subsystems/registry.json @@ -2526,6 +2526,8 @@ "frontend-modern/src/components/Dashboard/guestDrawerModel.ts", "frontend-modern/src/components/Dashboard/GuestRow.tsx", "frontend-modern/src/components/Dashboard/guestRowModel.tsx", + "frontend-modern/src/components/Dashboard/MetricBar.tsx", + "frontend-modern/src/components/Dashboard/metricBarModel.ts", "frontend-modern/src/components/Dashboard/StackedDiskBar.tsx", "frontend-modern/src/components/Dashboard/stackedDiskBarModel.ts", "frontend-modern/src/components/Dashboard/StackedMemoryBar.tsx", @@ -2537,6 +2539,7 @@ "frontend-modern/src/components/Dashboard/useDiskListState.ts", "frontend-modern/src/components/Dashboard/useGuestDrawerState.ts", "frontend-modern/src/components/Dashboard/useGuestRowState.ts", + "frontend-modern/src/components/Dashboard/useMetricBarState.ts", "frontend-modern/src/components/Dashboard/useStackedDiskBarState.ts", "frontend-modern/src/components/Dashboard/useStackedMemoryBarState.ts", "frontend-modern/src/components/Dashboard/useThresholdSliderState.ts", @@ -2558,9 +2561,11 @@ "frontend-modern/src/components/Dashboard/__tests__/DiskList.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/StackedDiskBar.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/useDashboardFilterState.test.ts", + "frontend-modern/src/components/Dashboard/__tests__/useMetricBarState.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/useStackedDiskBarState.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/useStackedMemoryBarState.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/useThresholdSliderState.test.ts", + "frontend-modern/src/components/Dashboard/MetricBar.test.tsx", "frontend-modern/src/components/Dashboard/StackedMemoryBar.test.tsx", "frontend-modern/src/components/Dashboard/ThresholdSlider.test.tsx", "internal/api/router_bench_test.go", @@ -2601,6 +2606,8 @@ "frontend-modern/src/components/Dashboard/guestDrawerModel.ts", "frontend-modern/src/components/Dashboard/GuestRow.tsx", "frontend-modern/src/components/Dashboard/guestRowModel.tsx", + "frontend-modern/src/components/Dashboard/MetricBar.tsx", + "frontend-modern/src/components/Dashboard/metricBarModel.ts", "frontend-modern/src/components/Dashboard/StackedDiskBar.tsx", "frontend-modern/src/components/Dashboard/stackedDiskBarModel.ts", "frontend-modern/src/components/Dashboard/StackedMemoryBar.tsx", @@ -2612,6 +2619,7 @@ "frontend-modern/src/components/Dashboard/useDiskListState.ts", "frontend-modern/src/components/Dashboard/useGuestDrawerState.ts", "frontend-modern/src/components/Dashboard/useGuestRowState.ts", + "frontend-modern/src/components/Dashboard/useMetricBarState.ts", "frontend-modern/src/components/Dashboard/useStackedDiskBarState.ts", "frontend-modern/src/components/Dashboard/useStackedMemoryBarState.ts", "frontend-modern/src/components/Dashboard/useThresholdSliderState.ts", @@ -2630,11 +2638,13 @@ "frontend-modern/src/components/Dashboard/__tests__/GuestRow.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/StackedDiskBar.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/useDashboardFilterState.test.ts", + "frontend-modern/src/components/Dashboard/__tests__/useMetricBarState.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/useStackedDiskBarState.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/useStackedMemoryBarState.test.tsx", "frontend-modern/src/components/Dashboard/__tests__/useThresholdSliderState.test.ts", "frontend-modern/src/components/Dashboard/__tests__/workloadSelectors.test.ts", "frontend-modern/src/components/Dashboard/GuestDrawer.test.tsx", + "frontend-modern/src/components/Dashboard/MetricBar.test.tsx", "frontend-modern/src/components/Dashboard/StackedMemoryBar.test.tsx", "frontend-modern/src/components/Dashboard/ThresholdSlider.test.tsx", "frontend-modern/src/components/Infrastructure/__tests__/UnifiedResourceTable.performance.contract.test.tsx" diff --git a/frontend-modern/src/components/Dashboard/MetricBar.tsx b/frontend-modern/src/components/Dashboard/MetricBar.tsx index 00046a8b5..c53804144 100644 --- a/frontend-modern/src/components/Dashboard/MetricBar.tsx +++ b/frontend-modern/src/components/Dashboard/MetricBar.tsx @@ -1,74 +1,27 @@ -import { Show, createMemo, createSignal, onMount, onCleanup } from 'solid-js'; +import { Show } from 'solid-js'; import { ProgressBar } from '@/components/shared/ProgressBar'; -import { estimateTextWidth } from '@/utils/format'; -import { getMetricColorClass } from '@/utils/metricThresholds'; -import type { MetricType } from '@/utils/metricThresholds'; - -interface MetricBarProps { - value: number; - label: string; - sublabel?: string; - showLabel?: boolean; - type?: 'cpu' | 'memory' | 'disk' | 'generic'; - resourceId?: string; - class?: string; -} +import { type MetricBarProps } from './metricBarModel'; +import { useMetricBarState } from './useMetricBarState'; export function MetricBar(props: MetricBarProps) { - const width = createMemo(() => Math.min(props.value, 100)); - - // Track container width - const [containerWidth, setContainerWidth] = createSignal(100); - let containerRef: HTMLDivElement | undefined; - - // Set up ResizeObserver to track container width changes - onMount(() => { - if (!containerRef) return; - - setContainerWidth(containerRef.offsetWidth); - - const observer = new ResizeObserver((entries) => { - for (const entry of entries) { - setContainerWidth(entry.contentRect.width); - } - }); - - observer.observe(containerRef); - - onCleanup(() => observer.disconnect()); - }); - - // Determine if sublabel fits based on estimated text width - const showSublabel = createMemo(() => { - if (props.showLabel === false) return false; - if (!props.sublabel) return false; - const fullText = `${props.label} (${props.sublabel})`; - const estimatedWidth = estimateTextWidth(fullText); - return containerWidth() >= estimatedWidth; - }); - - const showLabel = createMemo(() => props.showLabel !== false && props.label.trim().length > 0); - - // Get color class from centralized thresholds - const progressColorClass = createMemo(() => { - const metric = props.type || 'cpu'; - // 'generic' falls back to cpu thresholds - const metricType: MetricType = metric === 'generic' ? 'cpu' : metric; - return getMetricColorClass(props.value, metricType); - }); + const state = useMetricBarState(props); + const presentation = state.presentation; return ( -