diff --git a/.changeset/web-code-block-line-numbers.md b/.changeset/web-code-block-line-numbers.md new file mode 100644 index 0000000000..3d28ff6a3e --- /dev/null +++ b/.changeset/web-code-block-line-numbers.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +web: Fix code block line numbers drifting out of sync with the code lines in plain-text code blocks. diff --git a/.changeset/web-ctrl-s-save-dialog.md b/.changeset/web-ctrl-s-save-dialog.md new file mode 100644 index 0000000000..34400ab415 --- /dev/null +++ b/.changeset/web-ctrl-s-save-dialog.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +web: Prevent the browser Save Page dialog on Ctrl+S / Cmd+S anywhere in the app; the shortcut still steers into the running turn from the message input. diff --git a/.changeset/web-full-width-chat-column.md b/.changeset/web-full-width-chat-column.md new file mode 100644 index 0000000000..0287bc4dbd --- /dev/null +++ b/.changeset/web-full-width-chat-column.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +web: Let the chat column follow the window width instead of capping it at a fixed reading width, removing the wide empty margins on large screens. diff --git a/apps/kimi-web/src/App.vue b/apps/kimi-web/src/App.vue index 5708bcc9bf..447c712c7b 100644 --- a/apps/kimi-web/src/App.vue +++ b/apps/kimi-web/src/App.vue @@ -207,6 +207,15 @@ onUnmounted(() => { }); function onGlobalKeydown(e: KeyboardEvent): void { + // Swallow Ctrl+S / Cmd+S app-wide, in capture phase: the composer advertises + // the shortcut for steering into the running turn, but its own keydown only + // fires while the composer is focused. Without this the browser opens its + // Save Page dialog whenever the shortcut is pressed anywhere else. Steering + // itself stays in the composer's handler. + if (e.key === 's' && (e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) { + e.preventDefault(); + return; + } if (e.key !== 'Escape') return; // A modal dialog open on top of the side panel owns Escape — leave the event // alone so the dialog can close itself instead of the panel behind it. diff --git a/apps/kimi-web/src/components/chat/Composer.vue b/apps/kimi-web/src/components/chat/Composer.vue index 5d2e16f6d9..bab5cc76aa 100644 --- a/apps/kimi-web/src/components/chat/Composer.vue +++ b/apps/kimi-web/src/components/chat/Composer.vue @@ -491,10 +491,13 @@ function handleKeydown(e: KeyboardEvent): void { } } - // Ctrl+S / Cmd+S — steer into the running turn (TUI parity) + // Ctrl+S / Cmd+S — steer into the running turn (TUI parity). Always swallow + // the shortcut: without preventDefault the browser opens its Save Page dialog. + // (The same swallow lives app-wide in App.vue's onGlobalKeydown, so the + // dialog is suppressed even when the composer is not focused.) if (e.key === 's' && (e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) { + e.preventDefault(); if (props.running) { - e.preventDefault(); handleSteer(); } return; diff --git a/apps/kimi-web/src/components/chat/ConversationPane.vue b/apps/kimi-web/src/components/chat/ConversationPane.vue index 0464beac9b..1749f34ba4 100644 --- a/apps/kimi-web/src/components/chat/ConversationPane.vue +++ b/apps/kimi-web/src/components/chat/ConversationPane.vue @@ -332,7 +332,7 @@ function updateActiveTocQuery(): void { // --- TOC occlusion by wide tables ------------------------------------------- // Wide markdown tables (up to --p-table-max) can extend past the TOC rail, -// which stays anchored to the reading-column edge. While a table actually +// which stays anchored to the pane's right edge. While a table actually // covers the rail we hide the TOC temporarily so the table stays fully // interactive (clicks, text selection, horizontal scroll). The user's TOC // setting is untouched and the rail returns as soon as the table scrolls away. @@ -354,7 +354,7 @@ function updateTocTableOcclusion(): void { ? pane.closest('.con')?.querySelector('.conversation-toc') : null; // The hit x is the centre of the fixed rail bar: `.toc-bar` keeps a stable x - // even when hover expands the labels rightward, so hovering the TOC itself + // even when hover expands the labels leftward, so hovering the TOC itself // never flips the state (the nav centre would). const bar = toc?.querySelector('.toc-bar'); let covered = false; @@ -423,7 +423,9 @@ const panesRef = ref(null); const dockRef = ref(null); const panesScrollbarWidth = ref(0); const dockHeight = ref(0); -const chatDockStyle = computed(() => ({ +// Exposed on `.con` (not the dock alone) so the TOC rail can compensate for +// the panes scrollbar gutter at the pane's right edge, just like the dock does. +const conStyle = computed(() => ({ '--panes-scrollbar-width': `${panesScrollbarWidth.value}px`, })); type ComposerHandle = { @@ -1251,7 +1253,7 @@ defineExpose({ loadComposerForEdit, focusComposer });