Merge pull request #10599 from Kilo-Org/fix/vscode-error-alert-polish

Improve VS Code chat error styling
This commit is contained in:
Iván Uruchurtu
2026-05-28 11:34:49 -06:00
committed by GitHub
8 changed files with 132 additions and 27 deletions
+6
View File
@@ -0,0 +1,6 @@
---
"@kilocode/kilo-ui": patch
"kilo-code": patch
---
Improve chat error styling in the VS Code extension.
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e3050c782d797be7dad951b76199df2c87195415e699d3e8481bbf40ad0dfccf
size 10073
+7
View File
@@ -5,6 +5,13 @@
padding: 8px;
border: 1px solid var(--border-weak-base);
&[data-variant="error"] {
padding: 12px;
background-color: color-mix(in srgb, var(--surface-critical-strong) 10%, var(--surface-inset-base));
border-color: color-mix(in srgb, var(--border-critical-selected) 55%, var(--border-weaker-base));
color: var(--text-base);
}
&[data-variant="warning"] {
padding: 12px 14px;
}
@@ -1,42 +1,92 @@
.error-card {
padding-bottom: 0;
background-color: var(--surface-critical-base);
gap: 8px;
padding-bottom: 12px;
--error-card-accent: var(--text-on-critical-base);
}
.error-card-body {
display: flex;
align-items: flex-start;
gap: 8px;
}
.error-card-body [data-component="icon"] {
color: var(--error-card-accent);
margin-top: 2px;
}
.error-card-message {
flex: 1;
min-width: 0;
color: var(--text-strong);
font-size: var(--font-size-base);
line-height: var(--line-height-large);
overflow-wrap: anywhere;
}
.error-card [data-component="collapsible"] {
margin-top: 8px;
margin-top: 0;
padding-left: 24px;
}
.error-details-trigger {
.error-card .error-details-trigger[data-slot="collapsible-trigger"] {
display: inline-flex;
align-items: center;
gap: 4px;
align-self: flex-start;
gap: 2px;
width: auto;
height: 22px;
font-size: var(--font-size-small);
font-weight: var(--font-weight-medium);
opacity: 0.85;
cursor: pointer;
background: none;
border: none;
color: inherit;
padding: 0;
border-radius: var(--radius-sm);
color: var(--error-card-accent);
padding: 0 6px;
}
.error-details-trigger:hover {
.error-card .error-details-trigger[data-slot="collapsible-trigger"]:hover {
background-color: color-mix(in srgb, var(--error-card-accent) 12%, transparent);
opacity: 1;
}
.error-card .error-details-trigger[data-slot="collapsible-trigger"]:focus-visible {
background-color: color-mix(in srgb, var(--error-card-accent) 12%, transparent);
outline: 1px solid var(--border-focus);
outline-offset: 2px;
}
.error-card .error-details-trigger [data-slot="collapsible-arrow"] {
width: 16px;
height: 16px;
opacity: 1;
}
.error-card .error-details-trigger [data-slot="collapsible-arrow-icon"] {
color: currentColor;
}
.error-details {
display: flex;
flex-direction: column;
gap: 4px;
gap: 6px;
font-size: var(--font-size-small);
margin-top: 4px;
margin-top: 8px;
}
.error-detail-pre {
margin: 0;
max-height: 120px;
overflow-y: auto;
background-color: color-mix(in srgb, var(--surface-inset-base) 82%, var(--background-base));
border: 1px solid color-mix(in srgb, var(--border-critical-base) 30%, var(--border-weaker-base));
border-radius: var(--radius-sm);
color: var(--text-base);
font-size: var(--font-size-small);
line-height: var(--line-height-large);
padding: 8px;
white-space: pre-wrap;
word-break: break-all;
flex: 1;
@@ -11,7 +11,7 @@ export function ErrorDetails(props: ErrorDetailsProps) {
return (
<div class="error-details">
<pre class="error-detail-pre">{raw()}</pre>
<pre class="error-detail-pre" data-scrollable>{raw()}</pre>
</div>
)
}
+14 -14
View File
@@ -68,7 +68,7 @@ html[data-theme="kilo-vscode"] {
--surface-critical-base: var(--vscode-editorMarkerNavigationError-headerBackground);
--surface-critical-weak: var(--vscode-editorMarkerNavigationError-headerBackground);
--surface-critical-strong: var(--vscode-charts-red);
--surface-critical-strong: var(--vscode-errorForeground, var(--vscode-charts-red));
--surface-info-base: var(--vscode-editorMarkerNavigationInfo-headerBackground);
--surface-info-weak: var(--vscode-editorMarkerNavigationInfo-headerBackground);
@@ -125,9 +125,9 @@ html[data-theme="kilo-vscode"] {
--text-on-success-base: var(--vscode-charts-green);
--text-on-success-weak: var(--vscode-charts-green);
--text-on-success-strong: var(--vscode-charts-green);
--text-on-critical-base: var(--vscode-charts-red);
--text-on-critical-weak: var(--vscode-charts-red);
--text-on-critical-strong: var(--vscode-charts-red);
--text-on-critical-base: var(--vscode-errorForeground, var(--vscode-charts-red));
--text-on-critical-weak: var(--vscode-errorForeground, var(--vscode-charts-red));
--text-on-critical-strong: var(--vscode-errorForeground, var(--vscode-charts-red));
--text-on-warning-base: var(--vscode-charts-yellow);
--text-on-warning-weak: var(--vscode-charts-yellow);
--text-on-warning-strong: var(--vscode-charts-yellow);
@@ -192,9 +192,9 @@ html[data-theme="kilo-vscode"] {
--border-warning-base: var(--vscode-charts-yellow);
--border-warning-hover: var(--vscode-charts-yellow);
--border-warning-selected: var(--vscode-charts-yellow);
--border-critical-base: var(--vscode-charts-red);
--border-critical-hover: var(--vscode-charts-red);
--border-critical-selected: var(--vscode-charts-red);
--border-critical-base: var(--vscode-inputValidation-errorBorder, var(--vscode-errorForeground, var(--vscode-charts-red)));
--border-critical-hover: var(--vscode-inputValidation-errorBorder, var(--vscode-errorForeground, var(--vscode-charts-red)));
--border-critical-selected: var(--vscode-inputValidation-errorBorder, var(--vscode-errorForeground, var(--vscode-charts-red)));
--border-info-base: var(--vscode-charts-blue);
--border-info-hover: var(--vscode-charts-blue);
--border-info-selected: var(--vscode-charts-blue);
@@ -230,9 +230,9 @@ html[data-theme="kilo-vscode"] {
--icon-warning-base: var(--vscode-charts-yellow);
--icon-warning-hover: var(--vscode-charts-yellow);
--icon-warning-active: var(--vscode-charts-yellow);
--icon-critical-base: var(--vscode-charts-red);
--icon-critical-hover: var(--vscode-charts-red);
--icon-critical-active: var(--vscode-charts-red);
--icon-critical-base: var(--vscode-errorForeground, var(--vscode-charts-red));
--icon-critical-hover: var(--vscode-errorForeground, var(--vscode-charts-red));
--icon-critical-active: var(--vscode-errorForeground, var(--vscode-charts-red));
--icon-info-base: var(--vscode-charts-blue);
--icon-info-hover: var(--vscode-charts-blue);
--icon-info-active: var(--vscode-charts-blue);
@@ -248,9 +248,9 @@ html[data-theme="kilo-vscode"] {
--icon-on-warning-base: var(--vscode-charts-yellow);
--icon-on-warning-hover: var(--vscode-charts-yellow);
--icon-on-warning-selected: var(--vscode-charts-yellow);
--icon-on-critical-base: var(--vscode-charts-red);
--icon-on-critical-hover: var(--vscode-charts-red);
--icon-on-critical-selected: var(--vscode-charts-red);
--icon-on-critical-base: var(--vscode-errorForeground, var(--vscode-charts-red));
--icon-on-critical-hover: var(--vscode-errorForeground, var(--vscode-charts-red));
--icon-on-critical-selected: var(--vscode-errorForeground, var(--vscode-charts-red));
--icon-on-info-base: var(--vscode-charts-blue);
--icon-on-info-hover: var(--vscode-charts-blue);
--icon-on-info-selected: var(--vscode-charts-blue);
@@ -282,7 +282,7 @@ html[data-theme="kilo-vscode"] {
--syntax-object: var(--vscode-editor-foreground);
--syntax-success: var(--vscode-charts-green);
--syntax-warning: var(--vscode-charts-yellow);
--syntax-critical: var(--vscode-charts-red);
--syntax-critical: var(--vscode-errorForeground, var(--vscode-charts-red));
--syntax-info: var(--vscode-charts-blue);
--syntax-diff-add: var(--vscode-gitDecoration-addedResourceForeground);
--syntax-diff-delete: var(--vscode-gitDecoration-deletedResourceForeground);
@@ -3,6 +3,7 @@ import { Card } from "@kilocode/kilo-ui/card"
import { Collapsible } from "@kilocode/kilo-ui/collapsible"
import { useDialog } from "@kilocode/kilo-ui/context/dialog"
import { ErrorDetails } from "@kilocode/kilo-ui/error-details"
import { Icon } from "@kilocode/kilo-ui/icon"
import { Button } from "@kilocode/kilo-ui/button"
import type { AssistantMessage } from "@kilocode/sdk/v2"
import { useLanguage } from "../../context/language"
@@ -62,8 +63,11 @@ export const ErrorDisplay: Component<ErrorDisplayProps> = (props) => {
return (
<Switch
fallback={
<Card variant="error" class="error-card">
{errorText()}
<Card variant="error" class="error-card" role="alert">
<div class="error-card-body">
<Icon name="warning" size="small" />
<div class="error-card-message">{errorText()}</div>
</div>
<Collapsible variant="ghost">
<Collapsible.Trigger class="error-details-trigger">
<span>{t("error.details.show")}</span>
@@ -8,8 +8,10 @@
*/
import type { Meta, StoryObj } from "storybook-solidjs-vite"
import type { AssistantMessage } from "@kilocode/sdk/v2"
import { StoryProviders, defaultMockData, mockSessionValue } from "./StoryProviders"
import { ChatView } from "../components/chat/ChatView"
import { ErrorDisplay } from "../components/chat/ErrorDisplay"
import { TaskHeader } from "../components/chat/TaskHeader"
import { QuestionDock } from "../components/chat/QuestionDock"
import { SuggestBar } from "../components/chat/SuggestBar"
@@ -77,6 +79,28 @@ const reviewSuggestion: SuggestionRequest = {
tool: { messageID: "asst-msg-002", callID: "call-suggest-001" },
}
const policyMessage =
"No endpoints found matching your data policy (Free model training). Configure: https://openrouter.ai/settings/privacy"
const policyError: NonNullable<AssistantMessage["error"]> = {
name: "APIError",
data: {
message: policyMessage,
statusCode: 400,
isRetryable: false,
responseBody: JSON.stringify(
{
error: {
type: "Bad Request",
message: "Data collection is required for this model. Please enable data collection to use this model.",
},
},
null,
2,
),
},
}
// ---------------------------------------------------------------------------
// Meta
// ---------------------------------------------------------------------------
@@ -232,6 +256,17 @@ export const SuggestBarReview: Story = {
),
}
export const ErrorDisplayDataPolicy: Story = {
name: "ErrorDisplay — data policy",
render: () => (
<StoryProviders sessionID={SESSION_ID}>
<div style={{ width: "min(720px, 100%)" }}>
<ErrorDisplay error={policyError} />
</div>
</StoryProviders>
),
}
const toolUserID = "user-msg-spacing-001"
const toolAssistantID = "asst-msg-spacing-001"
const queuedUserID = "user-msg-spacing-002"