From 826eaf2a1275b59dfc22f372958665223a0ebbe8 Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Sun, 4 Oct 2026 00:47:28 +0100 Subject: [PATCH] Forward native and delegated guest row handlers through typed props Match the existing shared TableRow splitProps pattern so the JSX lint check recognises distinct native eligibility and delegated action handlers. Preserve the same callback ordering, conditional removal, identity and keyboard controls; repeat the production guest/full-drawer browser pass for the final binding. Change-source: pulse-maintainer Contract-Neutral: Typed handler forwarding preserves the already-contracted touch eligibility, actions, child isolation, accessibility, row identity and state; no contract delta. --- .../9596a94267f10b6d.json | 44 +++++++++++++++++++ .../src/components/Workloads/GuestRow.tsx | 7 +-- 2 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 frontend-modern/browser-verification/9596a94267f10b6d.json diff --git a/frontend-modern/browser-verification/9596a94267f10b6d.json b/frontend-modern/browser-verification/9596a94267f10b6d.json new file mode 100644 index 0000000000..b18aa6a289 --- /dev/null +++ b/frontend-modern/browser-verification/9596a94267f10b6d.json @@ -0,0 +1,44 @@ +{ + "version": 1, + "base_sha": "d856689f5b3b200c942db4151a0b657cfdacf1c4", + "verified_at": "2026-10-03T23:44:57.288Z", + "result": "passed", + "changed_paths": [ + "frontend-modern/src/components/Workloads/GuestRow.tsx" + ], + "content_sha256": { + "frontend-modern/src/components/Workloads/GuestRow.tsx": "e531b8c4584a8a8f4c76a3205b472ae6cc41c15780cf70a0205b06f7bdf553ed" + }, + "routes": [ + "/browser-tests/guest-row-touch.html?kind=qemu", + "/browser-tests/guest-row-touch.html?kind=lxc", + "/browser-tests/table-row-touch.html" + ], + "viewports": [ + { + "width": 1365, + "height": 900 + }, + { + "width": 390, + "height": 844 + }, + { + "width": 360, + "height": 844 + } + ], + "states": [ + "Production GuestRow and full GuestDrawer, production CSS and delegated actions, synthetic VM/CT observations. Playwright 1.56.1 matches integration lock; Chromium 141.0.7390.37 desktop/phone and WebKit 26.0 phone. Six screenshots opened and inspected.", + "Trusted first name/row-body activation reveals missing completed backup, separately cautionary running activity and retained VM-lock disk guidance. The 360px CT control uses the row body. Full drawer safety copy wraps without page overflow; the two-column fixture is not full Workloads table layout acceptance.", + "Row remains a table row, not an extra tab stop or duplicate expanded control. Native disclosure retains matching aria-expanded and aria-controls, conditional action removal/re-enable preserves the same row node.", + "Emulated input and presentation only: no physical phone, real guest collector, QGA/thaw, installed recovery or released-availability assertion. Earlier failed parent activation and two adverse harness runs remain retained separately.", + "Final GuestRow uses typed splitProps forwarding, matching the shared TableRow native/delegated pattern after the initial JSX lint failure. No lint rule was disabled; all browser interaction checks rerun on these exact final bytes." + ], + "interactions": [ + "Trusted Playwright touch taps emit click and toggle the same row exactly once; repeated name/row taps and production drawer collapse preserve independent action counts. Touch entry does not activate a hover history lens.", + "Focused native disclosure Enter/Space and nested SVG click each toggle once. The row body remains usable while keyboard focus makes compact disclosure visible. No touch-end or pointer-up action is added.", + "Real adjacent external-link SVG is exercised on the actual wide layout with only navigation prevented; production propagation isolation keeps the row closed. Phone identity intentionally hides that link; it is not forced into a non-condensed phone layout.", + "Removing the row action prevents activation and removes disclosure; re-enabling restores first-tap activation without remount. Exported compatibility marker preserves shared TableRow single action and delegated child-button isolation. Guest fixtures issue only local GET requests and report no page errors." + ] +} diff --git a/frontend-modern/src/components/Workloads/GuestRow.tsx b/frontend-modern/src/components/Workloads/GuestRow.tsx index 8254fed215..784665c66b 100644 --- a/frontend-modern/src/components/Workloads/GuestRow.tsx +++ b/frontend-modern/src/components/Workloads/GuestRow.tsx @@ -1,4 +1,4 @@ -import { createMemo, createSignal, Show } from 'solid-js'; +import { createMemo, createSignal, Show, splitProps } from 'solid-js'; import BoxIcon from 'lucide-solid/icons/box'; import type { VM } from '@/types/api'; import type { WorkloadGuest } from '@/types/workloads'; @@ -50,6 +50,7 @@ export type { GuestRowProps, WorkloadIOEmphasis } from './guestRowModel'; import { getGuestColumnStyle } from './guestRowModel'; export function GuestRow(props: GuestRowProps) { + const [rowActionProps] = splitProps(props, ['onClick']); const { agentVersion, appContainerRuntimeBadge, @@ -242,8 +243,8 @@ export function GuestRow(props: GuestRowProps) { : undefined } data-summary-row-active={props.isSummaryHighlighted && !props.isExpanded ? 'true' : 'false'} - on:click={props.onClick ? nativeRowClickTarget : undefined} - onClick={props.onClick} + on:click={rowActionProps.onClick ? nativeRowClickTarget : undefined} + {...rowActionProps} {...interactiveRowHandlers} > {/* Name - always visible */}