diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
index 41a3ccf07..d7203b68f 100644
--- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md
+++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
@@ -215,6 +215,7 @@ overflow.
1a. `frontend-modern/src/components/Infrastructure/resourceDetailDrawerMetricsHistoryModel.ts`
1b. `frontend-modern/src/components/Workloads/nodeDrawerModel.ts`
1c. `frontend-modern/src/features/docker/dockerHostDrawerModel.ts`
+ 1d. `frontend-modern/src/components/Workloads/AvailabilityProbeSuggestionCard.tsx`
2. `frontend-modern/src/components/Settings/Settings.tsx`
3. `frontend-modern/src/components/Settings/SettingsDialogs.tsx`
4. `frontend-modern/src/components/Settings/SettingsPageShell.tsx`
@@ -1226,6 +1227,12 @@ not a replacement status card, CTA band, or page-local nested card.
otherwise the shared `lg` transition is canonical. Feature surfaces own the
labels, values, wrapping, and selection behavior, but must not restore
drawer-width `justify-between` rows on desktop.
+ This contract also covers secondary drawer facts in availability status and
+ suggestion cards, resource change-history entries, Docker/PBS/PMG service
+ support panels, and Docker container-update management cards. Headers,
+ status summaries, actions, disk capacity summaries, and RAID state pairs may
+ retain intentional endpoint alignment; ordinary label/value facts in those
+ surfaces may not.
Read-only metadata chips belong to `MetadataBadge` and domain wrappers over
it. Organization role and share-status chips must use
`OrganizationRoleBadge` and `OrganizationShareStatusBadge`, so role/status
@@ -6185,6 +6192,10 @@ Known platform resources use that same compact presentation when availability
is attached. `AvailabilityProbeStatusCard` is the shared detail primitive for
Workloads and Docker host drawers; it renders the complete target, protocol,
latest result, latency when relevant, evidence freshness, and last observation.
+Its fact rows, and the matching service/probe/target rows in
+`AvailabilityProbeSuggestionCard`, compose `InfoCardKeyValueRow` so phone
+layouts remain condensed while wide cards keep each value adjacent to its
+label.
Plural attached checks render as repeated bounded cards from
`availabilityChecks`, while the row keeps one compatibility summary. Expired
successful evidence must render an amber `Stale` state with no green
diff --git a/docs/release-control/v6/internal/subsystems/registry.json b/docs/release-control/v6/internal/subsystems/registry.json
index d90c300ae..b6bf1b1e1 100644
--- a/docs/release-control/v6/internal/subsystems/registry.json
+++ b/docs/release-control/v6/internal/subsystems/registry.json
@@ -4899,6 +4899,7 @@
"frontend-modern/src/components/SetupWizard/SetupCompletionPreview.tsx",
"frontend-modern/src/components/SetupWizard/SetupWizard.tsx",
"frontend-modern/src/components/Toast/Toast.tsx",
+ "frontend-modern/src/components/Workloads/AvailabilityProbeSuggestionCard.tsx",
"frontend-modern/src/components/Workloads/nodeDrawerModel.ts",
"frontend-modern/src/features/docker/dockerHostDrawerModel.ts",
"frontend-modern/src/features/platformPage/platformEstateOverviewModel.ts",
@@ -5185,8 +5186,21 @@
"frontend-modern/src/utils/__tests__/reportingResourceTypes.test.ts"
]
},
- {
- "id": "workload-presentation-helpers",
+ {
+ "id": "compact-info-card-consumers",
+ "label": "compact information card consumer proof",
+ "match_prefixes": [],
+ "match_files": [
+ "frontend-modern/src/components/Workloads/AvailabilityProbeSuggestionCard.tsx"
+ ],
+ "allow_same_subsystem_tests": false,
+ "test_prefixes": [],
+ "exact_files": [
+ "frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts"
+ ]
+ },
+ {
+ "id": "workload-presentation-helpers",
"label": "workload presentation helper proof",
"match_prefixes": [],
"match_files": [
diff --git a/docs/release-control/v6/internal/subsystems/unified-resources.md b/docs/release-control/v6/internal/subsystems/unified-resources.md
index 00cff987b..c83bf6ee5 100644
--- a/docs/release-control/v6/internal/subsystems/unified-resources.md
+++ b/docs/release-control/v6/internal/subsystems/unified-resources.md
@@ -1329,6 +1329,11 @@ and temperature facts must also compose the frontend-primitives
`InfoCardKeyValueRow`. Mobile rows retain their condensed endpoint layout;
desktop rows use the shared fixed label track so labels and values remain
visually adjacent instead of spanning the full drawer width.
+The same boundary applies to availability facts, resource change-history
+metadata, Docker/PBS/PMG service facts, nested PMG queue/mail breakdowns, and
+Docker container-update management facts. Their headers, actions, and compact
+status summaries remain feature-owned, while ordinary label/value rows compose
+`InfoCardKeyValueRow` rather than restoring a drawer-width flex split.
Curated technical inventory follows the shared compact-row contract instead
of the secondary-card contract. Docker-host drawers must project system,
runtime, memory, storage, and telemetry facts through
diff --git a/frontend-modern/browser-verification.json b/frontend-modern/browser-verification.json
index a79b4887d..c1766e9ba 100644
--- a/frontend-modern/browser-verification.json
+++ b/frontend-modern/browser-verification.json
@@ -1,43 +1,36 @@
{
"version": 1,
- "base_sha": "e0baecc418d15a6638ef80ed1e2b39d08aa9a5ad",
- "verified_at": "2026-08-27T18:57:57Z",
+ "base_sha": "81b09d870fb39112cbcef70becf09d6f30d77393",
+ "verified_at": "2026-08-27T19:35:10Z",
"result": "passed",
"changed_paths": [
- "frontend-modern/src/components/Storage/StorageDetailKeyValueRow.tsx",
- "frontend-modern/src/components/shared/InfoCardFrame.tsx",
- "frontend-modern/src/components/shared/cards/DisksCard.tsx",
- "frontend-modern/src/components/shared/cards/HardwareCard.tsx",
- "frontend-modern/src/components/shared/cards/RootDiskCard.tsx",
- "frontend-modern/src/components/shared/cards/SystemInfoCard.tsx",
- "frontend-modern/src/components/shared/cards/TemperaturesCard.tsx",
- "frontend-modern/src/features/storageBackups/detailPresentation.ts"
+ "frontend-modern/src/components/Infrastructure/AvailabilityProbeStatusCard.tsx",
+ "frontend-modern/src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx",
+ "frontend-modern/src/components/Workloads/AvailabilityProbeSuggestionCard.tsx",
+ "frontend-modern/src/features/docker/DockerHostDrawerOverview.tsx"
],
"content_sha256": {
- "frontend-modern/src/components/Storage/StorageDetailKeyValueRow.tsx": "db827a709c0f018c24dd0821ae9845022a2ba15c7052b6471926957aafdf6270",
- "frontend-modern/src/components/shared/InfoCardFrame.tsx": "0819bce063e2caf72ffbbd3beb398fd4776a7fe089da7eac5c899bd92fffe66c",
- "frontend-modern/src/components/shared/cards/DisksCard.tsx": "f9721f90d6b1c1a7030bbc1767c90a4d353d8c4a82843e47ad37aae8f687c46d",
- "frontend-modern/src/components/shared/cards/HardwareCard.tsx": "66df4609cc019cf5a7d0928abb82a2ad88f99683cd277ee1f0e38b9b48d281dc",
- "frontend-modern/src/components/shared/cards/RootDiskCard.tsx": "48a1698a5781639a2fcb027837edc6c7b580e392b37041c89911f23c71d80fc6",
- "frontend-modern/src/components/shared/cards/SystemInfoCard.tsx": "723fab36dbd6eeaf882f6eb89d2d0c7c276f5b930c17bfcbc44413a13f531880",
- "frontend-modern/src/components/shared/cards/TemperaturesCard.tsx": "f91cecf1de23abec0b7b571b02516643206ba2b27f7cb37cd8b941f2588229dd",
- "frontend-modern/src/features/storageBackups/detailPresentation.ts": "6dd2da6052aa37e6cfe2488356a296c578c26f7aed3ee8e49f6a5362135b34e7"
+ "frontend-modern/src/components/Infrastructure/AvailabilityProbeStatusCard.tsx": "2d991718c178866ba5bd7d1b89e7a1a9bec6fcd30133bc2fd549aa2fd3ccf4e5",
+ "frontend-modern/src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx": "ac68e2e7f5d954ca5bd23b44f347817ce9a39414ab493d22ad52340ceb3296e2",
+ "frontend-modern/src/components/Workloads/AvailabilityProbeSuggestionCard.tsx": "a8c549b1284befee652c9ecc79c3c449602d1a102f3867acb81f4a5c9f5fd042",
+ "frontend-modern/src/features/docker/DockerHostDrawerOverview.tsx": "ab63fba8e1a06cb5951e0d3dc637d92ef371f2b5db5da2dfb80408cd477c0ea5"
},
- "routes": ["/standalone/machines", "/proxmox/storage"],
+ "routes": ["/standalone/availability", "/proxmox/backups/date", "/docker/overview"],
"viewports": [
{ "width": 1920, "height": 800 },
{ "width": 390, "height": 844 }
],
"states": [
- "Apollo-114 expanded with Platform details and Machine details visible",
- "west-f-service-pool expanded with Configuration and ZFS Pool cards visible"
+ "Solar inverter web panel expanded with availability facts visible",
+ "backup-vault expanded with Platform details and PBS service facts visible",
+ "auth-service-01 expanded on Manage with Container updates visible"
],
"interactions": [
- "expanded the Apollo-114 row, opened Platform details, and revealed the nested Machine details",
- "confirmed System, Hardware, Disks, and temperature facts use an adjacent fixed label track at 1920px",
- "confirmed machine facts retain condensed right-aligned values and clean wrapping at 390px",
- "expanded west-f-service-pool and confirmed Configuration values sit adjacent to their labels at 1920px",
- "confirmed storage Configuration values retain condensed right alignment and clean wrapping at 390px",
- "reloaded the phone machine route and repeated the complete disclosure interaction"
+ "expanded the Solar inverter web panel and confirmed desktop availability values use an adjacent fixed label track",
+ "confirmed availability facts retain condensed right-aligned values and clean wrapping at 390px",
+ "expanded backup-vault, opened Platform details, and revealed the PBS service section",
+ "confirmed PBS service facts use adjacent desktop values and retain compact mobile alignment",
+ "expanded auth-service-01, selected Manage, and confirmed Container updates facts use adjacent desktop values",
+ "confirmed Docker management facts retain condensed right alignment at 390px"
]
}
diff --git a/frontend-modern/scripts/shared-template-registry.json b/frontend-modern/scripts/shared-template-registry.json
index a697ac9c0..13a0f3426 100644
--- a/frontend-modern/scripts/shared-template-registry.json
+++ b/frontend-modern/scripts/shared-template-registry.json
@@ -466,6 +466,7 @@
{ "path": "src/components/shared/cards/RootDiskCard.tsx" },
{ "path": "src/components/shared/cards/SystemInfoCard.tsx" },
{ "path": "src/components/shared/cards/TemperaturesCard.tsx" },
+ { "path": "src/components/Workloads/AvailabilityProbeSuggestionCard.tsx" },
{ "path": "src/components/Workloads/DrawerDiskListCard.tsx" },
{ "path": "src/features/docker/DockerHostDrawerOverview.tsx" },
{ "path": "src/features/storageBackups/detailPresentation.ts" }
diff --git a/frontend-modern/src/components/Infrastructure/AvailabilityProbeStatusCard.tsx b/frontend-modern/src/components/Infrastructure/AvailabilityProbeStatusCard.tsx
index e4144e020..f16bffbfe 100644
--- a/frontend-modern/src/components/Infrastructure/AvailabilityProbeStatusCard.tsx
+++ b/frontend-modern/src/components/Infrastructure/AvailabilityProbeStatusCard.tsx
@@ -2,7 +2,7 @@ import { For, Show, createMemo } from 'solid-js';
import { Activity, AlertCircle, Check } from 'lucide-solid';
import type { ResourceAvailabilityMeta } from '@/types/resource';
-import { InfoCardFrame } from '@/components/shared/InfoCardFrame';
+import { InfoCardFrame, InfoCardKeyValueRow } from '@/components/shared/InfoCardFrame';
import {
getAvailabilityProbeMethodLabel,
getAvailabilityProbeEndpointLabel,
@@ -129,130 +129,111 @@ export function AvailabilityProbeStatusCard(props: AvailabilityProbeStatusCardPr
-
- Latency
- —}
- >
- —}
>
- {latency()}
-
-
-
-
- Method
-
- {method()}
-
-
-
- Target
-
- {targetAddr()}
-
-
+
+ {latency()}
+
+
+ }
+ />
+
+
-
- Checked
- {lastChecked()}
-
+
-
- Freshness
-
- {presentation()?.freshnessLabel ?? 'freshness unknown'}
-
-
+
{(label) => (
-
- Resource
- {label()}
-
+
)}
{(cert) => (
-
- Certificate
-
- {certificateTrust().label}
-
-
+
-
- Subject
-
- {cert().subject}
-
-
+
{(expiry) => (
-
- Expires
-
- {expiry()}
-
-
+
)}
-
- Hostname
-
- {cert().hostnameValid ? 'Matches' : 'Mismatch'}
-
-
+
-
- Issuer
-
- {cert().issuer}
-
-
+
{(fingerprint) => (
-
- SHA-256
-
- {fingerprint().slice(0, 16)}…
-
-
+
)}
diff --git a/frontend-modern/src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx b/frontend-modern/src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx
index 814e3f640..9f84d2b00 100644
--- a/frontend-modern/src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx
+++ b/frontend-modern/src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx
@@ -18,7 +18,7 @@ import { RaidCard } from '@/components/shared/cards/RaidCard';
import { DiscoveryTab } from '@/components/Discovery/DiscoveryTab';
import { DiscoveryLoadingFallback } from '@/components/shared/DiscoveryLoadingFallback';
import { FormSelect } from '@/components/shared/FormSelect';
-import { InfoCardFrame } from '@/components/shared/InfoCardFrame';
+import { InfoCardFrame, InfoCardKeyValueRow } from '@/components/shared/InfoCardFrame';
import { WebInterfaceUrlField } from '@/components/shared/WebInterfaceUrlField';
import {
WEB_INTERFACE_LINK_COLOR_CLASS,
@@ -575,31 +575,27 @@ export const ResourceDetailDrawerOverviewTab: Component{sourceTypePresentation.label}
-
- Confidence
-
- {formatConfidenceLabel(change.confidence)}
-
-
-
- Adapter
-
- {sourceAdapterPresentation?.label || '—'}
-
-
+
+
-
- Actor
- {change.actor}
-
+
-
- Transition
-
- {change.from || '—'} → {change.to || '—'}
-
-
+
@@ -726,27 +722,24 @@ export const ResourceDetailDrawerOverviewTab: Component
-
- Containers
-
- {formatInteger(drawer.dockerContainerCount())}
-
-
-
- Updates
- 0 ? 'text-sky-700 dark:text-sky-300' : 'text-base-content'}`}
- >
- {formatInteger(drawer.dockerUpdatesAvailable())}
-
-
+
+
0
+ ? 'text-sky-700 dark:text-sky-300'
+ : ''
+ }
+ />
-
- Checked
-
- {drawer.dockerUpdatesCheckedRelative()}
-
-
+
@@ -758,24 +751,24 @@ export const ResourceDetailDrawerOverviewTab: Component
-
- Action
-
- {formatIdentifierLabel(drawer.dockerHostCommand()?.type, {
- fallback: 'command',
- })}
-
-
-
- State
-
- {formatIdentifierLabel(drawer.dockerHostCommand()?.status, {
- fallback: 'unknown',
- })}
-
-
+
+
-
- State
-
- {connection.label}
-
-
+
-
- Version
- {pbs().version}
-
+
-
- Uptime
-
- {formatUptime(pbs().uptimeSeconds ?? resource.uptime ?? 0)}
-
-
+
0}>
-
- Active tasks
-
- {formatInteger(drawer.pbsActiveTaskCount())}
-
-
+
@@ -1141,25 +1127,19 @@ export const ResourceDetailDrawerOverviewTab: Component
-
- State
-
- {connection.label}
-
-
+
-
- Version
- {pmg().version}
-
+
-
- Uptime
-
- {formatUptime(pmg().uptimeSeconds ?? resource.uptime ?? 0)}
-
-
+
@@ -1187,22 +1167,21 @@ export const ResourceDetailDrawerOverviewTab: Component
-
- Nodes
-
- {formatInteger(pmg().nodeCount)}
-
-
+
-
- Updated
-
- {drawer.pmgUpdatedRelative()}
-
-
+
@@ -1213,14 +1192,13 @@ export const ResourceDetailDrawerOverviewTab: Component
{(entry) => (
-
- {entry.label}
-
- {formatInteger(entry.value)}
-
-
+
)}
@@ -1232,12 +1210,10 @@ export const ResourceDetailDrawerOverviewTab: Component
{(entry) => (
-
- {entry.label}
-
- {formatInteger(entry.value)}
-
-
+
)}
diff --git a/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.history.test.tsx b/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.history.test.tsx
index 7ee1fd8ca..5753f8901 100644
--- a/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.history.test.tsx
+++ b/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.history.test.tsx
@@ -802,6 +802,12 @@ describe('ResourceDetailDrawer change history section', () => {
expect(panel.getByText('Routine restart requested')).toBeInTheDocument();
expect(panel.getByText('Confidence')).toBeInTheDocument();
expect(panel.getByText('Adapter')).toBeInTheDocument();
+ expect(panel.getByText('Confidence').parentElement).toHaveClass(
+ 'justify-between',
+ 'lg:grid',
+ 'lg:grid-cols-[7rem_minmax(0,1fr)]',
+ );
+ expect(panel.getByText('High')).toHaveClass('text-right', 'lg:text-left');
expect(panel.getByText('Metadata')).toBeInTheDocument();
expect(panel.getByText(/"ticket": "INC-1234"/)).toBeInTheDocument();
expect(panel.queryByText('Capabilities')).toBeNull();
diff --git a/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.service-cards.test.tsx b/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.service-cards.test.tsx
index e702469b1..5ef3e9ff4 100644
--- a/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.service-cards.test.tsx
+++ b/frontend-modern/src/components/Infrastructure/__tests__/ResourceDetailDrawer.service-cards.test.tsx
@@ -113,6 +113,12 @@ describe('ResourceDetailDrawer service cards', () => {
expect(serviceDetails.queryByText('Connection')).toBeNull();
expect(serviceDetails.getAllByText('State').length).toBeGreaterThan(0);
expect(serviceDetails.getAllByText('pbs-main.local').length).toBeGreaterThan(0);
+ expect(serviceDetails.getByText('State').parentElement).toHaveClass(
+ 'justify-between',
+ 'lg:grid',
+ 'lg:grid-cols-[7rem_minmax(0,1fr)]',
+ );
+ expect(serviceDetails.getByText('Healthy')).toHaveClass('text-right', 'lg:text-left');
expect(queryByText('Backup summary')).toBeNull();
expect(queryByText('Job breakdown')).toBeNull();
expect(queryByText('Types')).toBeNull();
@@ -307,6 +313,12 @@ describe('ResourceDetailDrawer service cards', () => {
expect(serviceDetails.queryByText('Connection')).toBeNull();
expect(serviceDetails.getAllByText('State').length).toBeGreaterThan(0);
expect(serviceDetails.getAllByText('pmg-main.local').length).toBeGreaterThan(0);
+ expect(serviceDetails.getByText('State').parentElement).toHaveClass(
+ 'justify-between',
+ 'lg:grid',
+ 'lg:grid-cols-[7rem_minmax(0,1fr)]',
+ );
+ expect(serviceDetails.getByText('Healthy')).toHaveClass('text-right', 'lg:text-left');
expect(queryByText('Mail flow summary')).toBeNull();
expect(queryByText('Queue breakdown')).toBeNull();
expect(queryByText('Mail processing')).toBeNull();
@@ -384,6 +396,11 @@ describe('ResourceDetailDrawer service cards', () => {
expect(getByText('18 containers · 4 updates')).toBeInTheDocument();
fireEvent.click(getByRole('button', { name: 'Show service' }));
expect(getByText('Docker runtime')).toBeInTheDocument();
+ expect(getByText('Containers').parentElement).toHaveClass(
+ 'justify-between',
+ 'lg:grid',
+ 'lg:grid-cols-[7rem_minmax(0,1fr)]',
+ );
expect(queryByText('Container Updates')).toBeNull();
expect(queryByText('Check now')).toBeNull();
expect(queryByText('Show update controls')).toBeNull();
diff --git a/frontend-modern/src/components/Workloads/AvailabilityProbeSuggestionCard.tsx b/frontend-modern/src/components/Workloads/AvailabilityProbeSuggestionCard.tsx
index c8d549c16..f2e3dedcb 100644
--- a/frontend-modern/src/components/Workloads/AvailabilityProbeSuggestionCard.tsx
+++ b/frontend-modern/src/components/Workloads/AvailabilityProbeSuggestionCard.tsx
@@ -7,7 +7,7 @@ import {
type AvailabilityTarget,
} from '@/api/availabilityTargets';
import type { AvailabilityProbeSuggestion } from '@/types/discovery';
-import { InfoCardFrame } from '@/components/shared/InfoCardFrame';
+import { InfoCardFrame, InfoCardKeyValueRow } from '@/components/shared/InfoCardFrame';
interface AvailabilityProbeSuggestionCardProps {
suggestion: AvailabilityProbeSuggestion;
@@ -64,28 +64,19 @@ export function AvailabilityProbeSuggestionCard(props: AvailabilityProbeSuggesti
-
- Service
-
- {props.suggestion.service_name}
-
-
-
- Probe
- {protocolLabel()}
-
-
- Target
-
- {props.suggestion.address}
-
-
+
+
+
{error()}
diff --git a/frontend-modern/src/components/Workloads/__tests__/AvailabilityProbeStatusCard.test.tsx b/frontend-modern/src/components/Workloads/__tests__/AvailabilityProbeStatusCard.test.tsx
index e9797623d..89c591e98 100644
--- a/frontend-modern/src/components/Workloads/__tests__/AvailabilityProbeStatusCard.test.tsx
+++ b/frontend-modern/src/components/Workloads/__tests__/AvailabilityProbeStatusCard.test.tsx
@@ -21,6 +21,12 @@ describe('AvailabilityProbeStatusCard', () => {
expect(screen.getByText('Not checked')).toBeInTheDocument();
expect(screen.queryByText('Down')).not.toBeInTheDocument();
expect(screen.getByText('freshness unknown')).toBeInTheDocument();
+ expect(screen.getByText('Latency').parentElement).toHaveClass(
+ 'justify-between',
+ 'lg:grid',
+ 'lg:grid-cols-[7rem_minmax(0,1fr)]',
+ );
+ expect(screen.getByText('freshness unknown')).toHaveClass('text-right', 'lg:text-left');
});
it('shows stale evidence and an unresolved canonical resource link', () => {
diff --git a/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts b/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts
index a74750013..6364fec79 100644
--- a/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts
+++ b/frontend-modern/src/components/shared/SharedPrimitives.guardrails.test.ts
@@ -1171,6 +1171,7 @@ describe('shared primitive guardrails', () => {
'src/components/shared/cards/RootDiskCard.tsx',
'src/components/shared/cards/SystemInfoCard.tsx',
'src/components/shared/cards/TemperaturesCard.tsx',
+ 'src/components/Workloads/AvailabilityProbeSuggestionCard.tsx',
'src/components/Workloads/DrawerDiskListCard.tsx',
'src/features/docker/DockerHostDrawerOverview.tsx',
'src/features/storageBackups/detailPresentation.ts',
@@ -1233,6 +1234,19 @@ describe('shared primitive guardrails', () => {
expect(source).toContain('InfoCardKeyValueRow');
expect(source).not.toContain('flex items-center justify-between');
}
+
+ for (const consumerPath of [
+ 'src/components/Infrastructure/AvailabilityProbeStatusCard.tsx',
+ 'src/components/Infrastructure/ResourceDetailDrawerOverviewTab.tsx',
+ 'src/components/Workloads/AvailabilityProbeSuggestionCard.tsx',
+ 'src/features/docker/DockerHostDrawerOverview.tsx',
+ ]) {
+ const source = readFrontendSource(consumerPath);
+ expect(source).toContain('InfoCardKeyValueRow');
+ expect(source).not.toMatch(
+ /class="flex items-(?:center|start) justify-between gap-2">\s*/,
+ );
+ }
});
it('keeps shared subtabs as one primitive and leaves shell styling to owning surfaces', () => {
diff --git a/frontend-modern/src/features/docker/DockerHostDrawerOverview.tsx b/frontend-modern/src/features/docker/DockerHostDrawerOverview.tsx
index 9458063fb..44ec32a69 100644
--- a/frontend-modern/src/features/docker/DockerHostDrawerOverview.tsx
+++ b/frontend-modern/src/features/docker/DockerHostDrawerOverview.tsx
@@ -5,7 +5,7 @@ import {
type DrawerDiskListItem,
} from '@/components/Workloads/DrawerDiskListCard';
import { AvailabilityProbeStatusCards } from '@/components/Infrastructure/AvailabilityProbeStatusCard';
-import { InfoCardFrame } from '@/components/shared/InfoCardFrame';
+import { InfoCardFrame, InfoCardKeyValueRow } from '@/components/shared/InfoCardFrame';
import { TechnicalDetailsSection } from '@/components/shared/TechnicalDetailsDisclosure';
import { DrawerAttentionSection } from '@/components/shared/DrawerAttentionSection';
import {
@@ -99,32 +99,19 @@ export function DockerHostDrawerManagement(props: DockerHostDrawerOverviewProps)
Container updates
-
- Available
- {updatesAvailable()}
-
+
{(timestamp) => (
-
- Last checked
- {formatRelativeTime(timestamp)}
-
+
)}
-
-
- {titleCase(cleanText(hostCommand()?.type).replace(/_/g, ' ') || 'Command')}
-
-
- {titleCase(cleanText(hostCommand()?.status).replace(/_/g, ' ') || 'unknown')}
-
-
+