Register platform section tabs governance

This commit is contained in:
rcourtman
2026-06-12 14:01:39 +01:00
parent 51ac42870c
commit 77134632e2
3 changed files with 133 additions and 0 deletions
@@ -2404,6 +2404,12 @@ and Refresh action for platform page and table load failures; platform
consumers own only the failure title, description, and refresh callback.
Platform feature surfaces must not recreate an `EmptyState` plus local Refresh
button for `Could not load...` states.
Platform section tabs are registry-backed too. `PlatformSectionTabs` owns the
workflow tab shell, hidden-single-tab behavior, active-link styling, link
targeting, and active-page aria state for platform pages; platform page
surfaces own only tab specs, the active tab choice, and aria-label copy.
Platform feature surfaces must not rebuild local nav tab bars with
`aria-current` and border-tab styling.
Filter bars are registry-backed too. `FilterBar` owns resource-list filtering
as a catalog of `FilterDef` entries, while `filterChipStatusDot` owns the
small leading status-dot glyph used by filter options. Page and feature
@@ -164,6 +164,28 @@
"scripts/shared-template-audit.mjs"
]
},
{
"id": "platform-section-tabs",
"category": "platform-section-tabs",
"summary": "Platform page workflow tabs must compose PlatformSectionTabs instead of recreating page-local nav tab bars.",
"canonical": {
"path": "src/features/platformPage/sharedPlatformPage.tsx",
"export": "PlatformSectionTabs"
},
"requiredConsumers": [
{ "path": "src/features/docker/DockerPageSurface.tsx" },
{ "path": "src/features/kubernetes/KubernetesPageSurface.tsx" },
{ "path": "src/features/proxmox/ProxmoxPageSurface.tsx" },
{ "path": "src/features/standalone/StandalonePageSurface.tsx" },
{ "path": "src/features/truenas/TrueNASPageSurface.tsx" },
{ "path": "src/features/vmware/VmwarePageSurface.tsx" }
],
"proof": [
"src/components/shared/SharedPrimitives.guardrails.test.ts",
"src/features/platformPage/__tests__/platformOverviewLayout.guardrails.test.ts",
"scripts/shared-template-audit.mjs"
]
},
{
"id": "filter-bar-catalog-shell",
"category": "filter-bar",
@@ -292,6 +314,31 @@
"scripts/shared-template-audit.mjs"
]
},
{
"id": "platform-section-tabs-local-nav",
"category": "platform-section-tabs",
"summary": "Platform page surfaces must not recreate the active-link tab navigation owned by PlatformSectionTabs.",
"canonical": {
"path": "src/features/platformPage/sharedPlatformPage.tsx",
"export": "PlatformSectionTabs"
},
"scopes": [
"src/features/docker",
"src/features/kubernetes",
"src/features/proxmox",
"src/features/standalone",
"src/features/truenas",
"src/features/vmware"
],
"extensions": [".tsx"],
"allPatterns": ["aria-current={", "border-b-2", "border-b border-border"],
"legacyReason": "Retired migration debt. Platform page section tabs must use PlatformSectionTabs; no page-local tab-bar exceptions are currently allowed.",
"allowedPaths": [],
"proof": [
"src/components/shared/SharedPrimitives.guardrails.test.ts",
"scripts/shared-template-audit.mjs"
]
},
{
"id": "filter-bar-consumer-legacy-page-controls",
"category": "filter-bar",
@@ -1151,6 +1151,86 @@ describe('shared primitive guardrails', () => {
}
});
it('keeps platform section navigation on the shared tabs template', () => {
const registry = JSON.parse(sharedTemplateRegistrySource) as {
rules?: Array<{
id: string;
canonical?: { path?: string; export?: string };
requiredConsumers?: Array<{ path?: string }>;
}>;
patternGuards?: Array<{
id: string;
canonical?: { path?: string; export?: string };
allPatterns?: string[];
scopes?: string[];
allowedPaths?: string[];
}>;
};
const registeredRule = registry.rules?.find((rule) => rule.id === 'platform-section-tabs');
const registeredGuard = registry.patternGuards?.find(
(guard) => guard.id === 'platform-section-tabs-local-nav',
);
const requiredConsumerPaths = [
'src/features/docker/DockerPageSurface.tsx',
'src/features/kubernetes/KubernetesPageSurface.tsx',
'src/features/proxmox/ProxmoxPageSurface.tsx',
'src/features/standalone/StandalonePageSurface.tsx',
'src/features/truenas/TrueNASPageSurface.tsx',
'src/features/vmware/VmwarePageSurface.tsx',
];
const platformPageSurfaceSources = [
dockerPageSurfaceSource,
kubernetesPageSurfaceSource,
proxmoxPageSurfaceSource,
standalonePageSurfaceSource,
truenasPageSurfaceSource,
vmwarePageSurfaceSource,
];
expect(registeredRule?.canonical?.path).toBe(
'src/features/platformPage/sharedPlatformPage.tsx',
);
expect(registeredRule?.canonical?.export).toBe('PlatformSectionTabs');
expect(registeredRule?.requiredConsumers?.map((consumer) => consumer.path)).toEqual(
expect.arrayContaining(requiredConsumerPaths),
);
expect(registeredGuard?.canonical?.path).toBe(
'src/features/platformPage/sharedPlatformPage.tsx',
);
expect(registeredGuard?.canonical?.export).toBe('PlatformSectionTabs');
expect(registeredGuard?.allPatterns).toEqual([
'aria-current={',
'border-b-2',
'border-b border-border',
]);
expect(registeredGuard?.allowedPaths ?? []).toHaveLength(0);
expect(registeredGuard?.scopes).toEqual(
expect.arrayContaining([
'src/features/docker',
'src/features/kubernetes',
'src/features/proxmox',
'src/features/standalone',
'src/features/truenas',
'src/features/vmware',
]),
);
expect(sharedPlatformPageSource).toContain('export function PlatformSectionTabs');
expect(sharedPlatformPageSource).toContain('props.tabs.length > 1');
expect(sharedPlatformPageSource).toContain('href={tab.path}');
expect(sharedPlatformPageSource).toContain('border-b-2');
expect(sharedPlatformPageSource).toContain(
"aria-current={props.active === tab.id ? 'page' : undefined}",
);
for (const source of platformPageSurfaceSources) {
expect(source).toContain('PlatformSectionTabs');
expect(source).not.toContain('aria-current={');
expect(source).not.toContain('border-b-2');
expect(source).not.toContain('border-b border-border');
}
});
it('keeps platform load-failure states on the shared error template', () => {
const registry = JSON.parse(sharedTemplateRegistrySource) as {
rules?: Array<{