From ded62c875d37af3be13d64265601d0c95c6282e9 Mon Sep 17 00:00:00 2001 From: qer Date: Thu, 2 Jul 2026 19:19:31 +0800 Subject: [PATCH 1/5] fix(web): trim redundant and incorrect tooltips Drop hover tooltips that only restated a button's accessible label, and remove the permission-pill tooltip that described cycling modes while the control actually opens a dropdown. Keep tooltips that reveal truncated text or explain status. --- .changeset/trim-redundant-web-tooltips.md | 5 + apps/kimi-web/src/App.vue | 17 +-- apps/kimi-web/src/components/FilePreview.vue | 90 +++++------- apps/kimi-web/src/components/Sidebar.vue | 93 ++++++------ .../src/components/WorkspaceGroup.vue | 42 +++--- .../src/components/chat/ApprovalCard.vue | 20 ++- .../src/components/chat/ChatHeader.vue | 24 ++-- .../kimi-web/src/components/chat/ChatPane.vue | 72 ++++------ .../kimi-web/src/components/chat/Composer.vue | 132 ++++++++---------- .../kimi-web/src/components/chat/DiffView.vue | 10 +- .../src/components/chat/OpenInMenu.vue | 22 ++- .../src/components/chat/QuestionCard.vue | 21 ++- .../components/mobile/MobileSwitcherSheet.vue | 56 ++++---- .../src/components/ui/PanelHeader.vue | 20 ++- apps/kimi-web/src/i18n/locales/en/status.ts | 3 - apps/kimi-web/src/i18n/locales/zh/status.ts | 3 - 16 files changed, 277 insertions(+), 353 deletions(-) create mode 100644 .changeset/trim-redundant-web-tooltips.md diff --git a/.changeset/trim-redundant-web-tooltips.md b/.changeset/trim-redundant-web-tooltips.md new file mode 100644 index 0000000000..970b8a223c --- /dev/null +++ b/.changeset/trim-redundant-web-tooltips.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Remove duplicate and incorrect tooltips from web UI icon buttons and status pills. diff --git a/apps/kimi-web/src/App.vue b/apps/kimi-web/src/App.vue index 48224498e7..d89debde79 100644 --- a/apps/kimi-web/src/App.vue +++ b/apps/kimi-web/src/App.vue @@ -40,7 +40,6 @@ import type { AppConfig, ThinkingLevel } from './api/types'; import Button from './components/ui/Button.vue'; import IconButton from './components/ui/IconButton.vue'; import Icon from './components/ui/Icon.vue'; -import Tooltip from './components/ui/Tooltip.vue'; // Hydrate the server-transport credential (fragment token or sessionStorage) // BEFORE the client connects, so the first REST/WS calls already carry it. @@ -625,15 +624,13 @@ function openPr(url: string): void { @update:width="sessionColWidth = $event" /> diff --git a/apps/kimi-web/src/components/FilePreview.vue b/apps/kimi-web/src/components/FilePreview.vue index 8b65cf4c8e..1888c2127d 100644 --- a/apps/kimi-web/src/components/FilePreview.vue +++ b/apps/kimi-web/src/components/FilePreview.vue @@ -482,60 +482,46 @@ function truncatePath(path: string, maxLen = 55): string { {{ searchMatches.length }} - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + + + + + diff --git a/apps/kimi-web/src/components/Sidebar.vue b/apps/kimi-web/src/components/Sidebar.vue index 4b4911b1af..c8c92ef2b9 100644 --- a/apps/kimi-web/src/components/Sidebar.vue +++ b/apps/kimi-web/src/components/Sidebar.vue @@ -23,7 +23,6 @@ import IconButton from './ui/IconButton.vue'; import Icon from './ui/Icon.vue'; import Menu from './ui/Menu.vue'; import MenuItem from './ui/MenuItem.vue'; -import Tooltip from './ui/Tooltip.vue'; import { useConfirmDialog } from '../composables/useConfirmDialog'; const { t } = useI18n(); @@ -553,24 +552,20 @@ onBeforeUnmount(() => { Kimi Code · {{ endpoint }} - - - - - - - - - - + + + + + + @@ -585,16 +580,14 @@ onBeforeUnmount(() => { {{ t('sidebar.newChat') }} - - - - - + + + @@ -609,29 +602,25 @@ onBeforeUnmount(() => {
- - - - - + + + - - - - - + + +
diff --git a/apps/kimi-web/src/components/chat/ApprovalCard.vue b/apps/kimi-web/src/components/chat/ApprovalCard.vue index ee8d470036..0448ff2613 100644 --- a/apps/kimi-web/src/components/chat/ApprovalCard.vue +++ b/apps/kimi-web/src/components/chat/ApprovalCard.vue @@ -191,17 +191,15 @@ onUnmounted(() => document.removeEventListener('keydown', handleKeydown)); {{ t('approval.subagentBadge', { name: agentName }) }} {{ t('approval.required') }} - - - - - - + + + + diff --git a/apps/kimi-web/src/components/chat/ChatHeader.vue b/apps/kimi-web/src/components/chat/ChatHeader.vue index 77b89cf5e9..4ba0b5b430 100644 --- a/apps/kimi-web/src/components/chat/ChatHeader.vue +++ b/apps/kimi-web/src/components/chat/ChatHeader.vue @@ -222,19 +222,17 @@ async function startArchive(): Promise { - - - - - + + +
- - - -
- - +
+ - + + + @@ -733,16 +723,14 @@ function isStreamingRenderBlock(turn: ChatTurn, block: { sourceIndex: number }): {{ t('composer.queueNext') }} #{{ qi + 1 }} - - - + diff --git a/apps/kimi-web/src/components/chat/Composer.vue b/apps/kimi-web/src/components/chat/Composer.vue index f8a8feb7ee..9d00f61b63 100644 --- a/apps/kimi-web/src/components/chat/Composer.vue +++ b/apps/kimi-web/src/components/chat/Composer.vue @@ -783,18 +783,16 @@ function selectModel(modelId: string): void { @compositionend="handleCompositionEnd" @input="handleInput" /> - - - + @@ -813,30 +811,26 @@ function selectModel(modelId: string): void {
- - - - - + + + - - {{ permLabel }} - + {{ permLabel }} {{ attentionBySession[s.id] }} - - - - - + + + diff --git a/apps/kimi-web/src/components/ui/PanelHeader.vue b/apps/kimi-web/src/components/ui/PanelHeader.vue index fbd276b9b8..930ba51797 100644 --- a/apps/kimi-web/src/components/ui/PanelHeader.vue +++ b/apps/kimi-web/src/components/ui/PanelHeader.vue @@ -30,17 +30,15 @@ defineEmits<{ close: [] }>(); {{ subtitle }} - - - - - + + +
diff --git a/apps/kimi-web/src/i18n/locales/en/status.ts b/apps/kimi-web/src/i18n/locales/en/status.ts index ae5f521c39..fc4ca8cc47 100644 --- a/apps/kimi-web/src/i18n/locales/en/status.ts +++ b/apps/kimi-web/src/i18n/locales/en/status.ts @@ -4,11 +4,9 @@ export default { connectionDisconnected: 'Disconnected', ctxTooltip: 'Used {used} / {max} tokens ({pct}%)', modelLabel: 'Model', - modelTooltip: 'Click to switch model', permissionManual: 'Manual', permissionAuto: 'Auto', permissionYolo: 'YOLO', - permissionTooltip: 'Click to cycle permission mode', permissionManualDesc: 'Ask for approval on every tool action', permissionAutoDesc: 'Fully autonomous — agent decides everything without asking', permissionYoloDesc: 'Auto-approve tool actions, but agent may still ask questions', @@ -19,7 +17,6 @@ export default { planTooltip: 'Toggle plan mode (research before editing)', // Mode selector (Plan / Goal / Swarm) modesLabel: 'Mode', - modesTooltip: 'Mode: Plan / Goal / Swarm', goalLabel: 'Goal', swarmLabel: 'Swarm', modeOff: 'Off', diff --git a/apps/kimi-web/src/i18n/locales/zh/status.ts b/apps/kimi-web/src/i18n/locales/zh/status.ts index 2eb8dcc4ae..98287e9d57 100644 --- a/apps/kimi-web/src/i18n/locales/zh/status.ts +++ b/apps/kimi-web/src/i18n/locales/zh/status.ts @@ -4,11 +4,9 @@ export default { connectionDisconnected: '未连接', ctxTooltip: '使用 {used} / {max} tokens ({pct}%)', modelLabel: '模型', - modelTooltip: '点击切换模型', permissionManual: '逐条确认', permissionAuto: '完全自主', permissionYolo: '自动通过', - permissionTooltip: '点击循环切换审批模式', permissionManualDesc: '每个工具操作都需要你手动确认', permissionAutoDesc: '完全自主运行,agent 自己做决定,不再询问', permissionYoloDesc: '自动批准工具操作,但遇到关键问题仍会询问', @@ -19,7 +17,6 @@ export default { planTooltip: '切换计划模式(先调研再修改)', // 模式选择器(计划 / 目标 / Swarm) modesLabel: '模式', - modesTooltip: '模式:计划 / 目标 / Swarm', goalLabel: '目标', swarmLabel: 'Swarm', modeOff: '未启用', From 38a9ead9a2734c3e5ffbbc5cd2f181322d0a9361 Mon Sep 17 00:00:00 2001 From: qer Date: Thu, 2 Jul 2026 19:24:15 +0800 Subject: [PATCH 2/5] fix(web): remove remaining ChatHeader tooltips Drop the session-title, git-branch, and open-PR tooltips in ChatHeader so the header has no hover tooltips. Broaden the changeset wording to cover the wider trim. --- .changeset/trim-redundant-web-tooltips.md | 2 +- .../src/components/chat/ChatHeader.vue | 71 ++++++++----------- 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/.changeset/trim-redundant-web-tooltips.md b/.changeset/trim-redundant-web-tooltips.md index 970b8a223c..ee1038b2db 100644 --- a/.changeset/trim-redundant-web-tooltips.md +++ b/.changeset/trim-redundant-web-tooltips.md @@ -2,4 +2,4 @@ "@moonshot-ai/kimi-code": patch --- -Remove duplicate and incorrect tooltips from web UI icon buttons and status pills. +Trim redundant and incorrect tooltips in the web UI. diff --git a/apps/kimi-web/src/components/chat/ChatHeader.vue b/apps/kimi-web/src/components/chat/ChatHeader.vue index 4ba0b5b430..4019b9be3f 100644 --- a/apps/kimi-web/src/components/chat/ChatHeader.vue +++ b/apps/kimi-web/src/components/chat/ChatHeader.vue @@ -11,7 +11,6 @@ import Menu from '../ui/Menu.vue'; import MenuItem from '../ui/MenuItem.vue'; import IconButton from '../ui/IconButton.vue'; import Icon from '../ui/Icon.vue'; -import Tooltip from '../ui/Tooltip.vue'; import { useConfirmDialog } from '../../composables/useConfirmDialog'; const { t } = useI18n(); @@ -216,9 +215,7 @@ async function startArchive(): Promise { @blur="commitRename" @click.stop /> - - {{ sessionTitle }} - + {{ sessionTitle }}
@@ -268,45 +265,39 @@ async function startArchive(): Promise { - - - + {{ branch || t('header.detached') }} + + + ↑{{ ahead }} + ↓{{ behind }} + + + +{{ adds }} + -{{ dels }} + + - - - + From 8f0d29c1480ef6469731403bacce72a38ef82d5a Mon Sep 17 00:00:00 2001 From: qer Date: Thu, 2 Jul 2026 19:32:41 +0800 Subject: [PATCH 3/5] fix(web): keep tooltips from getting stuck on unmount Tooltip attached its mouseleave listener to the slotted trigger element once, so if that element was removed (e.g. a v-if toggled while hovering a tool-call path) the open bubble never received mouseleave and stranded on screen. Re-sync the listener to the live slotted element via a MutationObserver and close the tooltip whenever the trigger changes. --- apps/kimi-web/src/components/ui/Tooltip.vue | 58 +++++++++++++++------ 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/apps/kimi-web/src/components/ui/Tooltip.vue b/apps/kimi-web/src/components/ui/Tooltip.vue index 8d097e44da..a120cbff3d 100644 --- a/apps/kimi-web/src/components/ui/Tooltip.vue +++ b/apps/kimi-web/src/components/ui/Tooltip.vue @@ -2,11 +2,12 @@ + the real trigger element, which also anchors the bubble, and re-attached if that + element is removed or replaced (so an open tooltip can never strand on screen). + The bubble is rendered through a body teleport so it escapes ancestor overflow + clipping, and positioned with flip + viewport clamping. Short text stays on one + line; long text wraps within `maxWidth` and is clamped to `maxLines` lines with + an ellipsis so the bubble never grows too tall. -->