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:
committed by
GitHub
co-authored by
Iuliia Ivashko
parent
359879153a
commit
321cc7252a
@@ -24,6 +24,12 @@ interface SelectionPayload {
|
||||
|
||||
const DESKTOP_MENU_SIDE_MARGIN_PX = 8;
|
||||
const DESKTOP_MENU_FALLBACK_WIDTH_PX = 280;
|
||||
const BLOCK_TAGS = new Set([
|
||||
'address', 'article', 'aside', 'blockquote', 'dd', 'div', 'dl', 'dt',
|
||||
'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3',
|
||||
'h4', 'h5', 'h6', 'header', 'hr', 'li', 'main', 'nav', 'ol', 'p', 'pre',
|
||||
'section', 'table', 'ul',
|
||||
]);
|
||||
|
||||
const normalizeLineBreaks = (value: string): string => value.replace(/\r\n?/g, '\n');
|
||||
|
||||
@@ -103,6 +109,11 @@ const renderBlockMarkdownNode = (node: Node): string => {
|
||||
return `\`\`\`${language}\n${code}\n\`\`\``;
|
||||
}
|
||||
|
||||
if (tag === 'code') {
|
||||
const code = normalizeLineBreaks(element.textContent || '').trim();
|
||||
return code ? `\`${code.replace(/`/g, '\\`')}\`` : '';
|
||||
}
|
||||
|
||||
if (tag === 'ul') return renderListMarkdown(element, false);
|
||||
if (tag === 'ol') return renderListMarkdown(element, true);
|
||||
|
||||
@@ -137,8 +148,34 @@ const renderBlockMarkdownNode = (node: Node): string => {
|
||||
return trimSelectionValue(Array.from(element.childNodes).map((child) => renderInlineMarkdownNode(child)).join(''));
|
||||
};
|
||||
|
||||
const isInlineSelectionFragment = (fragment: DocumentFragment): boolean => {
|
||||
return Array.from(fragment.childNodes).every((node) => {
|
||||
if (node.nodeType === Node.TEXT_NODE) {
|
||||
return true;
|
||||
}
|
||||
if (node.nodeType !== Node.ELEMENT_NODE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const element = node as HTMLElement;
|
||||
return !BLOCK_TAGS.has(element.tagName.toLowerCase());
|
||||
});
|
||||
};
|
||||
|
||||
const rangeToMarkdown = (range: Range, plainText: string): string => {
|
||||
const fragment = range.cloneContents();
|
||||
|
||||
if (isInlineSelectionFragment(fragment)) {
|
||||
const inlineMarkdown = trimSelectionValue(
|
||||
Array.from(fragment.childNodes)
|
||||
.map((node) => renderInlineMarkdownNode(node))
|
||||
.join('')
|
||||
);
|
||||
if (inlineMarkdown) {
|
||||
return inlineMarkdown;
|
||||
}
|
||||
}
|
||||
|
||||
const markdown = Array.from(fragment.childNodes)
|
||||
.map((node) => renderBlockMarkdownNode(node))
|
||||
.filter((value) => value.length > 0)
|
||||
@@ -436,6 +473,8 @@ export const TextSelectionMenu: React.FC<TextSelectionMenuProps> = ({ containerR
|
||||
)}
|
||||
style={{
|
||||
paddingBottom: 'calc(0.5rem + env(safe-area-inset-bottom, 0px))',
|
||||
backdropFilter: 'blur(28px)',
|
||||
WebkitBackdropFilter: 'blur(28px)',
|
||||
}}
|
||||
>
|
||||
<button
|
||||
@@ -507,6 +546,10 @@ export const TextSelectionMenu: React.FC<TextSelectionMenuProps> = ({ containerR
|
||||
'transition-[opacity,transform] duration-200 ease-out will-change-[opacity,transform]',
|
||||
isOpening ? 'opacity-0 translate-y-[4px]' : 'opacity-100 translate-y-0'
|
||||
)}
|
||||
style={{
|
||||
backdropFilter: 'blur(28px)',
|
||||
WebkitBackdropFilter: 'blur(28px)',
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={handleAddToChat}
|
||||
|
||||
Reference in New Issue
Block a user