WIP: Add theming system with /theme command

- Consolidated theme system into single src/theme/ directory
- Created Theme class with fg(), bg(), bold(), italic(), underline()
- Added dark and light built-in themes with 36 color tokens
- Support for custom themes in ~/.pi/agent/themes/*.json
- JSON schema for theme validation
- Theme selector UI with /theme command
- Save theme preference to settings
- Uses chalk for text formatting to preserve colors

TODO:
- Replace hardcoded colors throughout TUI components
- Apply markdown theming to Markdown components
- Add theme support to all TUI elements
This commit is contained in:
Mario Zechner 2025-11-20 23:16:05 +01:00
parent 93a60b7969
commit cc88095140
13 changed files with 937 additions and 11 deletions

View file

@ -0,0 +1,51 @@
import { Container, type SelectItem, SelectList } from "@mariozechner/pi-tui";
import { getAvailableThemes, theme } from "../theme/theme.js";
import { DynamicBorder } from "./dynamic-border.js";
/**
* Component that renders a theme selector
*/
export class ThemeSelectorComponent extends Container {
private selectList: SelectList;
constructor(currentTheme: string, onSelect: (themeName: string) => void, onCancel: () => void) {
super();
// Get available themes and create select items
const themes = getAvailableThemes();
const themeItems: SelectItem[] = themes.map((name) => ({
value: name,
label: name,
description: name === currentTheme ? "(current)" : undefined,
}));
// Add top border
this.addChild(new DynamicBorder((text) => theme.fg("border", text)));
// Create selector
this.selectList = new SelectList(themeItems, 10);
// Preselect current theme
const currentIndex = themes.indexOf(currentTheme);
if (currentIndex !== -1) {
this.selectList.setSelectedIndex(currentIndex);
}
this.selectList.onSelect = (item) => {
onSelect(item.value);
};
this.selectList.onCancel = () => {
onCancel();
};
this.addChild(this.selectList);
// Add bottom border
this.addChild(new DynamicBorder((text) => theme.fg("border", text)));
}
getSelectList(): SelectList {
return this.selectList;
}
}