diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md index 7e0d54dc6..4fd6a40ef 100644 --- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md +++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md @@ -96,6 +96,11 @@ work extends shared components instead of creating new local variants. 67. `frontend-modern/src/utils/dashboardGuestPresentation.ts` 68. `frontend-modern/src/utils/dashboardKpiPresentation.ts` 69. `frontend-modern/src/utils/dashboardTrendPresentation.ts` +70. `frontend-modern/src/components/Toast/Toast.tsx` +71. `frontend-modern/src/utils/toast.ts` +72. `frontend-modern/src/utils/semanticTonePresentation.ts` +73. `frontend-modern/src/utils/emptyStatePresentation.ts` +74. `frontend-modern/src/utils/typeColumnPresentation.ts` 61. `frontend-modern/src/pages/__tests__/Operations.helpers.test.ts` 59. `frontend-modern/src/components/Settings/NetworkDiscoverySection.tsx` 60. `frontend-modern/src/components/Settings/NetworkBoundarySettingsSection.tsx` @@ -770,6 +775,18 @@ arrow-delimited label presentation used across AI, Patrol, Storage/Recovery, and other feature surfaces. Feature contracts may depend on that helper, but they should not re-home or fork those generic text-formatting rules into feature-local utilities. +That same shared presentation boundary now also owns operator feedback and +shared table-label semantics. `frontend-modern/src/components/Toast/Toast.tsx` +stays the render shell for the global toast stack, +`frontend-modern/src/utils/toast.ts` owns the app-level trigger helper, +`frontend-modern/src/utils/semanticTonePresentation.ts` owns canonical toast +and diagnostics tone classes, `frontend-modern/src/utils/emptyStatePresentation.ts` +owns the shared empty-state tone styling consumed by `EmptyState`, and +`frontend-modern/src/utils/typeColumnPresentation.ts` owns the single +canonical type-column label used across dashboard and alert tables. Future +feedback, empty-state, or shared type-column work should extend those helpers +instead of reintroducing panel-local tone classes, app-local toast wiring, or +copy drift between tables. First-session educational surfaces must also stay brief, flat, and model-led. When Pulse needs to teach a user how a flow works, the primary on-screen guidance should collapse to a few short descriptions of the real product diff --git a/docs/release-control/v6/internal/subsystems/registry.json b/docs/release-control/v6/internal/subsystems/registry.json index 75e8aaae2..f64fd919a 100644 --- a/docs/release-control/v6/internal/subsystems/registry.json +++ b/docs/release-control/v6/internal/subsystems/registry.json @@ -2347,6 +2347,7 @@ "frontend-modern/src/components/Settings/useSystemLogsPanelState.ts", "frontend-modern/src/components/SetupWizard/SetupCompletionPreview.tsx", "frontend-modern/src/components/SetupWizard/SetupWizard.tsx", + "frontend-modern/src/components/Toast/Toast.tsx", "frontend-modern/src/features/dashboardOverview/ActionRequiredPanel.tsx", "frontend-modern/src/features/dashboardOverview/DashboardCustomizer.tsx", "frontend-modern/src/features/dashboardOverview/index.ts", @@ -2363,15 +2364,19 @@ "frontend-modern/src/utils/dashboardTrendPresentation.ts", "frontend-modern/src/utils/diagnosticsPresentation.ts", "frontend-modern/src/utils/discoveryPresentation.ts", + "frontend-modern/src/utils/emptyStatePresentation.ts", "frontend-modern/src/utils/problemResourcePresentation.ts", "frontend-modern/src/utils/reportableResourceTypes.ts", "frontend-modern/src/utils/reportingPresentation.ts", "frontend-modern/src/utils/reportingResourceTypes.ts", + "frontend-modern/src/utils/semanticTonePresentation.ts", "frontend-modern/src/utils/settingsShellPresentation.ts", "frontend-modern/src/utils/ssoProviderPresentation.ts", "frontend-modern/src/utils/systemLogsPresentation.ts", "frontend-modern/src/utils/systemSettingsPresentation.ts", "frontend-modern/src/utils/textPresentation.ts", + "frontend-modern/src/utils/toast.ts", + "frontend-modern/src/utils/typeColumnPresentation.ts", "frontend-modern/src/utils/updatesPresentation.ts" ], "verification": { @@ -2525,6 +2530,27 @@ "frontend-modern/src/utils/__tests__/dashboardTrendPresentation.test.ts" ] }, + { + "id": "shared-feedback-and-column-presentation", + "label": "shared feedback and column presentation proof", + "match_prefixes": [], + "match_files": [ + "frontend-modern/src/components/Toast/Toast.tsx", + "frontend-modern/src/utils/emptyStatePresentation.ts", + "frontend-modern/src/utils/semanticTonePresentation.ts", + "frontend-modern/src/utils/toast.ts", + "frontend-modern/src/utils/typeColumnPresentation.ts" + ], + "allow_same_subsystem_tests": false, + "test_prefixes": [], + "exact_files": [ + "frontend-modern/src/components/shared/TypeColumn.guardrails.test.ts", + "frontend-modern/src/components/Toast/__tests__/Toast.test.tsx", + "frontend-modern/src/utils/__tests__/emptyStatePresentation.test.ts", + "frontend-modern/src/utils/__tests__/semanticTonePresentation.test.ts", + "frontend-modern/src/utils/__tests__/typeColumnPresentation.test.ts" + ] + }, { "id": "ai-settings-presentation-helper", "label": "AI settings presentation helper proof", diff --git a/frontend-modern/src/components/shared/TypeColumn.guardrails.test.ts b/frontend-modern/src/components/shared/TypeColumn.guardrails.test.ts index 535c39dfb..ab407c354 100644 --- a/frontend-modern/src/components/shared/TypeColumn.guardrails.test.ts +++ b/frontend-modern/src/components/shared/TypeColumn.guardrails.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import guestRowSource from '@/components/Dashboard/GuestRow.tsx?raw'; +import guestRowModelSource from '@/components/Dashboard/guestRowModel.tsx?raw'; import recoverySource from '@/components/Recovery/Recovery.tsx?raw'; import responsiveSource from '@/types/responsive.ts?raw'; import typeColumnDefinitionSource from '@/utils/typeColumnDefinition.ts?raw'; @@ -60,10 +60,10 @@ describe('type column guardrails', () => { }); it('routes runtime Type columns through the shared helper', () => { - expect(guestRowSource).toContain('createVisibleCanonicalTypeColumn()'); - expect(guestRowSource).not.toContain('createCanonicalTypeColumn'); - expect(guestRowSource).not.toMatch(INLINE_TYPE_COLUMN_PATTERN); - expect(guestRowSource).not.toContain("defaultVisibility:"); + expect(guestRowModelSource).toContain('createVisibleCanonicalTypeColumn()'); + expect(guestRowModelSource).not.toContain('createCanonicalTypeColumn'); + expect(guestRowModelSource).not.toMatch(INLINE_TYPE_COLUMN_PATTERN); + expect(guestRowModelSource).not.toContain("defaultVisibility:"); expect(recoverySource).toContain('createHiddenCanonicalTypeColumn()'); expect(recoverySource).not.toContain('createCanonicalTypeColumn'); @@ -92,7 +92,7 @@ describe('type column guardrails', () => { .sort(); expect(typeColumnUsers).toEqual([ - '../Dashboard/GuestRow.tsx', + '../Dashboard/guestRowModel.tsx', '../Recovery/Recovery.tsx', ]); @@ -127,7 +127,7 @@ describe('type column guardrails', () => { .sort(); expect(directHelperImportUsers).toEqual([ - '../Dashboard/GuestRow.tsx', + '../Dashboard/guestRowModel.tsx', '../Recovery/Recovery.tsx', ]); }); diff --git a/frontend-modern/src/utils/__tests__/typeColumnPresentation.test.ts b/frontend-modern/src/utils/__tests__/typeColumnPresentation.test.ts index b440c3ef5..d38402eed 100644 --- a/frontend-modern/src/utils/__tests__/typeColumnPresentation.test.ts +++ b/frontend-modern/src/utils/__tests__/typeColumnPresentation.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import alertsHistoryTabSource from '@/features/alerts/tabs/HistoryTab.tsx?raw'; +import alertHistoryTableSectionSource from '@/features/alerts/AlertHistoryTableSection.tsx?raw'; import problemResourcesTableSource from '@/features/dashboardOverview/ProblemResourcesTable.tsx?raw'; import { TYPE_COLUMN_LABEL } from '@/utils/typeColumnContract'; import { getTypeColumnLabel } from '@/utils/typeColumnPresentation'; @@ -17,7 +17,7 @@ describe('typeColumnPresentation', () => { it('keeps fixed runtime Type headers on the shared label utility', () => { expect(problemResourcesTableSource).toContain('getTypeColumnLabel()'); - expect(alertsHistoryTabSource).toContain('getTypeColumnLabel()'); + expect(alertHistoryTableSectionSource).toContain('getTypeColumnLabel()'); }); it('limits runtime Type header label helper imports to the known allowlist', () => { @@ -33,7 +33,7 @@ describe('typeColumnPresentation', () => { .sort(); expect(directTypeLabelHelperUsers).toEqual([ - '../../features/alerts/tabs/HistoryTab.tsx', + '../../features/alerts/AlertHistoryTableSection.tsx', '../../features/dashboardOverview/ProblemResourcesTable.tsx', ]); });