Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions ui-tui/src/__tests__/theme.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest'

import { DARK_THEME, DEFAULT_THEME, fromSkin, LIGHT_THEME } from '../theme.js'
import { DARK_THEME, DEFAULT_THEME, detectLightMode, fromSkin, LIGHT_THEME } from '../theme.js'

describe('DEFAULT_THEME', () => {
it('has brand defaults', () => {
Expand Down Expand Up @@ -30,11 +30,37 @@ describe('LIGHT_THEME', () => {
})

describe('DEFAULT_THEME aliasing', () => {
it('defaults to DARK_THEME when HERMES_TUI_LIGHT is unset', () => {
it('defaults to DARK_THEME when nothing signals light', () => {
expect(DEFAULT_THEME).toBe(DARK_THEME)
})
})

describe('detectLightMode', () => {
it('returns false on empty env', () => {
expect(detectLightMode({})).toBe(false)
})

it('honors HERMES_TUI_LIGHT on/off', () => {
expect(detectLightMode({ HERMES_TUI_LIGHT: '1' })).toBe(true)
expect(detectLightMode({ HERMES_TUI_LIGHT: 'true' })).toBe(true)
expect(detectLightMode({ HERMES_TUI_LIGHT: 'on' })).toBe(true)
expect(detectLightMode({ HERMES_TUI_LIGHT: '0' })).toBe(false)
expect(detectLightMode({ HERMES_TUI_LIGHT: 'off' })).toBe(false)
})

it('sniffs COLORFGBG bg slots 7 and 15 as light (#11300)', () => {
expect(detectLightMode({ COLORFGBG: '0;15' })).toBe(true)
expect(detectLightMode({ COLORFGBG: '0;default;15' })).toBe(true)
expect(detectLightMode({ COLORFGBG: '0;7' })).toBe(true)
expect(detectLightMode({ COLORFGBG: '15;0' })).toBe(false)
expect(detectLightMode({ COLORFGBG: '7;default;0' })).toBe(false)
})

it('lets HERMES_TUI_LIGHT=0 override a light COLORFGBG', () => {
expect(detectLightMode({ COLORFGBG: '0;15', HERMES_TUI_LIGHT: '0' })).toBe(false)
})
})

describe('fromSkin', () => {
it('overrides banner colors', () => {
expect(fromSkin({ banner_title: '#FF0000' }, {}).color.gold).toBe('#FF0000')
Expand Down
8 changes: 4 additions & 4 deletions ui-tui/src/components/branding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,16 @@ export function SessionPanel({ info, sid, t }: SessionPanelProps) {
</Text>

{typeof info.update_behind === 'number' && info.update_behind > 0 && (
<Text bold color="yellow">
<Text bold color={t.color.warn}>
! {info.update_behind} {info.update_behind === 1 ? 'commit' : 'commits'} behind
<Text bold={false} color="yellow" dimColor>
<Text bold={false} color={t.color.warn} dimColor>
{' '}
- run{' '}
</Text>
<Text bold color="yellow">
<Text bold color={t.color.warn}>
{info.update_command || 'hermes update'}
</Text>
<Text bold={false} color="yellow" dimColor>
<Text bold={false} color={t.color.warn} dimColor>
{' '}
to update
</Text>
Expand Down
21 changes: 19 additions & 2 deletions ui-tui/src/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,26 @@ export const LIGHT_THEME: Theme = {
bannerHero: ''
}

const LIGHT_MODE = /^(?:1|true|yes|on)$/i.test((process.env.HERMES_TUI_LIGHT ?? '').trim())
// Pick light vs dark. Explicit `HERMES_TUI_LIGHT` wins; otherwise sniff
// `COLORFGBG` (set by XFCE Terminal, rxvt, Terminal.app, etc.) — last field is the
// background ANSI index; 7/15 are the "white" slots most light themes emit (#11300).
export function detectLightMode(env: NodeJS.ProcessEnv = process.env): boolean {
const explicit = (env.HERMES_TUI_LIGHT ?? '').trim().toLowerCase()

if (/^(?:1|true|yes|on)$/.test(explicit)) {
return true
}

if (/^(?:0|false|no|off)$/.test(explicit)) {
return false
}

const bg = Number((env.COLORFGBG ?? '').trim().split(';').at(-1))

return bg === 7 || bg === 15
}

export const DEFAULT_THEME: Theme = LIGHT_MODE ? LIGHT_THEME : DARK_THEME
export const DEFAULT_THEME: Theme = detectLightMode() ? LIGHT_THEME : DARK_THEME

// ── Skin → Theme ─────────────────────────────────────────────────────

Expand Down
Loading