mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-24 16:02:55 +08:00
Merge pull request #10599 from Kilo-Org/fix/vscode-error-alert-polish
Improve VS Code chat error styling
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@kilocode/kilo-ui": patch
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Improve chat error styling in the VS Code extension.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e3050c782d797be7dad951b76199df2c87195415e699d3e8481bbf40ad0dfccf
|
||||
size 10073
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user