* fix(ui): use absolute positioning for pending changes popover to prevent z-index occlusion by revert dock
* refactor(ui): reuse changedFilesPopover constants instead of inlining styles
Replace @remixicon/react with a shared Icon component that renders
via <use href> references to a single hidden SVG sprite. This reduces
DOM node count by replacing inline SVGs with lightweight references.
- Create Icon component with sprite injection (packages/ui/src/components/icon/)
- Migrate all 164 files from @remixicon/react to Icon component
- Auto-generate sprite data from remixicon bundle (scripts/generate-icon-sprite.mjs)
- Add bun run icons:generate to package.json
- Move @remixicon/react to devDependencies
- Add icon usage instructions to theme-system skill
Use base-ui's transition-status pattern (data-starting-style /
data-ending-style) for Dialog, DropdownMenu, Select, Tooltip and Popover
so open/close animate consistently at 150ms ease-out without flicker.
Wrap dialog popups in a centered flex container so the scale animation
no longer fights with translate-based positioning, and switch
PendingChangesBar to a real Popover so it actually animates closed.
Convert ScheduledTaskEditorDialog from raw Radix to the shared Dialog
wrapper, give ScheduledTasksDialog a stable min-height to prevent layout
shift mid-animation, and reset NewWorktreeDialog form state on open
instead of close so fields don't empty during the close transition.
Drop tooltip delay from 700ms to 300ms globally and remove all
per-component overrides except the model/variant/agent selectors in the
chat input (600ms).
* fix(chat): restore desktop editor file-open in PendingChangesBar (#979)
Commit d1553ba removed the runtime?.editor branch from handleOpenFile,
breaking file-click in VS Code and Electron desktop runtimes.
Restore the 3-branch logic: editor.openDiff(patch) → editor.openFile()
→ openContextDiff() web fallback. Display paths remain relative.
* fix(chat): route non-git changed files to file view in desktop
DiffView requires a git repository to display diffs. In desktop
(Electron/Tauri), runtime.editor is unavailable, so non-git files
fell through to openContextDiff which shows "Not a git repository".
Route non-git files to openContextFile instead, which works without
git. Git-tracked files continue to use openContextDiff.
* feat(chat): per-turn changes dropdown for non-git; self-sufficient git sync in bar
- PendingChangesBar seeds git store + listens to onGitRefreshHint; works without RightSidebarTabs (fixes VS Code where bar never rendered).
- Bar is git-only now; non-git shows per-turn dropdown at end of completed assistant turns.
- Dropdown uses base-ui Popover for collision-aware position; icon-only collapse with tooltips at narrow container widths.
- Extract shared helpers (changedFiles.ts), popover list (ChangedFilesList.tsx), styles (changedFilesPopover.ts).
---------
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
* feat: add FileChangeSummary component for multi-file diff preview in ToolPart
Provides an aggregated diff card for apply_patch and multi-edit tools,
showing per-file stats with click-to-expand diff view.
* feat: add PendingChangesBar above chat input with collapse/expand and file opening
- Collapsed/expanded toggle with aggregate +N -N stats (green/red)
- Relative path display, chat-column alignment with ChatInput
- Click file to open in diff viewer (web/desktop) or editor (VS Code)
- Support edit/multiedit/apply_patch/write tool metadata extraction
- Add PendingChangesBar to main chat view (ChatContainer)
* feat: dual-mode ChangedFilesBar — Git diff state vs latest AI turn
Git mode: reads git status from useGitStore (status.files + diffStats),
auto-clears on commit/restore. Shows 'N files changed in workspace'.
Non-Git mode: latest assistant turn only (no accumulation), clears on new
user message or manual dismiss. Shows 'AI updated N files in the last reply'.
Both modes: dismiss button with signature-based tracking.
Add pendingChangesBarDismissed state to session-ui-store, cleared on sendMessage.
* fix: address code review issues in ChangedFilesBar
- Gate non-git mode on streaming state to prevent flicker during AI turns
- Return null when isGitRepo is unknown (loading state)
- Add group/row class for reject button visibility in FileChangeSummary
- Use per-session Map for dismiss tracking to prevent cross-session leaks
- Include additions/deletions in dismiss signature for re-edit detection
- Extract shared parsePatchStats/parseCount to fileChangeHelpers
* chore: revert local .opencode/package-lock.json changes from PR
* fix: per-part fallback guard and git-only reject button
- Fix extractChangedFiles to use per-part files.length snapshot instead
of global guard, preventing file entries from being skipped when
earlier parts already contributed files
- Hide reject button in FileChangeSummary when not in a git repo,
preventing silent revert failures
* refactor: remove FileChangeSummary — dead code redundant with ToolPart
FileChangeSummary duplicated diff rendering that ToolPart already
provides (PatchDiff, per-file stats, DiffViewToggle). The only unique
feature was a git revert button, which conflicts with the design
principle of not having accept/reject on file change previews.
Moved parsePatchStats/parseCount back into PendingChangesBar (sole
consumer) and deleted the shared helper module.
* chore: remove stray Tester.txt
* fix: deduplicate Fallback 4 'Diff' placeholder via seen set
* chore: update non-Git mode copy to neutral 'changed in the last reply'
* fix(chat): unify changes row with tasks
---------
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>