Implement shared compact split and unified tool-call diff layout (#270)

# PR Title

Implement shared compact split and unified tool-call diff layout

---
Fixes #268 
# PR Description

## Summary

This PR makes tool-call diffs more compact in both `Unified` and `Split`
views by reducing wasted horizontal space in line-number gutters and
content indentation.

## What changed

- introduced a shared compact-diff framework for tool-call diffs
- kept mobile-specific policy limited to:
  - forcing unified mode below the breakpoint
  - enabling wrap only in mobile unified mode
- added mode-specific compact applicators in the diff viewer:
  - unified applicator
  - split applicator
- reduced gutter width waste by measuring rendered line-number text and
tightening column width around it
- removed unnecessary right-side content padding
- aligned `+` / `-` markers closer to the left edge across both views
- simplified cleanup after gatekeeper review by removing extra plumbing
and residue

## Screenshots

### Before

<img width="581" height="341" alt="image"
src="https://github.com/user-attachments/assets/ec47b256-749a-4afc-8879-aaf33f0b46b6"
/>

### After

<img width="470" height="586" alt="image"
src="https://github.com/user-attachments/assets/7258a5a2-47c4-408d-84bc-1b497761c7ad"
/>

## Architectural approach

This change intentionally uses:

- shared policy in
`packages/ui/src/components/tool-call/diff-render.tsx`
- shared helper/measurement logic in
`packages/ui/src/components/diff-viewer.tsx`
- mode-specific applicators where unified and split DOM differ
- CSS for shared visual spacing and alignment cleanup

The goal was to keep the implementation architecturally clean and avoid
building separate duplicated compact-diff features for:

- mobile vs desktop
- unified vs split

Instead, the feature shares one compact-diff concept and only diverges
where the upstream diff DOM requires separate handling.

## Files changed

- `packages/ui/src/components/tool-call/diff-render.tsx`
- `packages/ui/src/components/diff-viewer.tsx`
- `packages/ui/src/styles/messaging/tool-call.css`
- `packages/ui/src/types/message.ts`

## Validation

Manual validation was performed in the running UI.

Verified manually:

- compact unified gutters on mobile
- compact unified gutters on desktop
- compact split gutters on desktop
- tighter operator alignment in both modes

Also verified:

- `npm run typecheck` passes

## Notes

- This PR is intended to address the compact diff layout problem
described in the related issue.
- Diff-specific CSS still lives in `tool-call.css`; future extraction
into a smaller dedicated stylesheet is possible but not required for
this change.

---------

Co-authored-by: Shantur Rathore <i@shantur.com>
This commit is contained in:
VooDisss
2026-04-02 01:13:32 +03:00
committed by GitHub
parent df16b64a95
commit 4f236ce36f
11 changed files with 384 additions and 35 deletions

View File

@@ -18,6 +18,11 @@ export const toolCallMessages = {
"toolCall.diff.viewMode.ariaLabel": "Diff view mode",
"toolCall.diff.viewMode.split": "Split",
"toolCall.diff.viewMode.unified": "Unified",
"toolCall.diff.switchToSplit": "Switch to split view",
"toolCall.diff.switchToUnified": "Switch to unified view",
"toolCall.diff.enableWordWrap": "Enable word wrap",
"toolCall.diff.disableWordWrap": "Disable word wrap",
"toolCall.diff.copyPatch": "Copy patch",
"toolCall.diagnostics.title": "Diagnostics",
"toolCall.diagnostics.ariaLabel": "Diagnostics",

View File

@@ -18,6 +18,11 @@ export const toolCallMessages = {
"toolCall.diff.viewMode.ariaLabel": "Modo de vista de diff",
"toolCall.diff.viewMode.split": "Dividida",
"toolCall.diff.viewMode.unified": "Unificada",
"toolCall.diff.switchToSplit": "Cambiar a vista dividida",
"toolCall.diff.switchToUnified": "Cambiar a vista unificada",
"toolCall.diff.enableWordWrap": "Activar ajuste de línea",
"toolCall.diff.disableWordWrap": "Desactivar ajuste de línea",
"toolCall.diff.copyPatch": "Copiar patch",
"toolCall.diagnostics.title": "Diagnósticos",
"toolCall.diagnostics.ariaLabel": "Diagnósticos",

View File

@@ -18,6 +18,11 @@ export const toolCallMessages = {
"toolCall.diff.viewMode.ariaLabel": "Mode d'affichage du diff",
"toolCall.diff.viewMode.split": "Côte à côte",
"toolCall.diff.viewMode.unified": "Unifié",
"toolCall.diff.switchToSplit": "Passer à la vue côte à côte",
"toolCall.diff.switchToUnified": "Passer à la vue unifiée",
"toolCall.diff.enableWordWrap": "Activer le retour à la ligne",
"toolCall.diff.disableWordWrap": "Désactiver le retour à la ligne",
"toolCall.diff.copyPatch": "Copier le patch",
"toolCall.diagnostics.title": "Diagnostics",
"toolCall.diagnostics.ariaLabel": "Diagnostics",

View File

@@ -18,6 +18,11 @@ export const toolCallMessages = {
"toolCall.diff.viewMode.ariaLabel": "מצב תצוגת diff",
"toolCall.diff.viewMode.split": "מפוצל",
"toolCall.diff.viewMode.unified": "מאוחד",
"toolCall.diff.switchToSplit": "עבור לתצוגה מפוצלת",
"toolCall.diff.switchToUnified": "עבור לתצוגה מאוחדת",
"toolCall.diff.enableWordWrap": "הפעל גלישת מילים",
"toolCall.diff.disableWordWrap": "כבה גלישת מילים",
"toolCall.diff.copyPatch": "העתק patch",
"toolCall.diagnostics.title": "אבחון",
"toolCall.diagnostics.ariaLabel": "אבחון",

View File

@@ -18,6 +18,11 @@ export const toolCallMessages = {
"toolCall.diff.viewMode.ariaLabel": "diff 表示モード",
"toolCall.diff.viewMode.split": "分割",
"toolCall.diff.viewMode.unified": "ユニファイド",
"toolCall.diff.switchToSplit": "分割表示に切り替え",
"toolCall.diff.switchToUnified": "ユニファイド表示に切り替え",
"toolCall.diff.enableWordWrap": "折り返しを有効化",
"toolCall.diff.disableWordWrap": "折り返しを無効化",
"toolCall.diff.copyPatch": "パッチをコピー",
"toolCall.diagnostics.title": "診断",
"toolCall.diagnostics.ariaLabel": "診断",

View File

@@ -18,6 +18,11 @@ export const toolCallMessages = {
"toolCall.diff.viewMode.ariaLabel": "Режим просмотра diff",
"toolCall.diff.viewMode.split": "Раздельный",
"toolCall.diff.viewMode.unified": "Единый",
"toolCall.diff.switchToSplit": "Переключить на раздельный вид",
"toolCall.diff.switchToUnified": "Переключить на единый вид",
"toolCall.diff.enableWordWrap": "Включить перенос слов",
"toolCall.diff.disableWordWrap": "Выключить перенос слов",
"toolCall.diff.copyPatch": "Скопировать patch",
"toolCall.diagnostics.title": "Диагностика",
"toolCall.diagnostics.ariaLabel": "Диагностика",

View File

@@ -18,6 +18,11 @@ export const toolCallMessages = {
"toolCall.diff.viewMode.ariaLabel": "Diff 视图模式",
"toolCall.diff.viewMode.split": "分栏",
"toolCall.diff.viewMode.unified": "统一",
"toolCall.diff.switchToSplit": "切换到分栏视图",
"toolCall.diff.switchToUnified": "切换到统一视图",
"toolCall.diff.enableWordWrap": "启用自动换行",
"toolCall.diff.disableWordWrap": "禁用自动换行",
"toolCall.diff.copyPatch": "复制补丁",
"toolCall.diagnostics.title": "诊断",
"toolCall.diagnostics.ariaLabel": "诊断",