fix(tui): honor skin highlight colors (#20895)

This commit is contained in:
brooklyn! 2026-05-06 14:01:56 -07:00 committed by GitHub
parent da6019820a
commit f1a8e99942
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 61 additions and 6 deletions

View file

@ -42,6 +42,7 @@ All fields are optional. Missing values inherit from the ``default`` skin.
session_border: "#8B8682" # Session ID dim color
status_bar_bg: "#1a1a2e" # TUI status/usage bar background
voice_status_bg: "#1a1a2e" # TUI voice status background
selection_bg: "#333355" # TUI mouse-selection highlight background
completion_menu_bg: "#1a1a2e" # Completion menu background
completion_menu_current_bg: "#333355" # Active completion row background
completion_menu_meta_bg: "#1a1a2e" # Completion meta column background

View file

@ -209,6 +209,34 @@ describe('fromSkin', () => {
expect(theme.color.completionCurrentBg).toBe('#bfbfbf')
})
it('uses active completion color as the selection highlight fallback', async () => {
const { fromSkin } = await importThemeWithCleanEnv()
const theme = fromSkin({ completion_menu_current_bg: '#123456' }, {})
expect(theme.color.selectionBg).toBe('#123456')
})
it('maps completion meta background colors from skins', async () => {
const { fromSkin } = await importThemeWithCleanEnv()
const theme = fromSkin({
completion_menu_meta_bg: '#111111',
completion_menu_meta_current_bg: '#222222'
}, {})
expect(theme.color.completionMetaBg).toBe('#111111')
expect(theme.color.completionMetaCurrentBg).toBe('#222222')
})
it('lets selection_bg override completion highlight colors', async () => {
const { fromSkin } = await importThemeWithCleanEnv()
const theme = fromSkin({ completion_menu_current_bg: '#123456', selection_bg: '#654321' }, {})
expect(theme.color.selectionBg).toBe('#654321')
})
it('overrides branding', async () => {
const { fromSkin } = await importThemeWithCleanEnv()
const { brand } = fromSkin({}, { agent_name: 'TestBot', prompt_symbol: '$' })

View file

@ -182,7 +182,7 @@ export function FloatingOverlays({
return (
<Box
backgroundColor={active ? theme.color.completionCurrentBg : undefined}
backgroundColor={active ? theme.color.completionCurrentBg : theme.color.completionBg}
flexDirection="row"
key={`${start + i}:${item.text}:${item.display}:${item.meta ?? ''}`}
width="100%"
@ -191,7 +191,15 @@ export function FloatingOverlays({
{' '}
{item.display}
</Text>
{item.meta ? <Text color={theme.color.muted}> {item.meta}</Text> : null}
{item.meta ? (
<Text
backgroundColor={active ? theme.color.completionMetaCurrentBg : theme.color.completionMetaBg}
color={theme.color.muted}
>
{' '}
{item.meta}
</Text>
) : null}
</Box>
)
})}

View file

@ -6,6 +6,8 @@ export interface ThemeColors {
muted: string
completionBg: string
completionCurrentBg: string
completionMetaBg: string
completionMetaCurrentBg: string
label: string
ok: string
@ -264,8 +266,10 @@ export const DARK_THEME: Theme = {
// new value sits ~60% luminance — readable without losing the "muted /
// secondary" semantic. Field labels still use `label` (65%) which
// stays brighter so hierarchy holds.
completionBg: '#FFFFFF',
completionCurrentBg: mix('#FFFFFF', '#FFBF00', 0.25),
completionBg: '#1a1a2e',
completionCurrentBg: '#333355',
completionMetaBg: '#1a1a2e',
completionMetaCurrentBg: '#333355',
label: '#DAA520',
ok: '#4caf50',
@ -312,6 +316,8 @@ export const LIGHT_THEME: Theme = {
muted: '#7A5A0F',
completionBg: '#F5F5F5',
completionCurrentBg: mix('#F5F5F5', '#A0651C', 0.25),
completionMetaBg: '#F5F5F5',
completionMetaCurrentBg: mix('#F5F5F5', '#A0651C', 0.25),
label: '#7A5A0F',
ok: '#2E7D32',
@ -517,12 +523,20 @@ export function fromSkin(
): Theme {
const d = DEFAULT_THEME
const c = (k: string) => colors[k]
const hasSkinColors = Object.keys(colors).length > 0
const accent = c('ui_accent') ?? c('banner_accent') ?? d.color.accent
const bannerAccent = c('banner_accent') ?? c('banner_title') ?? d.color.accent
const muted = c('banner_dim') ?? d.color.muted
const completionBg = c('completion_menu_bg') ?? d.color.completionBg
const completionCurrentBg =
c('completion_menu_current_bg') ??
(hasSkinColors ? mix(completionBg, bannerAccent, 0.25) : d.color.completionCurrentBg)
const completionMetaBg = c('completion_menu_meta_bg') ?? completionBg
const completionMetaCurrentBg = c('completion_menu_meta_current_bg') ?? completionCurrentBg
return normalizeThemeForAnsiLightTerminal({
color: {
primary: c('ui_primary') ?? c('banner_title') ?? d.color.primary,
@ -531,7 +545,9 @@ export function fromSkin(
text: c('ui_text') ?? c('banner_text') ?? d.color.text,
muted,
completionBg,
completionCurrentBg: c('completion_menu_current_bg') ?? mix(completionBg, bannerAccent, 0.25),
completionCurrentBg,
completionMetaBg,
completionMetaCurrentBg,
label: c('ui_label') ?? d.color.label,
ok: c('ui_ok') ?? d.color.ok,
@ -548,7 +564,7 @@ export function fromSkin(
statusWarn: c('ui_warn') ?? d.color.statusWarn,
statusBad: d.color.statusBad,
statusCritical: d.color.statusCritical,
selectionBg: c('selection_bg') ?? d.color.selectionBg,
selectionBg: c('selection_bg') ?? c('completion_menu_current_bg') ?? (hasSkinColors ? completionCurrentBg : d.color.selectionBg),
diffAdded: d.color.diffAdded,
diffRemoved: d.color.diffRemoved,

View file

@ -67,6 +67,7 @@ Controls all color values throughout the CLI. Values are hex color strings.
| `session_border` | Session ID dim border color | `#8B8682` |
| `status_bar_bg` | Background color for the TUI status / usage bar | `#1a1a2e` |
| `voice_status_bg` | Background color for the voice-mode status badge | `#1a1a2e` |
| `selection_bg` | Background color for the TUI mouse-selection highlighter. Falls back to `completion_menu_current_bg` when unset. | `#333355` |
| `completion_menu_bg` | Background color for the completion menu list | `#1a1a2e` |
| `completion_menu_current_bg` | Background color for the active completion row | `#333355` |
| `completion_menu_meta_bg` | Background color for the completion meta column | `#1a1a2e` |
@ -139,6 +140,7 @@ colors:
session_border: "#8B8682"
status_bar_bg: "#1a1a2e"
voice_status_bg: "#1a1a2e"
selection_bg: "#333355"
completion_menu_bg: "#1a1a2e"
completion_menu_current_bg: "#333355"
completion_menu_meta_bg: "#1a1a2e"