diff --git a/oxlint-suppressions.json b/oxlint-suppressions.json
index 91d92173f8b..21fe1a65efb 100644
--- a/oxlint-suppressions.json
+++ b/oxlint-suppressions.json
@@ -839,14 +839,6 @@
"count": 1
}
},
- "web/app/components/base/chat/chat/answer/tool-detail.tsx": {
- "jsx_a11y/click-events-have-key-events": {
- "count": 1
- },
- "jsx_a11y/no-static-element-interactions": {
- "count": 1
- }
- },
"web/app/components/base/chat/chat/answer/workflow-process.tsx": {
"eslint-react/set-state-in-effect": {
"count": 1
diff --git a/web/app/components/base/chat/chat/answer/__tests__/tool-detail.spec.tsx b/web/app/components/base/chat/chat/answer/__tests__/tool-detail.spec.tsx
index 9d362ed5bdc..4a4b37c26a6 100644
--- a/web/app/components/base/chat/chat/answer/__tests__/tool-detail.spec.tsx
+++ b/web/app/components/base/chat/chat/answer/__tests__/tool-detail.spec.tsx
@@ -23,6 +23,9 @@ describe('ToolDetail', () => {
expect(screen.getByText('Test Tool Label')).toBeInTheDocument()
expect(screen.getByText('tools.thought.used')).toBeInTheDocument()
+ expect(
+ screen.getByRole('button', { name: 'tools.thought.used Test Tool Label' }),
+ ).toHaveAttribute('aria-expanded', 'false')
})
it('should render the knowledge label and "using" state when not finished and name is a dataset', () => {
@@ -30,28 +33,47 @@ describe('ToolDetail', () => {
expect(screen.getByText('dataset.knowledge')).toBeInTheDocument()
expect(screen.getByText('tools.thought.using')).toBeInTheDocument()
+ expect(
+ screen.getByRole('button', { name: 'tools.thought.using dataset.knowledge' }),
+ ).toHaveAttribute('aria-expanded', 'false')
})
it('should toggle expansion and show request/response details on click', async () => {
const user = userEvent.setup()
render()
- // Initially collapsed: request/response titles should not be visible
expect(screen.queryByText('tools.thought.requestTitle')).not.toBeInTheDocument()
expect(screen.queryByText(mockPayload.input)).not.toBeInTheDocument()
- // Click to expand
- const label = screen.getByText('Test Tool Label')
- await user.click(label)
+ const toggle = screen.getByRole('button', {
+ name: 'tools.thought.used Test Tool Label',
+ })
+ expect(toggle).toHaveAttribute('aria-expanded', 'false')
+ await user.click(toggle)
- // Now expanded
+ expect(toggle).toHaveAttribute('aria-expanded', 'true')
expect(screen.getByText('tools.thought.requestTitle')).toBeInTheDocument()
expect(screen.getByText(mockPayload.input)).toBeInTheDocument()
expect(screen.getByText('tools.thought.responseTitle')).toBeInTheDocument()
expect(screen.getByText(mockPayload.output)).toBeInTheDocument()
- // Click again to collapse
- await user.click(label)
+ await user.click(toggle)
+ expect(toggle).toHaveAttribute('aria-expanded', 'false')
+ expect(screen.queryByText('tools.thought.requestTitle')).not.toBeInTheDocument()
+ })
+
+ it('should toggle details with Space and Enter', async () => {
+ const user = userEvent.setup()
+ render()
+
+ const toggle = screen.getByRole('button', {
+ name: 'tools.thought.used Test Tool Label',
+ })
+ toggle.focus()
+ await user.keyboard(' ')
+ expect(screen.getByText('tools.thought.requestTitle')).toBeInTheDocument()
+
+ await user.keyboard('{Enter}')
expect(screen.queryByText('tools.thought.requestTitle')).not.toBeInTheDocument()
})
})
diff --git a/web/app/components/base/chat/chat/answer/tool-detail.tsx b/web/app/components/base/chat/chat/answer/tool-detail.tsx
index d56d26a65fc..662846a1d13 100644
--- a/web/app/components/base/chat/chat/answer/tool-detail.tsx
+++ b/web/app/components/base/chat/chat/answer/tool-detail.tsx
@@ -21,20 +21,22 @@ const ToolDetail = ({ payload }: ToolDetailProps) => {
expand && 'border-[0.5px] border-components-panel-border-subtle bg-background-section-burn',
)}
>
-
setExpand(!expand)}
>
- {isFinished &&
}
- {!isFinished &&
}
+ {isFinished &&
}
+ {!isFinished &&
}
{t(($) => $[`thought.${isFinished ? 'used' : 'using'}`], { ns: 'tools' })}
-
{toolLabel}
- {!expand &&
}
- {expand &&
}
-
+ {toolLabel}
+ {!expand && }
+ {expand && }
+
{expand && (
<>