summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Hill <[email protected]>2026-03-10 18:52:32 +0000
committerGitHub <[email protected]>2026-03-10 13:52:32 -0500
commitf77e5cf8fb9d9babcfc1b3ba046c0ba571489647 (patch)
treed4424aac3e3bb6438e2af61050daefbdc2e7702b
parente6cdc21f2ddd7264a75eb389693d4d62367ae38c (diff)
downloadopencode-f77e5cf8fb9d9babcfc1b3ba046c0ba571489647.tar.gz
opencode-f77e5cf8fb9d9babcfc1b3ba046c0ba571489647.zip
feat(ui): restyle Card and improve tool error cards (#16888)
Co-authored-by: Adam <[email protected]>
-rw-r--r--packages/ui/src/components/card.css109
-rw-r--r--packages/ui/src/components/card.stories.tsx14
-rw-r--r--packages/ui/src/components/card.tsx107
-rw-r--r--packages/ui/src/components/markdown.css6
-rw-r--r--packages/ui/src/components/message-part.css36
-rw-r--r--packages/ui/src/components/message-part.tsx21
-rw-r--r--packages/ui/src/components/tool-error-card.css54
-rw-r--r--packages/ui/src/components/tool-error-card.stories.tsx96
-rw-r--r--packages/ui/src/components/tool-error-card.tsx112
-rw-r--r--packages/ui/src/styles/index.css1
-rw-r--r--packages/ui/src/styles/theme.css4
-rw-r--r--packages/ui/src/theme/themes/oc-2.json6
12 files changed, 476 insertions, 90 deletions
diff --git a/packages/ui/src/components/card.css b/packages/ui/src/components/card.css
index 6dae47223..2d482dba7 100644
--- a/packages/ui/src/components/card.css
+++ b/packages/ui/src/components/card.css
@@ -1,29 +1,94 @@
[data-component="card"] {
+ --card-pad-y: 10px;
+ --card-pad-r: 12px;
+ --card-pad-l: 10px;
+
width: 100%;
display: flex;
flex-direction: column;
- background-color: var(--surface-inset-base);
- border: 1px solid var(--border-weaker-base);
- transition: background-color 0.15s ease;
+ position: relative;
+ background: transparent;
+ border: none;
border-radius: var(--radius-md);
- padding: 6px 12px;
- overflow: clip;
-
- &[data-variant="error"] {
- background-color: var(--surface-critical-weak);
- border: 1px solid var(--border-critical-base);
- color: rgba(218, 51, 25, 0.6);
-
- /* text-12-regular */
- font-family: var(--font-family-sans);
- font-size: var(--font-size-small);
- font-style: normal;
- font-weight: var(--font-weight-regular);
- line-height: var(--line-height-large); /* 166.667% */
- letter-spacing: var(--letter-spacing-normal);
-
- &[data-component="icon"] {
- color: var(--icon-critical-active);
- }
+ padding: var(--card-pad-y) var(--card-pad-r) var(--card-pad-y) var(--card-pad-l);
+
+ /* text-14-regular */
+ font-family: var(--font-family-sans);
+ font-size: var(--font-size-base);
+ font-style: normal;
+ font-weight: var(--font-weight-regular);
+ line-height: var(--line-height-large);
+ letter-spacing: var(--letter-spacing-normal);
+ color: var(--text-strong);
+
+ --card-gap: 8px;
+ --card-icon: 16px;
+ --card-indent: 0px;
+ --card-line-pad: 8px;
+
+ --card-accent: var(--icon-active);
+
+ &:has([data-slot="card-title"]) {
+ gap: 8px;
+ }
+
+ &:has([data-slot="card-title-icon"]) {
+ --card-indent: calc(var(--card-icon) + var(--card-gap));
+ }
+
+ &::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: var(--card-line-pad);
+ bottom: var(--card-line-pad);
+ width: 2px;
+ border-radius: 2px;
+ background-color: var(--card-accent);
+ }
+
+ :where([data-card="title"], [data-slot="card-title"]) {
+ color: var(--text-strong);
+ font-weight: var(--font-weight-medium);
+ }
+
+ :where([data-slot="card-title"]) {
+ display: flex;
+ align-items: center;
+ gap: var(--card-gap);
+ }
+
+ :where([data-slot="card-title"]) [data-component="icon"] {
+ color: var(--card-accent);
+ }
+
+ :where([data-slot="card-title-icon"]) {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: var(--card-icon);
+ height: var(--card-icon);
+ flex: 0 0 auto;
+ }
+
+ :where([data-slot="card-title-icon"][data-placeholder]) [data-component="icon"] {
+ color: var(--text-weak);
+ }
+
+ :where([data-slot="card-title-icon"])
+ [data-slot="icon-svg"]
+ :is(path, line, polyline, polygon, rect, circle, ellipse)[stroke] {
+ stroke-width: 1.5px !important;
+ }
+
+ :where([data-card="description"], [data-slot="card-description"]) {
+ color: var(--text-base);
+ white-space: pre-wrap;
+ overflow-wrap: anywhere;
+ word-break: break-word;
+ }
+
+ :where([data-card="actions"], [data-slot="card-actions"]) {
+ padding-left: var(--card-indent);
}
}
diff --git a/packages/ui/src/components/card.stories.tsx b/packages/ui/src/components/card.stories.tsx
index befb2d34f..5b9cf3830 100644
--- a/packages/ui/src/components/card.stories.tsx
+++ b/packages/ui/src/components/card.stories.tsx
@@ -1,5 +1,5 @@
// @ts-nocheck
-import { Card } from "./card"
+import { Card, CardActions, CardDescription, CardTitle } from "./card"
import { Button } from "./button"
const docs = `### Overview
@@ -49,15 +49,13 @@ export default {
render: (props: { variant?: "normal" | "error" | "warning" | "success" | "info" }) => {
return (
<Card variant={props.variant}>
- <div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
- <div style={{ flex: 1 }}>
- <div style={{ fontWeight: 500 }}>Card title</div>
- <div style={{ color: "var(--text-weak)", fontSize: "13px" }}>Small supporting text.</div>
- </div>
- <Button size="small" variant="ghost">
+ <CardTitle variant={props.variant}>Card title</CardTitle>
+ <CardDescription>Small supporting text.</CardDescription>
+ <CardActions>
+ <Button size="small" variant="secondary">
Action
</Button>
- </div>
+ </CardActions>
</Card>
)
},
diff --git a/packages/ui/src/components/card.tsx b/packages/ui/src/components/card.tsx
index 3fb225ab2..7a1bd5e45 100644
--- a/packages/ui/src/components/card.tsx
+++ b/packages/ui/src/components/card.tsx
@@ -1,16 +1,57 @@
import { type ComponentProps, splitProps } from "solid-js"
+import { Icon, type IconProps } from "./icon"
+
+type Variant = "normal" | "error" | "warning" | "success" | "info"
export interface CardProps extends ComponentProps<"div"> {
- variant?: "normal" | "error" | "warning" | "success" | "info"
+ variant?: Variant
+}
+
+export interface CardTitleProps extends ComponentProps<"div"> {
+ variant?: Variant
+
+ /**
+ * Optional title icon.
+ *
+ * - `undefined`: picks a default icon based on `variant` (error/warning/success/info)
+ * - `false`/`null`: disables the icon
+ * - `Icon` name: forces a specific icon
+ */
+ icon?: IconProps["name"] | false | null
+}
+
+function pick(variant: Variant) {
+ if (variant === "error") return "circle-ban-sign" as const
+ if (variant === "warning") return "warning" as const
+ if (variant === "success") return "circle-check" as const
+ if (variant === "info") return "help" as const
+ return
+}
+
+function mix(style: ComponentProps<"div">["style"], value?: string) {
+ if (!value) return style
+ if (!style) return { "--card-accent": value }
+ if (typeof style === "string") return `${style};--card-accent:${value};`
+ return { ...(style as Record<string, string | number>), "--card-accent": value }
}
export function Card(props: CardProps) {
- const [split, rest] = splitProps(props, ["variant", "class", "classList"])
+ const [split, rest] = splitProps(props, ["variant", "style", "class", "classList"])
+ const variant = () => split.variant ?? "normal"
+ const accent = () => {
+ const v = variant()
+ if (v === "error") return "var(--icon-critical-base)"
+ if (v === "warning") return "var(--icon-warning-active)"
+ if (v === "success") return "var(--icon-success-active)"
+ if (v === "info") return "var(--icon-info-active)"
+ return
+ }
return (
<div
{...rest}
data-component="card"
- data-variant={split.variant || "normal"}
+ data-variant={variant()}
+ style={mix(split.style, accent())}
classList={{
...(split.classList ?? {}),
[split.class ?? ""]: !!split.class,
@@ -20,3 +61,63 @@ export function Card(props: CardProps) {
</div>
)
}
+
+export function CardTitle(props: CardTitleProps) {
+ const [split, rest] = splitProps(props, ["variant", "icon", "class", "classList", "children"])
+ const show = () => split.icon !== false && split.icon !== null
+ const name = () => {
+ if (split.icon === false || split.icon === null) return
+ if (typeof split.icon === "string") return split.icon
+ return pick(split.variant ?? "normal")
+ }
+ const placeholder = () => !name()
+ return (
+ <div
+ {...rest}
+ data-slot="card-title"
+ classList={{
+ ...(split.classList ?? {}),
+ [split.class ?? ""]: !!split.class,
+ }}
+ >
+ {show() ? (
+ <span data-slot="card-title-icon" data-placeholder={placeholder() || undefined}>
+ <Icon name={name() ?? "dash"} size="small" />
+ </span>
+ ) : null}
+ {split.children}
+ </div>
+ )
+}
+
+export function CardDescription(props: ComponentProps<"div">) {
+ const [split, rest] = splitProps(props, ["class", "classList", "children"])
+ return (
+ <div
+ {...rest}
+ data-slot="card-description"
+ classList={{
+ ...(split.classList ?? {}),
+ [split.class ?? ""]: !!split.class,
+ }}
+ >
+ {split.children}
+ </div>
+ )
+}
+
+export function CardActions(props: ComponentProps<"div">) {
+ const [split, rest] = splitProps(props, ["class", "classList", "children"])
+ return (
+ <div
+ {...rest}
+ data-slot="card-actions"
+ classList={{
+ ...(split.classList ?? {}),
+ [split.class ?? ""]: !!split.class,
+ }}
+ >
+ {split.children}
+ </div>
+ )
+}
diff --git a/packages/ui/src/components/markdown.css b/packages/ui/src/components/markdown.css
index 1fe11a7de..f82723807 100644
--- a/packages/ui/src/components/markdown.css
+++ b/packages/ui/src/components/markdown.css
@@ -60,6 +60,7 @@
ol {
margin-top: 0.5rem;
margin-bottom: 1rem;
+ margin-left: 0;
padding-left: 1.5rem;
list-style-position: outside;
}
@@ -70,6 +71,7 @@
ol {
list-style-type: decimal;
+ padding-left: 2.25rem;
}
li {
@@ -98,6 +100,10 @@
padding-left: 1rem; /* Minimal indent for nesting only */
}
+ li > ol {
+ padding-left: 1.75rem;
+ }
+
/* Blockquotes */
blockquote {
border-left: 2px solid var(--border-weak-base);
diff --git a/packages/ui/src/components/message-part.css b/packages/ui/src/components/message-part.css
index 704a57e5b..7ee537884 100644
--- a/packages/ui/src/components/message-part.css
+++ b/packages/ui/src/components/message-part.css
@@ -309,41 +309,6 @@
}
}
-[data-component="tool-error"] {
- display: flex;
- align-items: start;
- gap: 8px;
-
- [data-slot="icon-svg"] {
- color: var(--icon-critical-base);
- margin-top: 4px;
- }
-
- [data-slot="message-part-tool-error-content"] {
- display: flex;
- align-items: start;
- gap: 8px;
- }
-
- [data-slot="message-part-tool-error-title"] {
- font-family: var(--font-family-sans);
- font-size: var(--font-size-base);
- font-style: normal;
- font-weight: var(--font-weight-medium);
- line-height: var(--line-height-large);
- letter-spacing: var(--letter-spacing-normal);
- color: var(--text-on-critical-base);
- white-space: nowrap;
- }
-
- [data-slot="message-part-tool-error-message"] {
- color: var(--text-on-critical-weak);
- max-height: 240px;
- overflow-y: auto;
- word-break: break-word;
- }
-}
-
[data-component="tool-output"] {
white-space: pre;
padding: 0;
@@ -717,7 +682,6 @@
[data-component="user-message"] [data-slot="user-message-text"],
[data-component="text-part"],
[data-component="reasoning-part"],
-[data-component="tool-error"],
[data-component="tool-output"],
[data-component="bash-output"],
[data-component="edit-content"],
diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx
index 45b174e2b..0815c3333 100644
--- a/packages/ui/src/components/message-part.tsx
+++ b/packages/ui/src/components/message-part.tsx
@@ -39,6 +39,7 @@ import { Card } from "./card"
import { Collapsible } from "./collapsible"
import { FileIcon } from "./file-icon"
import { Icon } from "./icon"
+import { ToolErrorCard } from "./tool-error-card"
import { Checkbox } from "./checkbox"
import { DiffChanges } from "./diff-changes"
import { Markdown } from "./markdown"
@@ -1189,25 +1190,7 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
</div>
)
}
- const [title, ...rest] = cleaned.split(": ")
- return (
- <Card variant="error">
- <div data-component="tool-error">
- <Icon name="circle-ban-sign" size="small" />
- <Switch>
- <Match when={title && title.length < 30}>
- <div data-slot="message-part-tool-error-content">
- <div data-slot="message-part-tool-error-title">{title}</div>
- <span data-slot="message-part-tool-error-message">{rest.join(": ")}</span>
- </div>
- </Match>
- <Match when={true}>
- <span data-slot="message-part-tool-error-message">{cleaned}</span>
- </Match>
- </Switch>
- </div>
- </Card>
- )
+ return <ToolErrorCard tool={part().tool} error={error()} />
}}
</Match>
<Match when={true}>
diff --git a/packages/ui/src/components/tool-error-card.css b/packages/ui/src/components/tool-error-card.css
new file mode 100644
index 000000000..e93484f23
--- /dev/null
+++ b/packages/ui/src/components/tool-error-card.css
@@ -0,0 +1,54 @@
+[data-component="card"][data-kind="tool-error-card"] {
+ --card-pad-y: 8px;
+ --card-line-pad: 12px;
+
+ > [data-component="collapsible"].tool-collapsible {
+ gap: 0px;
+ }
+
+ > [data-component="collapsible"].tool-collapsible[data-open="true"] {
+ gap: 4px;
+ }
+
+ [data-component="tool-error-card-icon"] [data-component="icon"] {
+ color: var(--card-accent);
+ }
+
+ [data-slot="tool-error-card-content"] {
+ position: relative;
+ padding-left: 24px;
+ margin-bottom: 8px;
+ -webkit-user-select: text;
+ user-select: text;
+ }
+
+ > [data-component="collapsible"].tool-collapsible[data-open="true"] [data-slot="tool-error-card-content"] {
+ padding-right: 40px;
+ }
+
+ [data-slot="tool-error-card-copy"] {
+ position: absolute;
+ top: 0;
+ right: 0;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.15s ease;
+ will-change: opacity;
+ }
+
+ &:hover [data-slot="tool-error-card-copy"],
+ &:focus-within [data-slot="tool-error-card-copy"] {
+ opacity: 1;
+ pointer-events: auto;
+ }
+
+ [data-slot="tool-error-card-content"] :where(*)::selection {
+ background: var(--surface-critical-base);
+ color: var(--text-on-critical-base);
+ }
+
+ [data-slot="tool-error-card-content"] :where(*)::-moz-selection {
+ background: var(--surface-critical-base);
+ color: var(--text-on-critical-base);
+ }
+}
diff --git a/packages/ui/src/components/tool-error-card.stories.tsx b/packages/ui/src/components/tool-error-card.stories.tsx
new file mode 100644
index 000000000..03349ce01
--- /dev/null
+++ b/packages/ui/src/components/tool-error-card.stories.tsx
@@ -0,0 +1,96 @@
+// @ts-nocheck
+import { ToolErrorCard } from "./tool-error-card"
+
+const docs = `### Overview
+Tool call failure summary styled like a tool trigger.
+
+### API
+- Required: \`tool\` (tool id, e.g. apply_patch, bash)
+- Required: \`error\` (error string)
+
+### Behavior
+- Collapsible; click header to expand/collapse.
+`
+
+const samples = [
+ {
+ tool: "apply_patch",
+ error:
+ "apply_patch verification failed: Failed to find expected lines in /Users/davidhill/Documents/Local/opencode/packages/ui/src/components/session-turn.tsx",
+ },
+ {
+ tool: "bash",
+ error: "bash Command failed: exit code 1: bun test --watch",
+ },
+ {
+ tool: "read",
+ error:
+ "read File not found: /Users/davidhill/Documents/Local/opencode/packages/ui/src/components/does-not-exist.tsx",
+ },
+ {
+ tool: "glob",
+ error: "glob Pattern error: Invalid glob pattern: **/*[",
+ },
+ {
+ tool: "grep",
+ error: "grep Regex error: Invalid regular expression: (unterminated group",
+ },
+ {
+ tool: "webfetch",
+ error: "webfetch Request failed: 502 Bad Gateway",
+ },
+ {
+ tool: "websearch",
+ error: "websearch Rate limited: Please try again in 30 seconds",
+ },
+ {
+ tool: "codesearch",
+ error: "codesearch Timeout: exceeded 120s",
+ },
+ {
+ tool: "question",
+ error: "question Dismissed: user dismissed this question",
+ },
+]
+
+export default {
+ title: "UI/ToolErrorCard",
+ id: "components-tool-error-card",
+ component: ToolErrorCard,
+ tags: ["autodocs"],
+ parameters: {
+ docs: {
+ description: {
+ component: docs,
+ },
+ },
+ },
+ args: {
+ tool: "apply_patch",
+ error: samples[0].error,
+ },
+ argTypes: {
+ tool: {
+ control: "select",
+ options: ["apply_patch", "bash", "read", "glob", "grep", "webfetch", "websearch", "codesearch", "question"],
+ },
+ error: {
+ control: "text",
+ },
+ },
+ render: (props: { tool: string; error: string }) => {
+ return <ToolErrorCard tool={props.tool} error={props.error} />
+ },
+}
+
+export const All = {
+ render: () => {
+ return (
+ <div style="display: flex; flex-direction: column; gap: 12px; max-width: 720px;">
+ {samples.map((item) => (
+ <ToolErrorCard tool={item.tool} error={item.error} />
+ ))}
+ </div>
+ )
+ },
+}
diff --git a/packages/ui/src/components/tool-error-card.tsx b/packages/ui/src/components/tool-error-card.tsx
new file mode 100644
index 000000000..13873ae90
--- /dev/null
+++ b/packages/ui/src/components/tool-error-card.tsx
@@ -0,0 +1,112 @@
+import { type ComponentProps, createMemo, createSignal, Show, splitProps } from "solid-js"
+import { Card, CardDescription } from "./card"
+import { Collapsible } from "./collapsible"
+import { Icon } from "./icon"
+import { IconButton } from "./icon-button"
+import { Tooltip } from "./tooltip"
+import { useI18n } from "../context/i18n"
+
+export interface ToolErrorCardProps extends Omit<ComponentProps<typeof Card>, "children" | "variant"> {
+ tool: string
+ error: string
+}
+
+export function ToolErrorCard(props: ToolErrorCardProps) {
+ const i18n = useI18n()
+ const [open, setOpen] = createSignal(true)
+ const [copied, setCopied] = createSignal(false)
+ const [split, rest] = splitProps(props, ["tool", "error"])
+ const name = createMemo(() => {
+ const map: Record<string, string> = {
+ read: "ui.tool.read",
+ list: "ui.tool.list",
+ glob: "ui.tool.glob",
+ grep: "ui.tool.grep",
+ webfetch: "ui.tool.webfetch",
+ websearch: "ui.tool.websearch",
+ codesearch: "ui.tool.codesearch",
+ bash: "ui.tool.shell",
+ apply_patch: "ui.tool.patch",
+ question: "ui.tool.questions",
+ }
+ const key = map[split.tool]
+ if (!key) return split.tool
+ return i18n.t(key)
+ })
+ const cleaned = createMemo(() => split.error.replace(/^Error:\s*/, "").trim())
+ const tail = createMemo(() => {
+ const value = cleaned()
+ const prefix = `${split.tool} `
+ if (value.startsWith(prefix)) return value.slice(prefix.length)
+ return value
+ })
+
+ const subtitle = createMemo(() => {
+ const parts = tail().split(": ")
+ if (parts.length <= 1) return "Failed"
+ const head = (parts[0] ?? "").trim()
+ if (!head) return "Failed"
+ return head[0] ? head[0].toUpperCase() + head.slice(1) : "Failed"
+ })
+
+ const body = createMemo(() => {
+ const parts = tail().split(": ")
+ if (parts.length <= 1) return cleaned()
+ return parts.slice(1).join(": ").trim() || cleaned()
+ })
+
+ const copy = async () => {
+ const text = cleaned()
+ if (!text) return
+ await navigator.clipboard.writeText(text)
+ setCopied(true)
+ setTimeout(() => setCopied(false), 2000)
+ }
+
+ return (
+ <Card {...rest} data-kind="tool-error-card" data-open={open() ? "true" : "false"} variant="error">
+ <Collapsible class="tool-collapsible" data-open={open() ? "true" : "false"} open={open()} onOpenChange={setOpen}>
+ <Collapsible.Trigger>
+ <div data-component="tool-trigger">
+ <div data-slot="basic-tool-tool-trigger-content">
+ <span data-slot="basic-tool-tool-indicator" data-component="tool-error-card-icon">
+ <Icon name="circle-ban-sign" size="small" style={{ "stroke-width": 1.5 }} />
+ </span>
+ <div data-slot="basic-tool-tool-info">
+ <div data-slot="basic-tool-tool-info-structured">
+ <div data-slot="basic-tool-tool-info-main">
+ <span data-slot="basic-tool-tool-title">{name()}</span>
+ <span data-slot="basic-tool-tool-subtitle">{subtitle()}</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ <Collapsible.Arrow />
+ </div>
+ </Collapsible.Trigger>
+ <Collapsible.Content>
+ <div data-slot="tool-error-card-content">
+ <Show when={open()}>
+ <div data-slot="tool-error-card-copy">
+ <Tooltip value={copied() ? i18n.t("ui.message.copied") : "Copy error"} placement="top" gutter={4}>
+ <IconButton
+ icon={copied() ? "check" : "copy"}
+ size="normal"
+ variant="ghost"
+ onMouseDown={(e) => e.preventDefault()}
+ onClick={(e) => {
+ e.stopPropagation()
+ copy()
+ }}
+ aria-label={copied() ? i18n.t("ui.message.copied") : "Copy error"}
+ />
+ </Tooltip>
+ </div>
+ </Show>
+ <Show when={body()}>{(value) => <CardDescription>{value()}</CardDescription>}</Show>
+ </div>
+ </Collapsible.Content>
+ </Collapsible>
+ </Card>
+ )
+}
diff --git a/packages/ui/src/styles/index.css b/packages/ui/src/styles/index.css
index cec42f5a0..1b17f6c2b 100644
--- a/packages/ui/src/styles/index.css
+++ b/packages/ui/src/styles/index.css
@@ -13,6 +13,7 @@
@import "../components/basic-tool.css" layer(components);
@import "../components/button.css" layer(components);
@import "../components/card.css" layer(components);
+@import "../components/tool-error-card.css" layer(components);
@import "../components/checkbox.css" layer(components);
@import "../components/file.css" layer(components);
@import "../components/collapsible.css" layer(components);
diff --git a/packages/ui/src/styles/theme.css b/packages/ui/src/styles/theme.css
index 702d1e4e6..021f959e4 100644
--- a/packages/ui/src/styles/theme.css
+++ b/packages/ui/src/styles/theme.css
@@ -131,7 +131,7 @@
--surface-warning-base: #fcf3cb;
--surface-warning-weak: #fdfaec;
--surface-warning-strong: #fbdd46;
- --surface-critical-base: #feefeb;
+ --surface-critical-base: #fff2f0;
--surface-critical-weak: #fff8f6;
--surface-critical-strong: #fc533a;
--surface-info-base: #fdecfe;
@@ -391,7 +391,7 @@
--surface-warning-base: #fdf3cf;
--surface-warning-weak: #fdfaed;
--surface-warning-strong: #fcd53a;
- --surface-critical-base: #42120b;
+ --surface-critical-base: #1f0603;
--surface-critical-weak: #28110c;
--surface-critical-strong: #fc533a;
--surface-info-base: #feecfe;
diff --git a/packages/ui/src/theme/themes/oc-2.json b/packages/ui/src/theme/themes/oc-2.json
index fdf0c2caf..dc413f061 100644
--- a/packages/ui/src/theme/themes/oc-2.json
+++ b/packages/ui/src/theme/themes/oc-2.json
@@ -13,6 +13,9 @@
"interactive": "#034cff",
"diffAdd": "#9ff29a",
"diffDelete": "#fc533a"
+ },
+ "overrides": {
+ "surface-critical-base": "#FFF2F0"
}
},
"dark": {
@@ -26,6 +29,9 @@
"interactive": "#034cff",
"diffAdd": "#c8ffc4",
"diffDelete": "#fc533a"
+ },
+ "overrides": {
+ "surface-critical-base": "#1F0603"
}
}
}