diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx
index d6813387..cd8295f7 100644
--- a/packages/cli/src/ui/App.tsx
+++ b/packages/cli/src/ui/App.tsx
@@ -39,8 +39,12 @@ export const App = ({ config, cliVersion }: AppProps) => {
const { elapsedTime, currentLoadingPhrase } =
useLoadingIndicator(streamingState);
- const { isThemeDialogOpen, openThemeDialog, handleThemeSelect } =
- useThemeCommand();
+ const {
+ isThemeDialogOpen,
+ openThemeDialog,
+ handleThemeSelect,
+ handleThemeHighlight,
+ } = useThemeCommand();
useStartupWarnings(setStartupWarnings);
useInitializationErrorEffect(initError, history, setHistory);
@@ -134,7 +138,10 @@ export const App = ({ config, cliVersion }: AppProps) => {
)}
{isThemeDialogOpen ? (
-
+
) : (
<>
diff --git a/packages/cli/src/ui/components/ThemeDialog.tsx b/packages/cli/src/ui/components/ThemeDialog.tsx
index b3e4f063..62ede336 100644
--- a/packages/cli/src/ui/components/ThemeDialog.tsx
+++ b/packages/cli/src/ui/components/ThemeDialog.tsx
@@ -9,13 +9,21 @@ import { Box, Text } from 'ink';
import { Colors } from '../colors.js';
import { themeManager } from '../themes/theme-manager.js';
import { RadioButtonSelect } from './shared/RadioButtonSelect.js';
+import { DiffRenderer } from './messages/DiffRenderer.js';
+import { colorizeCode } from '../utils/CodeColorizer.js';
interface ThemeDialogProps {
/** Callback function when a theme is selected */
onSelect: (themeName: string) => void;
+
+ /** Callback function when a theme is highlighted */
+ onHighlight: (themeName: string) => void;
}
-export function ThemeDialog({ onSelect }: ThemeDialogProps): React.JSX.Element {
+export function ThemeDialog({
+ onSelect,
+ onHighlight,
+}: ThemeDialogProps): React.JSX.Element {
const themeItems = themeManager.getAvailableThemes().map((theme) => ({
label: theme.active ? `${theme.name} (Active)` : theme.name,
value: theme.name,
@@ -38,12 +46,40 @@ export function ThemeDialog({ onSelect }: ThemeDialogProps): React.JSX.Element {
items={themeItems}
initialIndex={initialIndex}
onSelect={onSelect}
+ onHighlight={onHighlight}
/>
(Use ↑/↓ arrows and Enter to select)
+
+
+ Preview
+
+ {colorizeCode(
+ `# Source code
+print("Hello, World!")
+`,
+ 'python',
+ )}
+
+
+
+
);
}
diff --git a/packages/cli/src/ui/components/shared/RadioButtonSelect.tsx b/packages/cli/src/ui/components/shared/RadioButtonSelect.tsx
index 7fef19c6..bda56014 100644
--- a/packages/cli/src/ui/components/shared/RadioButtonSelect.tsx
+++ b/packages/cli/src/ui/components/shared/RadioButtonSelect.tsx
@@ -34,6 +34,9 @@ export interface RadioButtonSelectProps {
/** Function called when an item is selected. Receives the `value` of the selected item. */
onSelect: (value: T) => void;
+
+ /** Function called when an item is highlighted. Receives the `value` of the selected item. */
+ onHighlight?: (value: T) => void;
}
/**
@@ -73,10 +76,16 @@ export function RadioButtonSelect({
items,
initialIndex,
onSelect,
+ onHighlight,
}: RadioButtonSelectProps): React.JSX.Element {
const handleSelect = (item: RadioSelectItem) => {
onSelect(item.value);
};
+ const handleHighlight = (item: RadioSelectItem) => {
+ if (onHighlight) {
+ onHighlight(item.value);
+ }
+ };
initialIndex = initialIndex ?? 0;
return (
({
items={items}
initialIndex={initialIndex}
onSelect={handleSelect}
+ onHighlight={handleHighlight}
/>
);
}
diff --git a/packages/cli/src/ui/hooks/useThemeCommand.ts b/packages/cli/src/ui/hooks/useThemeCommand.ts
index 85bd4906..66ec9eda 100644
--- a/packages/cli/src/ui/hooks/useThemeCommand.ts
+++ b/packages/cli/src/ui/hooks/useThemeCommand.ts
@@ -11,6 +11,7 @@ interface UseThemeCommandReturn {
isThemeDialogOpen: boolean;
openThemeDialog: () => void;
handleThemeSelect: (themeName: string) => void;
+ handleThemeHighlight: (themeName: string) => void;
}
export const useThemeCommand = (): UseThemeCommandReturn => {
@@ -21,12 +22,22 @@ export const useThemeCommand = (): UseThemeCommandReturn => {
setIsThemeDialogOpen(true);
}, []);
- const handleThemeSelect = useCallback((themeName: string) => {
+ function applyTheme(themeName: string) {
try {
themeManager.setActiveTheme(themeName);
setForceRender((v) => v + 1); // Trigger potential re-render
} catch (error) {
console.error(`Error setting theme: ${error}`);
+ }
+ }
+
+ const handleThemeHighlight = useCallback((themeName: string) => {
+ applyTheme(themeName);
+ }, []);
+
+ const handleThemeSelect = useCallback((themeName: string) => {
+ try {
+ applyTheme(themeName);
} finally {
setIsThemeDialogOpen(false); // Close the dialog
}
@@ -36,5 +47,6 @@ export const useThemeCommand = (): UseThemeCommandReturn => {
isThemeDialogOpen,
openThemeDialog,
handleThemeSelect,
+ handleThemeHighlight,
};
};