+
+
+
+ Original
+ {diff.operation === 'write' && (
+ (empty)
+ )}
-
-
- Modified
+
+
+
+ Modified
+ ({stats.totalLines} lines)
@@ -214,9 +249,15 @@ export function DiffEditor({ diff, onClose, className }: DiffEditorProps) {
style={{ minHeight: 0 }}
/>
- {/* 路径提示 */}
-
- {diff.path}
+ {/* 底部状态栏 */}
+
+
+ ESC
+ to close
+
+
+ Side-by-side comparison
+
);
diff --git a/packages/ui/src/styles/index.css b/packages/ui/src/styles/index.css
index 52d66d6..dcdda5e 100644
--- a/packages/ui/src/styles/index.css
+++ b/packages/ui/src/styles/index.css
@@ -93,6 +93,16 @@ html {
background: var(--scrollbar-thumb-hover);
}
+/* 隐藏滚动条(保留滚动功能) */
+.scrollbar-hide {
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+}
+
+.scrollbar-hide::-webkit-scrollbar {
+ display: none;
+}
+
/* ============ Message content ============ */
.message-content {
@@ -119,6 +129,232 @@ html {
padding: 0;
}
+/* ============ CodeMirror Editor Styles ============ */
+
+/* 编辑器容器 */
+.cm-editor {
+ font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', 'Menlo', 'Monaco', 'Consolas', monospace !important;
+ font-size: 13px !important;
+ line-height: 1.6 !important;
+ font-feature-settings: 'liga' 1, 'calt' 1; /* 启用连字 */
+}
+
+/* 编辑器聚焦时的边框 */
+.cm-editor.cm-focused {
+ outline: none !important;
+}
+
+/* 内容区域 */
+.cm-scroller {
+ overflow: auto !important;
+ font-family: inherit !important;
+}
+
+/* 行号栏 */
+.cm-gutters {
+ border-right: 1px solid rgb(var(--color-border-default)) !important;
+ background: rgb(var(--color-bg-subtle)) !important;
+}
+
+.dark .cm-gutters {
+ background: rgba(0, 0, 0, 0.2) !important;
+ border-right-color: rgb(var(--color-border-default)) !important;
+}
+
+/* 行号 */
+.cm-lineNumbers .cm-gutterElement {
+ padding: 0 12px 0 8px !important;
+ min-width: 40px !important;
+ color: rgb(var(--color-text-subtle)) !important;
+ font-size: 12px !important;
+}
+
+/* 活动行高亮 */
+.cm-activeLine {
+ background: rgba(var(--color-bg-emphasis), 0.5) !important;
+}
+
+.dark .cm-activeLine {
+ background: rgba(255, 255, 255, 0.04) !important;
+}
+
+/* 活动行号高亮 */
+.cm-activeLineGutter {
+ background: rgba(var(--color-bg-emphasis), 0.5) !important;
+}
+
+.dark .cm-activeLineGutter {
+ background: rgba(255, 255, 255, 0.06) !important;
+}
+
+/* 选区样式 */
+.cm-selectionBackground {
+ background: rgba(59, 130, 246, 0.2) !important;
+}
+
+.dark .cm-selectionBackground {
+ background: rgba(59, 130, 246, 0.3) !important;
+}
+
+/* 匹配的括号 */
+.cm-matchingBracket {
+ background: rgba(255, 215, 0, 0.3) !important;
+ outline: 1px solid rgba(255, 215, 0, 0.5) !important;
+}
+
+/* 折叠占位符 */
+.cm-foldPlaceholder {
+ background: rgb(var(--color-bg-muted)) !important;
+ border: 1px solid rgb(var(--color-border-default)) !important;
+ border-radius: 4px !important;
+ padding: 0 4px !important;
+ margin: 0 2px !important;
+ color: rgb(var(--color-text-muted)) !important;
+}
+
+/* 搜索面板 */
+.cm-panel.cm-search {
+ background: rgb(var(--color-bg-subtle)) !important;
+ border-bottom: 1px solid rgb(var(--color-border-default)) !important;
+ padding: 8px !important;
+}
+
+.cm-panel.cm-search input {
+ background: rgb(var(--color-bg-base)) !important;
+ border: 1px solid rgb(var(--color-border-default)) !important;
+ border-radius: 4px !important;
+ padding: 4px 8px !important;
+ color: rgb(var(--color-text-primary)) !important;
+}
+
+.cm-panel.cm-search button {
+ background: rgb(var(--color-bg-muted)) !important;
+ border: 1px solid rgb(var(--color-border-default)) !important;
+ border-radius: 4px !important;
+ padding: 4px 8px !important;
+ color: rgb(var(--color-text-secondary)) !important;
+ cursor: pointer !important;
+}
+
+.cm-panel.cm-search button:hover {
+ background: rgb(var(--color-bg-emphasis)) !important;
+}
+
+/* 自动补全下拉框 */
+.cm-tooltip-autocomplete {
+ background: rgb(var(--color-bg-base)) !important;
+ border: 1px solid rgb(var(--color-border-default)) !important;
+ border-radius: 6px !important;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
+ overflow: hidden !important;
+}
+
+.dark .cm-tooltip-autocomplete {
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) !important;
+}
+
+.cm-tooltip-autocomplete > ul {
+ font-family: inherit !important;
+ max-height: 200px !important;
+}
+
+.cm-tooltip-autocomplete > ul > li {
+ padding: 4px 10px !important;
+ color: rgb(var(--color-text-primary)) !important;
+}
+
+.cm-tooltip-autocomplete > ul > li[aria-selected] {
+ background: rgb(var(--color-bg-emphasis)) !important;
+ color: rgb(var(--color-text-primary)) !important;
+}
+
+.dark .cm-tooltip-autocomplete > ul > li[aria-selected] {
+ background: rgba(59, 130, 246, 0.2) !important;
+}
+
+/* 光标样式 */
+.cm-cursor {
+ border-left: 2px solid rgb(var(--color-text-primary)) !important;
+}
+
+.dark .cm-cursor {
+ border-left-color: #fff !important;
+}
+
+/* 行内容 */
+.cm-line {
+ padding: 0 8px !important;
+}
+
+/* ============ Diff Editor Styles ============ */
+
+/* Merge View 容器 */
+.cm-mergeView {
+ height: 100% !important;
+}
+
+/* Diff 视图中的变更高亮 */
+.cm-changedLine {
+ background: rgba(255, 215, 0, 0.1) !important;
+}
+
+.cm-deletedChunk {
+ background: rgba(239, 68, 68, 0.15) !important;
+}
+
+.dark .cm-deletedChunk {
+ background: rgba(239, 68, 68, 0.2) !important;
+}
+
+.cm-insertedChunk {
+ background: rgba(34, 197, 94, 0.15) !important;
+}
+
+.dark .cm-insertedChunk {
+ background: rgba(34, 197, 94, 0.2) !important;
+}
+
+/* Diff 行内变更 */
+.cm-changedText {
+ background: rgba(255, 215, 0, 0.3) !important;
+ border-radius: 2px !important;
+}
+
+.cm-deletedText {
+ background: rgba(239, 68, 68, 0.3) !important;
+ text-decoration: line-through !important;
+ border-radius: 2px !important;
+}
+
+.cm-insertedText {
+ background: rgba(34, 197, 94, 0.3) !important;
+ border-radius: 2px !important;
+}
+
+/* Gutter 中的变更标记 */
+.cm-changeGutter {
+ width: 4px !important;
+}
+
+.cm-changeGutter .cm-gutterElement {
+ padding: 0 !important;
+}
+
+/* 折叠的未变更区域 */
+.cm-collapsedLines {
+ background: rgb(var(--color-bg-subtle)) !important;
+ color: rgb(var(--color-text-muted)) !important;
+ font-size: 12px !important;
+ padding: 4px 12px !important;
+ margin: 4px 0 !important;
+ border-radius: 4px !important;
+ cursor: pointer !important;
+}
+
+.cm-collapsedLines:hover {
+ background: rgb(var(--color-bg-muted)) !important;
+}
+
/* ============ Typing indicator ============ */
.typing-indicator {