Major UI refresh: sidebar redesign, theme expansion, and chat performance optimizations (#706)

## Summary
Complete sidebar redesign and comprehensive UI polish pass with performance optimizations, theme system refinements, and desktop integration improvements.

## Key Changes

**Sidebar & Navigation Redesign**
- Redesigned sessions sidebar layout with unified button primitives
- Added activity sections with project grouping and improved session organization
- Refined sidebar corners, spacing, and visual hierarchy
- Removed NavRail component in favor of streamlined sidebar
- Stabilized sessions bar toggle position in fullscreen mode

**Performance Optimizations**
- Reduced chat streaming CPU usage and storage churn
- Optimized task tool polling and live timers with debouncing
- Prevented chat state races and reduced background request load
- Debounced draft writes and coalesced session reloads
- Optimized message store updates and turn tracking

**Theme & Visual System**
- Added theme-aware window corners (desktop) and border radius tokens
- Introduced glassmorphism effects on desktop sidebar
- Added backdrop blur to UI elements

**Chat Experience**
- Added session-based permission auto-accept toggle in chat input
- Polished permission shield UX with improved icon sizing and spacing
- Fixed chat scroll-to-bottom behavior and timeline tracking
- Enhanced tool output display with better path label detection
- Removed duplicate draft context details in chat header
- Added text selection menu to chat messages

**Git Improvements**
- Refreshed git history visual design with cleaner dividers
- Added remote removal action in sync selector
- Stabilized git polling to prevent excessive requests
- Improved tool output rendering for git operations

**Settings & Panels**
- Fixed mobile scrolling on settings pages
- Made outside-click settings close instantly
- Reduced settings load churn and CPU spikes
- Improved services dropdown layout and spacing
- Softened panel resize handles

**Desktop Integration**
- Synced macOS window theme with app theme
- Restored window dragging in sidebar header zones
- Fixed system window corners on macOS
- Improved header session metadata and action controls

**Button & Component Standardization**
- Unified button primitives across all components
- Standardized destructive action patterns
- Removed unused button variants (button-large, button-small)
- Aligned context tab close hit areas

---------

Co-authored-by: Iuliia Ivashko <yulia.ivashko@gmail.com>
This commit is contained in:
Bohdan Triapitsyn
2026-03-20 01:01:03 +02:00
committed by GitHub
co-authored by Iuliia Ivashko
parent 359879153a
commit 321cc7252a
222 changed files with 8575 additions and 5456 deletions
+53 -7
View File
@@ -433,6 +433,7 @@ export const GitView: React.FC = () => {
return isActionTab(stored) ? stored : 'commit';
});
const [remotes, setRemotes] = React.useState<GitRemote[]>([]);
const [removingRemoteName, setRemovingRemoteName] = React.useState<string | null>(null);
const [branchOperation, setBranchOperation] = React.useState<BranchOperation>(null);
const [operationLogs, setOperationLogs] = React.useState<OperationLogEntry[]>([]);
const [conflictDialogOpen, setConflictDialogOpen] = React.useState(false);
@@ -585,14 +586,23 @@ export const GitView: React.FC = () => {
git.getRemoteUrl(currentDirectory).then(setRemoteUrl).catch(() => setRemoteUrl(null));
}, [currentDirectory, git]);
React.useEffect(() => {
const refreshRemotes = React.useCallback(async () => {
if (!currentDirectory || !git?.getRemotes) {
setRemotes([]);
return;
}
git.getRemotes(currentDirectory).then(setRemotes).catch(() => setRemotes([]));
try {
const remoteList = await git.getRemotes(currentDirectory);
setRemotes(remoteList);
} catch {
setRemotes([]);
}
}, [currentDirectory, git]);
React.useEffect(() => {
void refreshRemotes();
}, [refreshRemotes]);
React.useEffect(() => {
if (!settingsGitmojiEnabled) {
setGitmojiEmojis([]);
@@ -825,6 +835,35 @@ export const GitView: React.FC = () => {
}
};
const handleRemoveRemote = React.useCallback(async (remote: GitRemote) => {
if (!currentDirectory) return;
const remoteName = remote.name.trim();
if (!remoteName) {
toast.error('Remote name is required');
return;
}
if (remoteName === 'origin') {
toast.error('Cannot remove origin remote');
return;
}
setRemovingRemoteName(remoteName);
try {
await git.removeRemote(currentDirectory, { remote: remoteName });
toast.success(`Removed ${remoteName} remote`);
await Promise.all([
refreshStatusAndBranches(false),
refreshRemotes(),
]);
} catch (error) {
const message = error instanceof Error ? error.message : `Failed to remove ${remoteName}`;
toast.error(message);
} finally {
setRemovingRemoteName(null);
}
}, [currentDirectory, git, refreshRemotes, refreshStatusAndBranches]);
const handleCommit = async (options: { pushAfter?: boolean } = {}) => {
if (!currentDirectory) return;
if (!commitMessage.trim()) {
@@ -1254,11 +1293,20 @@ export const GitView: React.FC = () => {
}
const insertBeforeIndex = log.all.findIndex((entry) => !branchHashes.has(entry.hash));
if (insertBeforeIndex <= 0) {
if (insertBeforeIndex === 0) {
setHistoryBranchDivider(null);
return;
}
if (insertBeforeIndex === -1) {
setHistoryBranchDivider({
insertBeforeIndex: log.all.length,
branchName: currentBranch,
direction: 'up',
});
return;
}
setHistoryBranchDivider({
insertBeforeIndex,
branchName: currentBranch,
@@ -1806,6 +1854,8 @@ export const GitView: React.FC = () => {
onFetch={(remote) => handleSyncAction('fetch', remote)}
onPull={(remote) => handleSyncAction('pull', remote)}
onPush={() => handleSyncAction('push')}
onRemoveRemote={handleRemoveRemote}
removingRemoteName={removingRemoteName}
onCheckoutBranch={handleCheckoutBranch}
onCreateBranch={handleCreateBranch}
onRenameBranch={handleRenameBranch}
@@ -1861,7 +1911,6 @@ export const GitView: React.FC = () => {
{(changeEntries?.length ?? 0) > 0 ? (
<>
<ChangesSection
variant="plain"
maxListHeightClassName="max-h-[40vh]"
changeEntries={changeEntries}
onVisiblePathsChange={setVisibleChangePaths}
@@ -1887,7 +1936,6 @@ export const GitView: React.FC = () => {
/>
<CommitSection
variant="plain"
selectedCount={selectedCount}
commitMessage={commitMessage}
onCommitMessageChange={setCommitMessage}
@@ -1945,7 +1993,6 @@ export const GitView: React.FC = () => {
<div className="space-y-4">
{integrateCommitsProps ? (
<IntegrateCommitsSection
variant="plain"
repoRoot={integrateCommitsProps.repoRoot}
sourceBranch={integrateCommitsProps.sourceBranch}
worktreeMetadata={integrateCommitsProps.worktreeMetadata}
@@ -1974,7 +2021,6 @@ export const GitView: React.FC = () => {
<div className="space-y-4">
{pullRequestProps ? (
<PullRequestSection
variant="plain"
directory={pullRequestProps.directory}
branch={pullRequestProps.branch}
baseBranch={baseBranch}