From d92181fecd9cefb226516fecebd384aeeb2242d2 Mon Sep 17 00:00:00 2001 From: qer Date: Sun, 28 Jun 2026 00:59:54 +0800 Subject: [PATCH 1/2] chore(web): show five sessions per workspace --- .changeset/web-session-initial-page-size.md | 5 +++++ apps/kimi-web/src/composables/client/useWorkspaceState.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/web-session-initial-page-size.md diff --git a/.changeset/web-session-initial-page-size.md b/.changeset/web-session-initial-page-size.md new file mode 100644 index 0000000000..0810387ca5 --- /dev/null +++ b/.changeset/web-session-initial-page-size.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Show the first five sessions per workspace in the web sidebar instead of ten. diff --git a/apps/kimi-web/src/composables/client/useWorkspaceState.ts b/apps/kimi-web/src/composables/client/useWorkspaceState.ts index e9ea362076..66cf6ae8da 100644 --- a/apps/kimi-web/src/composables/client/useWorkspaceState.ts +++ b/apps/kimi-web/src/composables/client/useWorkspaceState.ts @@ -287,7 +287,7 @@ export function useWorkspaceState(rawState: ExtendedState, deps: UseWorkspaceSta const SESSION_PAGE_SIZE = 100; // Sessions fetched per workspace on first load — keeps the initial request // count at (number of workspaces) and each response small. - const SESSIONS_INITIAL_PAGE_SIZE = 10; + const SESSIONS_INITIAL_PAGE_SIZE = 5; // Sessions fetched per "load more" click within a workspace. const SESSIONS_LOAD_MORE_SIZE = 30; From a85ea6018dcc2dcf831c37a51988f9152dd69e15 Mon Sep 17 00:00:00 2001 From: qer Date: Sun, 28 Jun 2026 01:13:21 +0800 Subject: [PATCH 2/2] feat(kimi-web): rework ask-user-question card as step-by-step wizard --- .changeset/web-ask-question-wizard.md | 5 + .../src/components/chat/QuestionCard.vue | 156 ++++++++++++++---- apps/kimi-web/src/i18n/locales/en/question.ts | 4 +- apps/kimi-web/src/i18n/locales/zh/question.ts | 4 +- 4 files changed, 133 insertions(+), 36 deletions(-) create mode 100644 .changeset/web-ask-question-wizard.md diff --git a/.changeset/web-ask-question-wizard.md b/.changeset/web-ask-question-wizard.md new file mode 100644 index 0000000000..3ac40cf663 --- /dev/null +++ b/.changeset/web-ask-question-wizard.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Rework the web ask-user-question card into a step-by-step wizard so multi-question navigation and the final Submit action are easier to see. diff --git a/apps/kimi-web/src/components/chat/QuestionCard.vue b/apps/kimi-web/src/components/chat/QuestionCard.vue index 3194887063..1515c0a753 100644 --- a/apps/kimi-web/src/components/chat/QuestionCard.vue +++ b/apps/kimi-web/src/components/chat/QuestionCard.vue @@ -36,6 +36,23 @@ function goNext(): void { if (step.value < total.value - 1) step.value++; } +function goToStep(index: number): void { + if (index >= 0 && index < total.value) step.value = index; +} + +function isQuestionAnswered(qid: string): boolean { + const a = answers.value[qid]; + if (!a) return false; + if (a.kind === 'multi') return a.optionIds.length > 0; + if (a.kind === 'multiWithOther') return a.optionIds.length > 0 || a.otherText.trim().length > 0; + if (a.kind === 'other') return a.text.trim().length > 0; + return true; +} + +function isCurrentAnswered(): boolean { + return isQuestionAnswered(current.value.id); +} + // --------------------------------------------------------------------------- // Per-question answers: Record // --------------------------------------------------------------------------- @@ -145,14 +162,7 @@ function isOtherSelected(qid: string): boolean { function canSubmit(): boolean { // All questions must have an answer - return props.question.questions.every((qi) => { - const a = answers.value[qi.id]; - if (!a) return false; - if (a.kind === 'multi') return a.optionIds.length > 0; - if (a.kind === 'multiWithOther') return a.optionIds.length > 0 || a.otherText.trim().length > 0; - if (a.kind === 'other') return a.text.trim().length > 0; - return true; - }); + return props.question.questions.every((qi) => isQuestionAnswered(qi.id)); } // --------------------------------------------------------------------------- @@ -184,7 +194,15 @@ function handleKeydown(e: KeyboardEvent): void { if (minimized.value && e.key !== 'Escape') return; if (e.key === 'Escape') { e.preventDefault(); dismiss(); return; } - if (e.key === 'Enter') { e.preventDefault(); submit(); return; } + if (e.key === 'Enter') { + e.preventDefault(); + if (step.value < total.value - 1 && isCurrentAnswered()) { + goNext(); + } else if (canSubmit()) { + submit(); + } + return; + } const num = parseInt(e.key, 10); if (!isNaN(num) && num >= 1 && num <= 9) { @@ -208,14 +226,10 @@ onUnmounted(() => document.removeEventListener('keydown', handleKeydown)); @@ -322,18 +373,6 @@ onUnmounted(() => document.removeEventListener('keydown', handleKeydown)); } .qtitle { color: var(--blue2); font-weight: 700; } .qstep { color: var(--muted); font-size: calc(var(--ui-font-size) - 3px); margin-left: 4px; } -.qnav { - font-family: var(--mono); - font-size: calc(var(--ui-font-size) - 3px); - padding: 2px 8px; - border: 1px solid var(--line); - border-radius: 3px; - background: var(--bg); - color: var(--dim); - cursor: pointer; -} -.qnav:disabled { color: var(--faint); cursor: default; } -.qnav:not(:disabled):hover { background: var(--panel2); } /* Minimize toggle — pinned to the right of the header row. */ .qmin { @@ -368,6 +407,40 @@ onUnmounted(() => document.removeEventListener('keydown', handleKeydown)); /* Body */ .qbody { padding: 12px 14px; } +/* Stepper */ +.qsteps { + display: flex; + align-items: center; + gap: 6px; + margin-bottom: 10px; +} +.qstep-dot { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border-radius: 50%; + border: 1px solid var(--line); + background: var(--bg); + color: var(--dim); + font-size: calc(var(--ui-font-size) - 2px); + cursor: pointer; + padding: 0; + transition: background 0.12s, border-color 0.12s, color 0.12s; +} +.qstep-dot:hover:not(.active) { background: var(--panel2); } +.qstep-dot.active { + border-color: var(--blue); + background: var(--blue); + color: var(--bg); + font-weight: 700; +} +.qstep-dot.answered:not(.active) { + border-color: var(--blue); + color: var(--blue); +} + .qheader-chip { display: inline-block; font-size: max(9px, calc(var(--ui-font-size) - 3.5px)); @@ -474,6 +547,18 @@ onUnmounted(() => document.removeEventListener('keydown', handleKeydown)); } .qbtn.pri:hover:not(:disabled) { background: var(--blue2); } .qbtn:disabled { opacity: 0.45; cursor: default; } +.qbtn-text { + border-color: transparent; + background: transparent; + color: var(--muted); + padding-left: 8px; + padding-right: 8px; +} +.qbtn-text:hover:not(:disabled) { + background: transparent; + color: var(--text); + text-decoration: underline; +} /* ========================================================================= MOBILE (≤640px): bigger option taps, comfortable nav, and full-width footer @@ -482,11 +567,17 @@ onUnmounted(() => document.removeEventListener('keydown', handleKeydown)); ========================================================================= */ @media (max-width: 640px) { .qh { padding: 9px 12px; flex-wrap: wrap; row-gap: 6px; } - .qnav { min-height: 34px; padding: 5px 12px; font-size: var(--ui-font-size-xs); border-radius: 6px; } .qbody { padding: 14px; } .qtext { font-size: var(--ui-font-size); } + /* Stepper → slightly larger tap targets. */ + .qstep-dot { + width: 28px; + height: 28px; + font-size: var(--ui-font-size-xs); + } + /* Options → taller, finger-friendly rows. Label + description already stack via .qopt-text, so no flex-wrap hack is needed. */ .qopt { @@ -498,7 +589,7 @@ onUnmounted(() => document.removeEventListener('keydown', handleKeydown)); .qopt-desc { font-size: var(--ui-font-size-xs); } .other-input { flex-basis: 100%; min-height: 28px; } - /* Footer → full-width stacked buttons, Submit on top. */ + /* Footer → full-width stacked buttons, Next/Submit on top. */ .qfooter { flex-direction: column; gap: 8px; padding: 12px 14px max(14px, env(safe-area-inset-bottom)); } .qbtn { width: 100%; @@ -506,5 +597,6 @@ onUnmounted(() => document.removeEventListener('keydown', handleKeydown)); font-size: var(--ui-font-size); border-radius: 8px; } + .qfooter-main { order: -1; } } diff --git a/apps/kimi-web/src/i18n/locales/en/question.ts b/apps/kimi-web/src/i18n/locales/en/question.ts index 43b703c95a..84423bbe36 100644 --- a/apps/kimi-web/src/i18n/locales/en/question.ts +++ b/apps/kimi-web/src/i18n/locales/en/question.ts @@ -1,8 +1,8 @@ export default { title: 'Question', step: 'Q{current}/{total}', - prev: '‹ Prev', - next: 'Next ›', + back: '‹ Back', + nextQuestion: 'Next question ›', otherDefault: 'Other…', submit: 'Submit', dismiss: 'Dismiss', diff --git a/apps/kimi-web/src/i18n/locales/zh/question.ts b/apps/kimi-web/src/i18n/locales/zh/question.ts index 384f14797a..1fabbfb9c6 100644 --- a/apps/kimi-web/src/i18n/locales/zh/question.ts +++ b/apps/kimi-web/src/i18n/locales/zh/question.ts @@ -1,8 +1,8 @@ export default { title: '提问', step: 'Q{current}/{total}', - prev: '‹ 上一', - next: '下一 ›', + back: '‹ 返回', + nextQuestion: '下一题 ›', otherDefault: '其他…', submit: '提交', dismiss: '放弃',