diff --git a/src/public/app/widgets/llm_chat/llm_chat_panel.ts b/src/public/app/widgets/llm_chat/llm_chat_panel.ts index 2feae2cc7..e485cd394 100644 --- a/src/public/app/widgets/llm_chat/llm_chat_panel.ts +++ b/src/public/app/widgets/llm_chat/llm_chat_panel.ts @@ -360,31 +360,60 @@ export default class LlmChatPanel extends BasicWidget { // Fill with tool execution content toolExecutionElement.innerHTML = ` +
+ + Tool Execution + +
-
-
- - Tool Execution -
- -
${this.renderToolStepsHtml(steps)}
`; - // Add event listener for the clear button - const clearButton = toolExecutionElement.querySelector('.tool-execution-chat-clear'); - if (clearButton) { - clearButton.addEventListener('click', (e) => { - e.preventDefault(); - e.stopPropagation(); - toolExecutionElement.remove(); + // Add event listener for the toggle button + const toggleButton = toolExecutionElement.querySelector('.tool-execution-toggle'); + if (toggleButton) { + toggleButton.addEventListener('click', () => { + const stepsContainer = toolExecutionElement.querySelector('.tool-execution-container'); + const icon = toggleButton.querySelector('i'); + + if (stepsContainer) { + if (stepsContainer.classList.contains('collapsed')) { + // Expand + stepsContainer.classList.remove('collapsed'); + (stepsContainer as HTMLElement).style.display = 'block'; + if (icon) { + icon.className = 'bx bx-chevron-down'; + } + } else { + // Collapse + stepsContainer.classList.add('collapsed'); + (stepsContainer as HTMLElement).style.display = 'none'; + if (icon) { + icon.className = 'bx bx-chevron-right'; + } + } + } }); } + + // Add click handler for the header to toggle expansion as well + const header = toolExecutionElement.querySelector('.tool-execution-header'); + if (header) { + header.addEventListener('click', (e) => { + // Only toggle if the click isn't on the toggle button itself + const target = e.target as HTMLElement; + if (target && !target.closest('.tool-execution-toggle')) { + const toggleButton = toolExecutionElement.querySelector('.tool-execution-toggle'); + toggleButton?.dispatchEvent(new Event('click')); + } + }); + (header as HTMLElement).style.cursor = 'pointer'; + } } /** @@ -990,29 +1019,18 @@ export default class LlmChatPanel extends BasicWidget { toolExecutionElement = document.createElement('div'); toolExecutionElement.className = 'chat-tool-execution mb-3'; - // Create header with title and controls + // Create header with title and dropdown toggle const header = document.createElement('div'); header.className = 'tool-execution-header d-flex align-items-center p-2 rounded'; header.innerHTML = ` Tool Execution - `; toolExecutionElement.appendChild(header); - // Add click handler for clear button - const clearButton = toolExecutionElement.querySelector('.tool-execution-chat-clear'); - if (clearButton) { - clearButton.addEventListener('click', () => { - const stepsContainer = toolExecutionElement?.querySelector('.tool-execution-container'); - if (stepsContainer) { - stepsContainer.innerHTML = ''; - } - }); - } - // Create container for tool steps const stepsContainer = document.createElement('div'); stepsContainer.className = 'tool-execution-container p-2 rounded mb-2'; @@ -1020,6 +1038,44 @@ export default class LlmChatPanel extends BasicWidget { // Add to chat messages this.noteContextChatMessages.appendChild(toolExecutionElement); + + // Add click handler for toggle button + const toggleButton = toolExecutionElement.querySelector('.tool-execution-toggle'); + if (toggleButton) { + toggleButton.addEventListener('click', () => { + const stepsContainer = toolExecutionElement?.querySelector('.tool-execution-container'); + const icon = toggleButton.querySelector('i'); + + if (stepsContainer) { + if (stepsContainer.classList.contains('collapsed')) { + // Expand + stepsContainer.classList.remove('collapsed'); + (stepsContainer as HTMLElement).style.display = 'block'; + if (icon) { + icon.className = 'bx bx-chevron-down'; + } + } else { + // Collapse + stepsContainer.classList.add('collapsed'); + (stepsContainer as HTMLElement).style.display = 'none'; + if (icon) { + icon.className = 'bx bx-chevron-right'; + } + } + } + }); + } + + // Add click handler for the header to toggle expansion as well + header.addEventListener('click', (e) => { + // Only toggle if the click isn't on the toggle button itself + const target = e.target as HTMLElement; + if (target && !target.closest('.tool-execution-toggle')) { + const toggleButton = toolExecutionElement?.querySelector('.tool-execution-toggle'); + toggleButton?.dispatchEvent(new Event('click')); + } + }); + (header as HTMLElement).style.cursor = 'pointer'; } // Get the steps container diff --git a/src/public/stylesheets/llm_chat.css b/src/public/stylesheets/llm_chat.css index 58b324069..aacdf543f 100644 --- a/src/public/stylesheets/llm_chat.css +++ b/src/public/stylesheets/llm_chat.css @@ -145,6 +145,11 @@ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); overflow: hidden; max-width: calc(100% - 20px); + transition: all 0.3s ease; +} + +.tool-execution-container.collapsed { + display: none; } .tool-execution-header { @@ -153,6 +158,34 @@ margin-bottom: 0.5rem; color: var(--muted-text-color); font-weight: 500; + padding: 0.6rem 0.8rem; + cursor: pointer; + transition: background-color 0.2s ease; +} + +.tool-execution-header:hover { + background-color: var(--hover-item-background-color, rgba(0, 0, 0, 0.03)); +} + +.tool-execution-toggle { + color: var(--muted-text-color) !important; + background: transparent !important; + padding: 0.2rem 0.4rem !important; + transition: transform 0.2s ease; +} + +.tool-execution-toggle:hover { + color: var(--main-text-color) !important; +} + +.tool-execution-toggle i.bx-chevron-down { + transform: rotate(0deg); + transition: transform 0.3s ease; +} + +.tool-execution-toggle i.bx-chevron-right { + transform: rotate(-90deg); + transition: transform 0.3s ease; } .tool-execution-chat-steps {