Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion app/components/session-hooks-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,17 @@ export default function SessionHooksPanel({ sessionId, initialData }: SessionHoo
return (
<React.Fragment key={`${item.timestamp}-${i}`}>
<tr
tabIndex={0}
role="row"
aria-expanded={isExpanded}
onClick={() => toggleRow(i)}
className={`cursor-pointer transition-colors ${
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
toggleRow(i);
}
}}
className={`cursor-pointer transition-colors focus:outline-none focus:ring-1 focus:ring-ring ${
Comment on lines +330 to +340

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
git ls-files | rg 'app/(components/session-hooks-panel|policies/hooks-client)\.tsx$' || true

echo "== file sizes =="
wc -l app/components/session-hooks-panel.tsx app/policies/hooks-client.tsx

echo "== snippets around affected lines =="
sed -n '300,355p' app/components/session-hooks-panel.tsx
printf '\n---\n'
sed -n '655,705p' app/policies/hooks-client.tsx

echo "== nearby context and role/button occurrences in affected TSX =="
rg -n 'role="button"|tabIndex=0|aria-expanded=|<tr|</tr|onKeyDown=.*e\.key|window\.preventDefault' app/components/session-hooks-panel.tsx app/policies/hooks-client.tsx

Repository: FailproofAI/failproofai

Length of output: 7279


🌐 Web query:

WAI-ARIA grid row role hidden semantics table row role aria-expanded button row

💡 Result:

Under WAI-ARIA standards, a row (role=row) should contain only specific child roles—typically gridcell, columnheader, or rowheader [1][2][3][4]. Placing a button directly as a child of a row is considered invalid according to strict semantic structure, as accessibility APIs expect grid cells to be the immediate children of rows [5]. Regarding your specific architectural questions: 1. Hidden Semantics: If rows or cells are hidden (e.g., via display: none or not present in the DOM), they are excluded from the accessibility tree [6]. To maintain correct row counting and indexing for assistive technologies when rows or columns are missing from the DOM, you must use aria-rowcount, aria-colcount, aria-rowindex, and aria-colindex on the appropriate elements [7][1][6][3]. 2. Button within a Row: Placing a button as a direct child of a row violates the requirement that rows contain only cells [5]. The correct, accessible pattern for an interactive element (like an expand/collapse toggle) inside a row is to place the button inside a gridcell [6][8][5]. 3. aria-expanded: The aria-expanded attribute should be placed on the interactive control (the button) that performs the toggle action, not on the row element itself [9][8]. When a grid requires hierarchical "expand/collapse" behavior (where a row controls the visibility of child rows), the pattern is a treegrid, not a standard grid [10][8]. In a treegrid, the aria-expanded state is managed on the parent row or a cell within that row, indicating whether the child rows are currently visible [9][10]. For most web applications, if you need expandable rows, using the treegrid role with the proper hierarchical ARIA attributes (aria-level, aria-expanded) is the recommended approach [10][8]. Always prefer native HTML table elements (table, tr, td) if the data is tabular, as they provide these semantics automatically [1][3][4]. If you must use ARIA roles for custom layouts, ensure your DOM structure strictly adheres to the required parent-child relationships (grid > row > gridcell) [1][2][3]. Top results: [1], [3], [9], [8], [5]

Citations:


Keep expandable table rows as rows and use an inner disclosure button.

Both interactive rows assign role="button" to native <tr> elements, which replaces the table row semantics from the descendant cells. Keep the <tr> native and move the focus/action semantics to a proper control inside a cell, such as an inner <button> with aria-expanded, keyboard handling, and focus styling.

  • app/components/session-hooks-panel.tsx#L329-L331
  • app/policies/hooks-client.tsx#L677-L679
📍 Affects 2 files
  • app/components/session-hooks-panel.tsx#L330-L340 (this comment)
  • app/policies/hooks-client.tsx#L678-L688
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/session-hooks-panel.tsx` around lines 330 - 340, The
expandable rows in app/components/session-hooks-panel.tsx lines 330-340 and
app/policies/hooks-client.tsx lines 678-688 should retain native <tr> semantics
by removing row-level role, focus, and keyboard interaction. Add an inner
disclosure button within the appropriate cell in each row, moving aria-expanded,
toggleRow behavior, keyboard handling, and focus styling to that button while
preserving the existing expansion behavior.

Source: MCP tools

isDeny
? "bg-red-500/[0.03] hover:bg-red-500/[0.07] border-l-2 border-l-red-500/40"
: isInstruct
Expand Down
11 changes: 10 additions & 1 deletion app/policies/hooks-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -675,8 +675,17 @@ function ActivityTab({
return (
<React.Fragment key={`${item.timestamp}-${i}`}>
<tr
tabIndex={0}
role="row"
aria-expanded={isExpanded}
onClick={() => toggleRow(i)}
className={`activity-data-row cursor-pointer transition-colors ${
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
toggleRow(i);
}
}}
className={`activity-data-row cursor-pointer transition-colors focus:outline-none focus:ring-1 focus:ring-ring ${
isDeny
? "bg-red-500/[0.03] hover:bg-red-500/[0.07] border-l-2 border-l-red-500/40"
: isInstruct
Expand Down