mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-29 20:22:58 +00:00
fix(tui): unify attention indicators with unread accent (#45741)
Use the unread accent color for question and permission status indicators by default, preserving semantic tokens and explicit theme overrides.
This commit is contained in:
parent
39416a0d95
commit
f607ca4c72
4 changed files with 39 additions and 8 deletions
5
.changeset/attention-accent-color.md
Normal file
5
.changeset/attention-accent-color.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@opencode-ai/theme": patch
|
||||
---
|
||||
|
||||
Use the unread accent color by default for question and permission status indicators, while preserving explicit theme overrides.
|
||||
|
|
@ -123,8 +123,8 @@ export const DEFAULT_THEME = {
|
|||
},
|
||||
status: {
|
||||
running: "$hue.interactive.800",
|
||||
question: "$text.feedback.info.default",
|
||||
permission: "$text.feedback.warning.default",
|
||||
question: "$text.status.unread",
|
||||
permission: "$text.status.unread",
|
||||
unread: "$hue.accent.800",
|
||||
},
|
||||
feedback: {
|
||||
|
|
@ -344,8 +344,8 @@ export const DEFAULT_THEME = {
|
|||
},
|
||||
status: {
|
||||
running: "$hue.interactive.200",
|
||||
question: "$text.feedback.info.default",
|
||||
permission: "$text.feedback.warning.default",
|
||||
question: "$text.status.unread",
|
||||
permission: "$text.status.unread",
|
||||
unread: "$hue.accent.200",
|
||||
},
|
||||
feedback: {
|
||||
|
|
|
|||
|
|
@ -11,13 +11,33 @@ test.each(["light", "dark"] as const)("built-in %s themes resolve status colors"
|
|||
for (const document of [DEFAULT_THEME, migrateV1(source)]) {
|
||||
const theme = resolveThemeDocument(document, mode)
|
||||
expect(theme.text.status.running.equals(theme.hue.interactive[mode === "light" ? 800 : 200])).toBeTrue()
|
||||
expect(theme.text.status.question.equals(theme.text.feedback.info.default)).toBeTrue()
|
||||
expect(theme.text.status.permission.equals(theme.text.feedback.warning.default)).toBeTrue()
|
||||
expect(theme.text.status.question.equals(theme.text.status.unread)).toBeTrue()
|
||||
expect(theme.text.status.permission.equals(theme.text.status.unread)).toBeTrue()
|
||||
expect(theme.text.status.unread.equals(theme.hue.accent[mode === "light" ? 800 : 200])).toBeTrue()
|
||||
expect(theme.contextual.elevated.text.status).toEqual(theme.text.status)
|
||||
}
|
||||
})
|
||||
|
||||
test.each(["light", "dark"] as const)("custom %s themes inherit the unread attention color", (mode) => {
|
||||
for (const standalone of [false, true]) {
|
||||
const theme = resolveThemeDocument(
|
||||
Schema.decodeUnknownSync(ThemeDocument)({
|
||||
version: 2,
|
||||
standalone,
|
||||
[mode]: {
|
||||
hue: { ...DEFAULT_THEME[mode].hue, accent: "$hue.purple" },
|
||||
text: { status: { unread: "#abcdef" } },
|
||||
},
|
||||
}),
|
||||
mode,
|
||||
)
|
||||
expect(theme.text.status.unread.equals(RGBA.fromHex("#abcdef"))).toBeTrue()
|
||||
expect(theme.text.status.question.equals(theme.text.status.unread)).toBeTrue()
|
||||
expect(theme.text.status.permission.equals(theme.text.status.unread)).toBeTrue()
|
||||
expect(theme.contextual.elevated.text.status).toEqual(theme.text.status)
|
||||
}
|
||||
})
|
||||
|
||||
test.each(["light", "dark"] as const)("custom %s themes inherit and override status colors", (mode) => {
|
||||
for (const standalone of [false, true]) {
|
||||
const theme = resolveThemeDocument(
|
||||
|
|
@ -27,8 +47,7 @@ test.each(["light", "dark"] as const)("custom %s themes inherit and override sta
|
|||
[mode]: {
|
||||
hue: { ...DEFAULT_THEME[mode].hue, interactive: "$hue.purple", accent: "$hue.orange" },
|
||||
text: {
|
||||
feedback: { warning: { default: "#654321" } },
|
||||
status: { question: "#123456" },
|
||||
status: { question: "#123456", permission: "#654321" },
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -124,6 +124,12 @@ for (const orientation of ["horizontal", "vertical"] as const) {
|
|||
setActive("second")
|
||||
setStatus({ ...EMPTY_SESSION_TAB_STATUS, busy: true, attention })
|
||||
await app.renderOnce()
|
||||
const indicatorColor = () =>
|
||||
app
|
||||
.captureSpans()
|
||||
.lines.flatMap((line) => line.spans)
|
||||
.find((span) => span.text.trim() === (attention === "question" ? "?" : "!"))?.fg
|
||||
expect(indicatorColor()?.toInts()).toEqual(theme.text.status[attention].toInts())
|
||||
const glow = () => {
|
||||
const colors = app
|
||||
.captureSpans()
|
||||
|
|
@ -140,6 +146,7 @@ for (const orientation of ["horizontal", "vertical"] as const) {
|
|||
expect(full).toBeGreaterThan(0)
|
||||
setActive("first")
|
||||
await app.renderOnce()
|
||||
expect(indicatorColor()?.toInts()).toEqual(theme.text.status[attention].toInts())
|
||||
const dim = glow()
|
||||
expect(dim).toBeGreaterThan(0)
|
||||
expect(dim).toBeLessThan(full)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue