mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-19 08:01:19 +00:00
Add image support and mobile UX improvements to export-html
- Display images from read tool results (base64 encoded) - Add ellipsis for truncated tree entries - Make mobile hamburger button more subtle - Add X close button in sidebar header on mobile - Hide hamburger when sidebar is open
This commit is contained in:
parent
c8c7e0fba4
commit
55fd8d9fed
1 changed files with 82 additions and 8 deletions
|
|
@ -95,6 +95,24 @@
|
||||||
border-color: var(--accent);
|
border-color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-close {
|
||||||
|
display: none;
|
||||||
|
padding: 3px 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: inherit;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--muted);
|
||||||
|
border: 1px solid var(--dim);
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-close:hover {
|
||||||
|
color: var(--text);
|
||||||
|
border-color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
.tree-container {
|
.tree-container {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
@ -142,6 +160,8 @@
|
||||||
|
|
||||||
.tree-content {
|
.tree-content {
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-role-user {
|
.tree-role-user {
|
||||||
|
|
@ -355,6 +375,17 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tool-images {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tool-image {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 500px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.expand-hint {
|
.expand-hint {
|
||||||
color: var(--borderAccent);
|
color: var(--borderAccent);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
|
@ -651,15 +682,23 @@
|
||||||
top: 10px;
|
top: 10px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
background: var(--accent);
|
background: var(--container-bg);
|
||||||
color: var(--body-bg);
|
color: var(--muted);
|
||||||
border: none;
|
border: 1px solid var(--dim);
|
||||||
padding: 8px 12px;
|
padding: 6px 10px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 16px;
|
font-size: 14px;
|
||||||
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sidebar-toggle:hover {
|
||||||
|
opacity: 1;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#sidebar-overlay {
|
#sidebar-overlay {
|
||||||
display: none;
|
display: none;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|
@ -695,6 +734,10 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-close {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
padding: 60px 16px 24px;
|
padding: 60px 16px 24px;
|
||||||
}
|
}
|
||||||
|
|
@ -732,6 +775,7 @@
|
||||||
<button class="filter-btn active" data-filter="default" title="Hide settings entries">Default</button>
|
<button class="filter-btn active" data-filter="default" title="Hide settings entries">Default</button>
|
||||||
<button class="filter-btn" data-filter="all" title="Show everything">All</button>
|
<button class="filter-btn" data-filter="all" title="Show everything">All</button>
|
||||||
<button class="filter-btn" data-filter="labeled" title="Only labeled entries">Labels</button>
|
<button class="filter-btn" data-filter="labeled" title="Only labeled entries">Labels</button>
|
||||||
|
<button class="sidebar-close" id="sidebar-close" title="Close">✕</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tree-container" id="tree-container"></div>
|
<div class="tree-container" id="tree-container"></div>
|
||||||
|
|
@ -1355,6 +1399,22 @@
|
||||||
return textBlocks.map(c => c.text).join('\n');
|
return textBlocks.map(c => c.text).join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getResultImages = () => {
|
||||||
|
if (!result) return [];
|
||||||
|
return result.content.filter(c => c.type === 'image');
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderResultImages = () => {
|
||||||
|
const images = getResultImages();
|
||||||
|
if (images.length === 0) return '';
|
||||||
|
let html = '<div class="tool-images">';
|
||||||
|
for (const img of images) {
|
||||||
|
html += `<img src="data:${img.mimeType};base64,${img.data}" class="tool-image" />`;
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
return html;
|
||||||
|
};
|
||||||
|
|
||||||
let html = `<div class="tool-execution ${statusClass}">`;
|
let html = `<div class="tool-execution ${statusClass}">`;
|
||||||
|
|
||||||
const args = call.arguments || {};
|
const args = call.arguments || {};
|
||||||
|
|
@ -1388,6 +1448,11 @@
|
||||||
|
|
||||||
html += `<div class="tool-header"><span class="tool-name">read</span> <span class="tool-path">${pathHtml}</span></div>`;
|
html += `<div class="tool-header"><span class="tool-name">read</span> <span class="tool-path">${pathHtml}</span></div>`;
|
||||||
if (result) {
|
if (result) {
|
||||||
|
// Check for images first (e.g., reading image files)
|
||||||
|
const images = getResultImages();
|
||||||
|
if (images.length > 0) {
|
||||||
|
html += renderResultImages();
|
||||||
|
}
|
||||||
const output = getResultText();
|
const output = getResultText();
|
||||||
if (output) {
|
if (output) {
|
||||||
html += formatExpandableOutput(output, 10, lang);
|
html += formatExpandableOutput(output, 10, lang);
|
||||||
|
|
@ -1706,16 +1771,25 @@
|
||||||
const sidebar = document.getElementById('sidebar');
|
const sidebar = document.getElementById('sidebar');
|
||||||
const overlay = document.getElementById('sidebar-overlay');
|
const overlay = document.getElementById('sidebar-overlay');
|
||||||
|
|
||||||
|
const sidebarToggle = document.getElementById('sidebar-toggle');
|
||||||
|
|
||||||
document.getElementById('sidebar-toggle').addEventListener('click', () => {
|
document.getElementById('sidebar-toggle').addEventListener('click', () => {
|
||||||
sidebar.classList.toggle('open');
|
sidebar.classList.toggle('open');
|
||||||
overlay.classList.toggle('open');
|
overlay.classList.toggle('open');
|
||||||
|
sidebarToggle.style.display = 'none';
|
||||||
});
|
});
|
||||||
|
|
||||||
// Close sidebar when clicking overlay
|
const closeSidebar = () => {
|
||||||
overlay.addEventListener('click', () => {
|
|
||||||
sidebar.classList.remove('open');
|
sidebar.classList.remove('open');
|
||||||
overlay.classList.remove('open');
|
overlay.classList.remove('open');
|
||||||
});
|
sidebarToggle.style.display = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Close sidebar when clicking overlay
|
||||||
|
overlay.addEventListener('click', closeSidebar);
|
||||||
|
|
||||||
|
// Close sidebar when clicking close button
|
||||||
|
document.getElementById('sidebar-close').addEventListener('click', closeSidebar);
|
||||||
|
|
||||||
// Keyboard shortcut: Escape to reset to leaf
|
// Keyboard shortcut: Escape to reset to leaf
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue