diff --git a/docs/release-control/v6/internal/subsystems/storage-recovery.md b/docs/release-control/v6/internal/subsystems/storage-recovery.md index 344350e54..946a7dd94 100644 --- a/docs/release-control/v6/internal/subsystems/storage-recovery.md +++ b/docs/release-control/v6/internal/subsystems/storage-recovery.md @@ -771,10 +771,12 @@ shared monitoring-card rhythm of one dominant metric plus compact supporting rows rather than reviving bespoke visual telemetry that makes the strip read heavier than the rest of Pulse. That same scan rule should also use the summary header for the first, obvious -recovery counts. The header should carry total protected items plus the top -healthy/attention cues in the same way other Pulse monitoring summaries expose -their first read, while the `Posture` card focuses on the composition of the -attention state instead of repeating the same healthy count again. +recovery counts. The header should carry total protected items plus one top +status cue, not a second copy of the full posture breakdown. When recovery has +attention-state items, the header should surface that attention cue; otherwise +it may carry the healthy cue. The `Posture` card then owns the composition of +the posture state instead of having the header and card repeat both healthy and +attention counts at once. That same differentiation rule applies across cards too. `Posture` and `Freshness` should not lead with the same stale/attention headline; the freshness card should emphasize recent successful coverage such as fresh-in-24h diff --git a/frontend-modern/src/components/Recovery/RecoverySummary.test.tsx b/frontend-modern/src/components/Recovery/RecoverySummary.test.tsx index 0b1c7e4a0..d3a80c8e3 100644 --- a/frontend-modern/src/components/Recovery/RecoverySummary.test.tsx +++ b/frontend-modern/src/components/Recovery/RecoverySummary.test.tsx @@ -62,7 +62,7 @@ describe('RecoverySummary', () => { expect(screen.getByText(/recovery points/i)).toBeInTheDocument(); expect(screen.getByText(/item types/i)).toBeInTheDocument(); expect(screen.getByText('2 platforms')).toBeInTheDocument(); - expect(screen.getAllByText('1 healthy').length).toBeGreaterThan(1); + expect(screen.getAllByText('1 healthy')).toHaveLength(1); expect(screen.getByText('1 attention')).toBeInTheDocument(); expect(screen.getByText('1 stale')).toBeInTheDocument(); expect(screen.getByText('fresh in 24h')).toBeInTheDocument(); diff --git a/frontend-modern/src/components/Recovery/RecoverySummary.tsx b/frontend-modern/src/components/Recovery/RecoverySummary.tsx index b879500de..c8633a661 100644 --- a/frontend-modern/src/components/Recovery/RecoverySummary.tsx +++ b/frontend-modern/src/components/Recovery/RecoverySummary.tsx @@ -108,6 +108,23 @@ export const RecoverySummary: Component = (props) => { if (!latestLabel) return undefined; return {latestLabel}; }); + const headerStatusCue = createMemo(() => { + if (attentionCount() > 0) { + return ( + + {attentionCount()} attention + + ); + } + if (healthyCount() > 0) { + return ( + + {healthyCount()} healthy + + ); + } + return undefined; + }); return ( @@ -115,16 +132,7 @@ export const RecoverySummary: Component = (props) => { headerLeft={ <> {summary().total} protected items - 0}> - - {healthyCount()} healthy - - - 0}> - - {attentionCount()} attention - - + {headerStatusCue()} } timeRange={props.timeRange()}