feat(kilo-ui): add hover-revealed diff viewer button to edit tool header

Introduce an icon button that appears on hover within the edit-tool
trigger, allowing users to open the diff viewer directly from the
tool header without clicking the file path.

- Add "Open in Diff Viewer" IconButton with tooltip inside edit trigger
- Extract openDiff logic into reusable handler with dedicated click handler
- Style the action button with opacity transition on parent hover/focus
- Add i18n string for "Open in Diff Viewer" label
This commit is contained in:
Imanol Maiztegui
2026-04-30 14:39:18 +02:00
parent 1338266da9
commit 006600b69d
3 changed files with 65 additions and 7 deletions
@@ -33,6 +33,39 @@
}
}
/* Hover-revealed "Open in Diff Viewer" icon button in the edit-tool header */
[data-component="tool-trigger"] [data-slot="basic-tool-tool-info"]:has([data-component="edit-trigger"]) {
flex: 1 1 auto;
}
[data-component="edit-trigger"] {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
min-width: 0;
[data-slot="message-part-title-area"] {
flex: 0 1 auto;
min-width: 0;
overflow: hidden;
}
[data-slot="edit-trigger-actions"] {
flex-shrink: 0;
margin-left: auto;
display: inline-flex;
align-items: center;
opacity: 0;
transition: opacity 0.15s ease;
}
}
[data-component="tool-trigger"]:hover [data-slot="edit-trigger-actions"],
[data-slot="edit-trigger-actions"]:focus-within {
opacity: 1;
}
/* Prevent long title/path from hiding the collapsible expand arrow */
[data-component="edit-trigger"],
[data-component="write-trigger"] {
@@ -2039,17 +2039,22 @@ ToolRegistry.register({
const canOpenDiff = () => !!data.openDiff && !!path() && (before() !== "" || after() !== "")
const canOpenFile = () => !!data.openFile && !!path()
const openDiff = () => {
if (!canOpenDiff()) return
data.openDiff!({
file: path(),
before: before(),
after: after(),
additions: props.metadata?.filediff?.additions ?? 0,
deletions: props.metadata?.filediff?.deletions ?? 0,
})
}
const handleFileClick = (e: MouseEvent) => {
e.stopPropagation()
if (canOpenDiff()) {
data.openDiff!({
file: path(),
before: before(),
after: after(),
additions: props.metadata?.filediff?.additions ?? 0,
deletions: props.metadata?.filediff?.deletions ?? 0,
})
openDiff()
return
}
@@ -2058,6 +2063,11 @@ ToolRegistry.register({
}
}
const handleOpenDiffClick = (e: MouseEvent) => {
e.stopPropagation()
openDiff()
}
return (
<div data-component="edit-tool">
<BasicTool
@@ -2084,6 +2094,20 @@ ToolRegistry.register({
</Show>
</div>
</div>
<Show when={canOpenDiff()}>
<span data-slot="edit-trigger-actions">
<Tooltip value={i18n.t("ui.messagePart.openInDiffViewer")} placement="top" gutter={4}>
<IconButton
icon="square-arrow-top-right"
size="small"
variant="ghost"
onMouseDown={(e) => e.preventDefault()}
onClick={handleOpenDiffClick}
aria-label={i18n.t("ui.messagePart.openInDiffViewer")}
/>
</Tooltip>
</span>
</Show>
</div>
}
>
+1
View File
@@ -73,6 +73,7 @@ export const dict: Record<string, string> = {
"ui.messagePart.mcp.output": "Output",
"ui.messagePart.title.edit": "Edit",
"ui.messagePart.title.write": "Write",
"ui.messagePart.openInDiffViewer": "Open in Diff Viewer",
"ui.messagePart.option.typeOwnAnswer": "Type your own answer",
"ui.messagePart.review.title": "Review your answers",
"ui.messagePart.questions.dismissed": "Questions dismissed",