feat(ui): standardize semantic focus colors and enhance history visibility (#20745)
Co-authored-by: jacob314 <jacob314@gmail.com>
@@ -98,7 +98,7 @@ export function ApiAuthDialog({
|
||||
return (
|
||||
<Box
|
||||
borderStyle="round"
|
||||
borderColor={theme.border.focused}
|
||||
borderColor={theme.ui.focus}
|
||||
flexDirection="column"
|
||||
padding={1}
|
||||
width="100%"
|
||||
|
||||
@@ -193,7 +193,7 @@ export function AuthDialog({
|
||||
return (
|
||||
<Box
|
||||
borderStyle="round"
|
||||
borderColor={theme.border.focused}
|
||||
borderColor={theme.ui.focus}
|
||||
flexDirection="row"
|
||||
padding={1}
|
||||
width="100%"
|
||||
@@ -209,7 +209,7 @@ export function AuthDialog({
|
||||
return (
|
||||
<Box
|
||||
borderStyle="round"
|
||||
borderColor={theme.border.focused}
|
||||
borderColor={theme.ui.focus}
|
||||
flexDirection="row"
|
||||
padding={1}
|
||||
width="100%"
|
||||
|
||||
@@ -427,7 +427,7 @@ export const BackgroundShellDisplay = ({
|
||||
height="100%"
|
||||
width="100%"
|
||||
borderStyle="single"
|
||||
borderColor={isFocused ? theme.border.focused : undefined}
|
||||
borderColor={isFocused ? theme.ui.focus : undefined}
|
||||
>
|
||||
<Box
|
||||
flexDirection="row"
|
||||
@@ -438,7 +438,7 @@ export const BackgroundShellDisplay = ({
|
||||
borderRight={false}
|
||||
borderTop={false}
|
||||
paddingX={1}
|
||||
borderColor={isFocused ? theme.border.focused : undefined}
|
||||
borderColor={isFocused ? theme.ui.focus : undefined}
|
||||
>
|
||||
<Box flexDirection="row">
|
||||
{renderTabs()}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { renderWithProviders } from '../../test-utils/render.js';
|
||||
import { ColorsDisplay } from './ColorsDisplay.js';
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { themeManager } from '../themes/theme-manager.js';
|
||||
import type { Theme, ColorsTheme } from '../themes/theme.js';
|
||||
import type { SemanticColors } from '../themes/semantic-tokens.js';
|
||||
|
||||
describe('ColorsDisplay', () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(themeManager, 'getSemanticColors').mockReturnValue({
|
||||
text: {
|
||||
primary: '#ffffff',
|
||||
secondary: '#cccccc',
|
||||
link: '#0000ff',
|
||||
accent: '#ff00ff',
|
||||
response: '#ffffff',
|
||||
},
|
||||
background: {
|
||||
primary: '#000000',
|
||||
message: '#111111',
|
||||
input: '#222222',
|
||||
focus: '#333333',
|
||||
diff: {
|
||||
added: '#003300',
|
||||
removed: '#330000',
|
||||
},
|
||||
},
|
||||
border: {
|
||||
default: '#555555',
|
||||
},
|
||||
ui: {
|
||||
comment: '#666666',
|
||||
symbol: '#cccccc',
|
||||
active: '#0000ff',
|
||||
dark: '#333333',
|
||||
focus: '#0000ff',
|
||||
gradient: undefined,
|
||||
},
|
||||
status: {
|
||||
error: '#ff0000',
|
||||
success: '#00ff00',
|
||||
warning: '#ffff00',
|
||||
},
|
||||
});
|
||||
|
||||
vi.spyOn(themeManager, 'getActiveTheme').mockReturnValue({
|
||||
name: 'Test Theme',
|
||||
type: 'dark',
|
||||
colors: {} as unknown as ColorsTheme,
|
||||
semanticColors: {
|
||||
text: {
|
||||
primary: '#ffffff',
|
||||
secondary: '#cccccc',
|
||||
link: '#0000ff',
|
||||
accent: '#ff00ff',
|
||||
response: '#ffffff',
|
||||
},
|
||||
background: {
|
||||
primary: '#000000',
|
||||
message: '#111111',
|
||||
input: '#222222',
|
||||
diff: {
|
||||
added: '#003300',
|
||||
removed: '#330000',
|
||||
},
|
||||
},
|
||||
border: {
|
||||
default: '#555555',
|
||||
},
|
||||
ui: {
|
||||
comment: '#666666',
|
||||
symbol: '#cccccc',
|
||||
active: '#0000ff',
|
||||
dark: '#333333',
|
||||
focus: '#0000ff',
|
||||
gradient: undefined,
|
||||
},
|
||||
status: {
|
||||
error: '#ff0000',
|
||||
success: '#00ff00',
|
||||
warning: '#ffff00',
|
||||
},
|
||||
} as unknown as SemanticColors,
|
||||
} as unknown as Theme);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('renders correctly', async () => {
|
||||
const mockTheme = themeManager.getActiveTheme();
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ColorsDisplay activeTheme={mockTheme} />,
|
||||
);
|
||||
await waitUntilReady();
|
||||
const output = lastFrame();
|
||||
|
||||
// Check for title and description
|
||||
expect(output).toContain('How do colors get applied?');
|
||||
expect(output).toContain('Hex:');
|
||||
|
||||
// Check for some color names and values expect(output).toContain('text.primary');
|
||||
expect(output).toContain('#ffffff');
|
||||
expect(output).toContain('background.diff.added');
|
||||
expect(output).toContain('#003300');
|
||||
expect(output).toContain('border.default');
|
||||
expect(output).toContain('#555555');
|
||||
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2026 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import Gradient from 'ink-gradient';
|
||||
import { theme } from '../semantic-colors.js';
|
||||
import type { Theme } from '../themes/theme.js';
|
||||
|
||||
interface StandardColorRow {
|
||||
type: 'standard';
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface GradientColorRow {
|
||||
type: 'gradient';
|
||||
name: string;
|
||||
value: string[];
|
||||
}
|
||||
|
||||
interface BackgroundColorRow {
|
||||
type: 'background';
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
type ColorRow = StandardColorRow | GradientColorRow | BackgroundColorRow;
|
||||
|
||||
const VALUE_COLUMN_WIDTH = 10;
|
||||
|
||||
const COLOR_DESCRIPTIONS: Record<string, string> = {
|
||||
'text.primary': 'Primary text color (uses terminal default if blank)',
|
||||
'text.secondary': 'Secondary/dimmed text color',
|
||||
'text.link': 'Hyperlink and highlighting color',
|
||||
'text.accent': 'Accent color for emphasis',
|
||||
'text.response':
|
||||
'Color for model response text (uses terminal default if blank)',
|
||||
'background.primary': 'Main terminal background color',
|
||||
'background.message': 'Subtle background for message blocks',
|
||||
'background.input': 'Background for the input prompt',
|
||||
'background.focus': 'Background highlight for selected/focused items',
|
||||
'background.diff.added': 'Background for added lines in diffs',
|
||||
'background.diff.removed': 'Background for removed lines in diffs',
|
||||
'border.default': 'Standard border color',
|
||||
'ui.comment': 'Color for code comments and metadata',
|
||||
'ui.symbol': 'Color for technical symbols and UI icons',
|
||||
'ui.active': 'Border color for active or running elements',
|
||||
'ui.dark': 'Deeply dimmed color for subtle UI elements',
|
||||
'ui.focus':
|
||||
'Color for focused elements (e.g. selected menu items, focused borders)',
|
||||
'status.error': 'Color for error messages and critical status',
|
||||
'status.success': 'Color for success messages and positive status',
|
||||
'status.warning': 'Color for warnings and cautionary status',
|
||||
};
|
||||
|
||||
interface ColorsDisplayProps {
|
||||
activeTheme: Theme;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines a contrasting text color (black or white) based on the background color's luminance.
|
||||
*/
|
||||
function getContrastingTextColor(hex: string): string {
|
||||
if (!hex || !hex.startsWith('#') || hex.length < 7) {
|
||||
// Fallback for invalid hex codes or named colors
|
||||
return theme.text.primary;
|
||||
}
|
||||
const r = parseInt(hex.slice(1, 3), 16);
|
||||
const g = parseInt(hex.slice(3, 5), 16);
|
||||
const b = parseInt(hex.slice(5, 7), 16);
|
||||
// Using YIQ formula to determine luminance
|
||||
const yiq = (r * 299 + g * 587 + b * 114) / 1000;
|
||||
return yiq >= 128 ? '#000000' : '#FFFFFF';
|
||||
}
|
||||
|
||||
export const ColorsDisplay: React.FC<ColorsDisplayProps> = ({
|
||||
activeTheme,
|
||||
}) => {
|
||||
const semanticColors = activeTheme.semanticColors;
|
||||
|
||||
const backgroundRows: BackgroundColorRow[] = [];
|
||||
const standardRows: StandardColorRow[] = [];
|
||||
let gradientRow: GradientColorRow | null = null;
|
||||
|
||||
if (semanticColors.ui.gradient && semanticColors.ui.gradient.length > 0) {
|
||||
gradientRow = {
|
||||
type: 'gradient',
|
||||
name: 'ui.gradient',
|
||||
value: semanticColors.ui.gradient,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively flattens the semanticColors object.
|
||||
*/
|
||||
const flattenColors = (obj: object, path: string = '') => {
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (value === undefined || value === null) continue;
|
||||
const newPath = path ? `${path}.${key}` : key;
|
||||
|
||||
if (key === 'gradient' && Array.isArray(value)) {
|
||||
// Gradient handled separately
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof value === 'object' && !Array.isArray(value)) {
|
||||
flattenColors(value, newPath);
|
||||
} else if (typeof value === 'string') {
|
||||
if (newPath.startsWith('background.')) {
|
||||
backgroundRows.push({
|
||||
type: 'background',
|
||||
name: newPath,
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
standardRows.push({
|
||||
type: 'standard',
|
||||
name: newPath,
|
||||
value,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
flattenColors(semanticColors);
|
||||
|
||||
// Final order: Backgrounds first, then Standards, then Gradient
|
||||
const allRows: ColorRow[] = [
|
||||
...backgroundRows,
|
||||
...standardRows,
|
||||
...(gradientRow ? [gradientRow] : []),
|
||||
];
|
||||
|
||||
return (
|
||||
<Box
|
||||
flexDirection="column"
|
||||
paddingX={1}
|
||||
paddingY={0}
|
||||
borderStyle="round"
|
||||
borderColor={theme.border.default}
|
||||
>
|
||||
<Box marginBottom={1} flexDirection="column">
|
||||
<Text bold color={theme.text.accent}>
|
||||
DEVELOPER TOOLS (Not visible to users)
|
||||
</Text>
|
||||
<Box marginTop={1} flexDirection="column">
|
||||
<Text color={theme.text.primary}>
|
||||
<Text bold>How do colors get applied?</Text>
|
||||
</Text>
|
||||
<Box marginLeft={2} flexDirection="column">
|
||||
<Text color={theme.text.primary}>
|
||||
• <Text bold>Hex:</Text> Rendered exactly by modern terminals. Not
|
||||
overridden by app themes.
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
• <Text bold>Blank:</Text> Uses your terminal's default
|
||||
foreground/background.
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
• <Text bold>Compatibility:</Text> On older terminals, hex is
|
||||
approximated to the nearest ANSI color.
|
||||
</Text>
|
||||
<Text color={theme.text.primary}>
|
||||
• <Text bold>ANSI Names:</Text> 'red',
|
||||
'green', etc. are mapped to your terminal app's
|
||||
palette.
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Header */}
|
||||
<Box flexDirection="row" marginBottom={0} paddingX={1}>
|
||||
<Box width={VALUE_COLUMN_WIDTH}>
|
||||
<Text bold color={theme.text.link} dimColor>
|
||||
Value
|
||||
</Text>
|
||||
</Box>
|
||||
<Box flexGrow={1}>
|
||||
<Text bold color={theme.text.link} dimColor>
|
||||
Name
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* All Rows */}
|
||||
<Box flexDirection="column">
|
||||
{allRows.map((row) => {
|
||||
if (row.type === 'standard') return renderStandardRow(row);
|
||||
if (row.type === 'gradient') return renderGradientRow(row);
|
||||
if (row.type === 'background') return renderBackgroundRow(row);
|
||||
return null;
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
function renderStandardRow({ name, value }: StandardColorRow) {
|
||||
const isHex = value.startsWith('#');
|
||||
const displayColor = isHex ? value : theme.text.primary;
|
||||
const description = COLOR_DESCRIPTIONS[name] || '';
|
||||
|
||||
return (
|
||||
<Box key={name} flexDirection="row" paddingX={1}>
|
||||
<Box width={VALUE_COLUMN_WIDTH}>
|
||||
<Text color={displayColor}>{value || '(blank)'}</Text>
|
||||
</Box>
|
||||
<Box flexGrow={1} flexDirection="row">
|
||||
<Box width="30%">
|
||||
<Text color={displayColor}>{name}</Text>
|
||||
</Box>
|
||||
<Box flexGrow={1} paddingLeft={1}>
|
||||
<Text color={theme.text.secondary}>{description}</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function renderGradientRow({ name, value }: GradientColorRow) {
|
||||
const description = COLOR_DESCRIPTIONS[name] || '';
|
||||
|
||||
return (
|
||||
<Box key={name} flexDirection="row" paddingX={1}>
|
||||
<Box width={VALUE_COLUMN_WIDTH} flexDirection="column">
|
||||
{value.map((c, i) => (
|
||||
<Text key={i} color={c}>
|
||||
{c}
|
||||
</Text>
|
||||
))}
|
||||
</Box>
|
||||
<Box flexGrow={1} flexDirection="row">
|
||||
<Box width="30%">
|
||||
<Gradient colors={value}>
|
||||
<Text>{name}</Text>
|
||||
</Gradient>
|
||||
</Box>
|
||||
<Box flexGrow={1} paddingLeft={1}>
|
||||
<Text color={theme.text.secondary}>{description}</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function renderBackgroundRow({ name, value }: BackgroundColorRow) {
|
||||
const description = COLOR_DESCRIPTIONS[name] || '';
|
||||
|
||||
return (
|
||||
<Box key={name} flexDirection="row" paddingX={1}>
|
||||
<Box
|
||||
width={VALUE_COLUMN_WIDTH}
|
||||
backgroundColor={value}
|
||||
justifyContent="center"
|
||||
paddingX={1}
|
||||
>
|
||||
<Text color={getContrastingTextColor(value)} bold wrap="truncate">
|
||||
{value || 'default'}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box flexGrow={1} flexDirection="row" paddingLeft={1}>
|
||||
<Box width="30%">
|
||||
<Text color={theme.text.primary}>{name}</Text>
|
||||
</Box>
|
||||
<Box flexGrow={1} paddingLeft={1}>
|
||||
<Text color={theme.text.secondary}>{description}</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -22,8 +22,13 @@ vi.mock('../semantic-colors.js', async (importOriginal) => {
|
||||
...original,
|
||||
theme: {
|
||||
...original.theme,
|
||||
background: {
|
||||
...original.theme.background,
|
||||
focus: '#004000',
|
||||
},
|
||||
ui: {
|
||||
...original.theme.ui,
|
||||
focus: '#00ff00',
|
||||
gradient: [], // Empty array to potentially trigger the crash
|
||||
},
|
||||
},
|
||||
|
||||
@@ -98,16 +98,18 @@ describe('<Header />', () => {
|
||||
primary: '',
|
||||
message: '',
|
||||
input: '',
|
||||
focus: '',
|
||||
diff: { added: '', removed: '' },
|
||||
},
|
||||
border: {
|
||||
default: '',
|
||||
focused: '',
|
||||
},
|
||||
ui: {
|
||||
comment: '',
|
||||
symbol: '',
|
||||
active: '',
|
||||
dark: '',
|
||||
focus: '',
|
||||
gradient: undefined,
|
||||
},
|
||||
status: {
|
||||
|
||||
@@ -1427,7 +1427,7 @@ export const InputPrompt: React.FC<InputPromptProps> = ({
|
||||
|
||||
const borderColor =
|
||||
isShellFocused && !isEmbeddedShellFocused
|
||||
? (statusColor ?? theme.border.focused)
|
||||
? (statusColor ?? theme.ui.focus)
|
||||
: theme.border.default;
|
||||
|
||||
return (
|
||||
|
||||
@@ -79,10 +79,18 @@ export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({
|
||||
/>
|
||||
</Box>
|
||||
{primaryText && (
|
||||
<Text color={theme.text.primary} italic wrap="truncate-end">
|
||||
{thinkingIndicator}
|
||||
{primaryText}
|
||||
</Text>
|
||||
<Box flexShrink={1}>
|
||||
<Text color={theme.text.primary} italic wrap="truncate-end">
|
||||
{thinkingIndicator}
|
||||
{primaryText}
|
||||
</Text>
|
||||
{primaryText === INTERACTIVE_SHELL_WAITING_PHRASE && (
|
||||
<Text color={theme.ui.active} italic>
|
||||
{' '}
|
||||
(press tab to focus)
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
{cancelAndTimerContent && (
|
||||
<>
|
||||
@@ -113,10 +121,18 @@ export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({
|
||||
/>
|
||||
</Box>
|
||||
{primaryText && (
|
||||
<Text color={theme.text.primary} italic wrap="truncate-end">
|
||||
{thinkingIndicator}
|
||||
{primaryText}
|
||||
</Text>
|
||||
<Box flexShrink={1}>
|
||||
<Text color={theme.text.primary} italic wrap="truncate-end">
|
||||
{thinkingIndicator}
|
||||
{primaryText}
|
||||
</Text>
|
||||
{primaryText === INTERACTIVE_SHELL_WAITING_PHRASE && (
|
||||
<Text color={theme.ui.active} italic>
|
||||
{' '}
|
||||
(press tab to focus)
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
{!isNarrow && cancelAndTimerContent && (
|
||||
<>
|
||||
|
||||
@@ -53,7 +53,7 @@ export const LogoutConfirmationDialog: React.FC<
|
||||
<Box
|
||||
flexDirection="column"
|
||||
borderStyle="round"
|
||||
borderColor={theme.border.focused}
|
||||
borderColor={theme.ui.focus}
|
||||
padding={1}
|
||||
flexGrow={1}
|
||||
marginLeft={1}
|
||||
|
||||
@@ -203,7 +203,7 @@ describe('getToolGroupBorderAppearance', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('returns symbol border for executing shell commands', () => {
|
||||
it('returns active border for executing shell commands', () => {
|
||||
const item = {
|
||||
type: 'tool_group' as const,
|
||||
tools: [
|
||||
@@ -219,7 +219,37 @@ describe('getToolGroupBorderAppearance', () => {
|
||||
],
|
||||
id: 1,
|
||||
};
|
||||
// While executing shell commands, it's dim false, border symbol
|
||||
// While executing shell commands, it's dim false, border active
|
||||
const result = getToolGroupBorderAppearance(
|
||||
item,
|
||||
activeShellPtyId,
|
||||
false,
|
||||
[],
|
||||
mockBackgroundShells,
|
||||
);
|
||||
expect(result).toEqual({
|
||||
borderColor: theme.ui.active,
|
||||
borderDimColor: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns focus border for focused executing shell commands', () => {
|
||||
const item = {
|
||||
type: 'tool_group' as const,
|
||||
tools: [
|
||||
{
|
||||
callId: '1',
|
||||
name: SHELL_COMMAND_NAME,
|
||||
description: '',
|
||||
status: CoreToolCallStatus.Executing,
|
||||
ptyId: activeShellPtyId,
|
||||
resultDisplay: undefined,
|
||||
confirmationDetails: undefined,
|
||||
} as IndividualToolCallDisplay,
|
||||
],
|
||||
id: 1,
|
||||
};
|
||||
// When focused, it's dim false, border focus
|
||||
const result = getToolGroupBorderAppearance(
|
||||
item,
|
||||
activeShellPtyId,
|
||||
@@ -228,12 +258,12 @@ describe('getToolGroupBorderAppearance', () => {
|
||||
mockBackgroundShells,
|
||||
);
|
||||
expect(result).toEqual({
|
||||
borderColor: theme.ui.symbol,
|
||||
borderColor: theme.ui.focus,
|
||||
borderDimColor: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns symbol border and dims color for background executing shell command when another shell is active', () => {
|
||||
it('returns active border and dims color for background executing shell command when another shell is active', () => {
|
||||
const item = {
|
||||
type: 'tool_group' as const,
|
||||
tools: [
|
||||
@@ -257,7 +287,7 @@ describe('getToolGroupBorderAppearance', () => {
|
||||
mockBackgroundShells,
|
||||
);
|
||||
expect(result).toEqual({
|
||||
borderColor: theme.ui.symbol,
|
||||
borderColor: theme.ui.active,
|
||||
borderDimColor: true,
|
||||
});
|
||||
});
|
||||
@@ -275,7 +305,7 @@ describe('getToolGroupBorderAppearance', () => {
|
||||
);
|
||||
// Since there are no tools to inspect, it falls back to empty pending, but isCurrentlyInShellTurn=true
|
||||
// so it counts as pending shell.
|
||||
expect(result.borderColor).toEqual(theme.ui.symbol);
|
||||
expect(result.borderColor).toEqual(theme.ui.focus);
|
||||
// It shouldn't be dim because there are no tools to say it isEmbeddedShellFocused = false
|
||||
expect(result.borderDimColor).toBe(false);
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import type React from 'react';
|
||||
import { useState, useCallback, useMemo, useEffect, useRef } from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import { theme } from '../semantic-colors.js';
|
||||
import { Colors } from '../colors.js';
|
||||
import { useTerminalSize } from '../hooks/useTerminalSize.js';
|
||||
import { useKeypress } from '../hooks/useKeypress.js';
|
||||
@@ -436,7 +437,7 @@ const SessionItem = ({
|
||||
if (isDisabled) {
|
||||
return Colors.Gray;
|
||||
}
|
||||
return isActive ? Colors.AccentPurple : c;
|
||||
return isActive ? theme.ui.focus : c;
|
||||
};
|
||||
|
||||
const prefix = isActive ? '❯ ' : ' ';
|
||||
@@ -483,7 +484,10 @@ const SessionItem = ({
|
||||
));
|
||||
|
||||
return (
|
||||
<Box flexDirection="row">
|
||||
<Box
|
||||
flexDirection="row"
|
||||
backgroundColor={isActive ? theme.background.focus : undefined}
|
||||
>
|
||||
<Text color={textColor()} dimColor={isDisabled}>
|
||||
{prefix}
|
||||
</Text>
|
||||
|
||||
@@ -84,7 +84,7 @@ export function SuggestionsDisplay({
|
||||
const originalIndex = startIndex + index;
|
||||
const isActive = originalIndex === activeIndex;
|
||||
const isExpanded = originalIndex === expandedIndex;
|
||||
const textColor = isActive ? theme.text.accent : theme.text.secondary;
|
||||
const textColor = isActive ? theme.ui.focus : theme.text.secondary;
|
||||
const isLong = suggestion.value.length >= MAX_WIDTH;
|
||||
const labelElement = (
|
||||
<ExpandableText
|
||||
@@ -97,7 +97,11 @@ export function SuggestionsDisplay({
|
||||
);
|
||||
|
||||
return (
|
||||
<Box key={`${suggestion.value}-${originalIndex}`} flexDirection="row">
|
||||
<Box
|
||||
key={`${suggestion.value}-${originalIndex}`}
|
||||
flexDirection="row"
|
||||
backgroundColor={isActive ? theme.background.focus : undefined}
|
||||
>
|
||||
<Box
|
||||
{...(mode === 'slash'
|
||||
? { width: commandColumnWidth, flexShrink: 0 as const }
|
||||
|
||||
@@ -8,6 +8,22 @@ import { renderWithProviders } from '../../test-utils/render.js';
|
||||
import { waitFor } from '../../test-utils/async.js';
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { ThemeDialog } from './ThemeDialog.js';
|
||||
|
||||
const { mockIsDevelopment } = vi.hoisted(() => ({
|
||||
mockIsDevelopment: { value: false },
|
||||
}));
|
||||
|
||||
vi.mock('../../utils/installationInfo.js', async (importOriginal) => {
|
||||
const actual =
|
||||
await importOriginal<typeof import('../../utils/installationInfo.js')>();
|
||||
return {
|
||||
...actual,
|
||||
get isDevelopment() {
|
||||
return mockIsDevelopment.value;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
import { createMockSettings } from '../../test-utils/settings.js';
|
||||
import { DEFAULT_THEME, themeManager } from '../themes/theme-manager.js';
|
||||
import { act } from 'react';
|
||||
@@ -30,17 +46,21 @@ describe('ThemeDialog Snapshots', () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should render correctly in theme selection mode', async () => {
|
||||
const settings = createMockSettings();
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ThemeDialog {...baseProps} settings={settings} />,
|
||||
{ settings },
|
||||
);
|
||||
await waitUntilReady();
|
||||
it.each([true, false])(
|
||||
'should render correctly in theme selection mode (isDevelopment: %s)',
|
||||
async (isDev) => {
|
||||
mockIsDevelopment.value = isDev;
|
||||
const settings = createMockSettings();
|
||||
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
|
||||
<ThemeDialog {...baseProps} settings={settings} />,
|
||||
{ settings },
|
||||
);
|
||||
await waitUntilReady();
|
||||
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
},
|
||||
);
|
||||
|
||||
it('should render correctly in scope selector mode', async () => {
|
||||
const settings = createMockSettings();
|
||||
|
||||
@@ -23,6 +23,8 @@ import { useKeypress } from '../hooks/useKeypress.js';
|
||||
import { useAlternateBuffer } from '../hooks/useAlternateBuffer.js';
|
||||
import { ScopeSelector } from './shared/ScopeSelector.js';
|
||||
import { useUIState } from '../contexts/UIStateContext.js';
|
||||
import { ColorsDisplay } from './ColorsDisplay.js';
|
||||
import { isDevelopment } from '../../utils/installationInfo.js';
|
||||
|
||||
interface ThemeDialogProps {
|
||||
/** Callback function when a theme is selected */
|
||||
@@ -245,6 +247,11 @@ export function ThemeDialog({
|
||||
// The code block is slightly longer than the diff, so give it more space.
|
||||
const codeBlockHeight = Math.ceil(availableHeightForPanes * 0.6);
|
||||
const diffHeight = Math.floor(availableHeightForPanes * 0.4);
|
||||
|
||||
const previewTheme =
|
||||
themeManager.getTheme(highlightedThemeName || DEFAULT_THEME.name) ||
|
||||
DEFAULT_THEME;
|
||||
|
||||
return (
|
||||
<Box
|
||||
borderStyle="round"
|
||||
@@ -328,53 +335,48 @@ export function ThemeDialog({
|
||||
<Text bold color={theme.text.primary}>
|
||||
Preview
|
||||
</Text>
|
||||
{/* Get the Theme object for the highlighted theme, fall back to default if not found */}
|
||||
{(() => {
|
||||
const previewTheme =
|
||||
themeManager.getTheme(
|
||||
highlightedThemeName || DEFAULT_THEME.name,
|
||||
) || DEFAULT_THEME;
|
||||
|
||||
return (
|
||||
<Box
|
||||
borderStyle="single"
|
||||
borderColor={theme.border.default}
|
||||
paddingTop={includePadding ? 1 : 0}
|
||||
paddingBottom={includePadding ? 1 : 0}
|
||||
paddingLeft={1}
|
||||
paddingRight={1}
|
||||
flexDirection="column"
|
||||
>
|
||||
{colorizeCode({
|
||||
code: `# function
|
||||
<Box
|
||||
borderStyle="single"
|
||||
borderColor={theme.border.default}
|
||||
paddingTop={includePadding ? 1 : 0}
|
||||
paddingBottom={includePadding ? 1 : 0}
|
||||
paddingLeft={1}
|
||||
paddingRight={1}
|
||||
flexDirection="column"
|
||||
>
|
||||
{colorizeCode({
|
||||
code: `# function
|
||||
def fibonacci(n):
|
||||
a, b = 0, 1
|
||||
for _ in range(n):
|
||||
a, b = b, a + b
|
||||
return a`,
|
||||
language: 'python',
|
||||
availableHeight:
|
||||
isAlternateBuffer === false ? codeBlockHeight : undefined,
|
||||
maxWidth: colorizeCodeWidth,
|
||||
settings,
|
||||
})}
|
||||
<Box marginTop={1} />
|
||||
<DiffRenderer
|
||||
diffContent={`--- a/util.py
|
||||
language: 'python',
|
||||
availableHeight:
|
||||
isAlternateBuffer === false ? codeBlockHeight : undefined,
|
||||
maxWidth: colorizeCodeWidth,
|
||||
settings,
|
||||
})}
|
||||
<Box marginTop={1} />
|
||||
<DiffRenderer
|
||||
diffContent={`--- a/util.py
|
||||
+++ b/util.py
|
||||
@@ -1,2 +1,2 @@
|
||||
- print("Hello, " + name)
|
||||
+ print(f"Hello, {name}!")
|
||||
`}
|
||||
availableTerminalHeight={
|
||||
isAlternateBuffer === false ? diffHeight : undefined
|
||||
}
|
||||
terminalWidth={colorizeCodeWidth}
|
||||
theme={previewTheme}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
})()}
|
||||
availableTerminalHeight={
|
||||
isAlternateBuffer === false ? diffHeight : undefined
|
||||
}
|
||||
terminalWidth={colorizeCodeWidth}
|
||||
theme={previewTheme}
|
||||
/>
|
||||
</Box>
|
||||
{isDevelopment && (
|
||||
<Box marginTop={1}>
|
||||
<ColorsDisplay activeTheme={previewTheme} />
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
) : (
|
||||
|
||||
@@ -13,6 +13,10 @@ vi.mock('../semantic-colors.js', () => ({
|
||||
theme: {
|
||||
ui: {
|
||||
gradient: ['red', 'blue'],
|
||||
focus: 'green',
|
||||
},
|
||||
background: {
|
||||
focus: 'darkgreen',
|
||||
},
|
||||
text: {
|
||||
accent: 'cyan',
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`AskUserDialog > Choice question placeholder > uses default placeholder when not provided 1`] = `
|
||||
"Select your preferred language:
|
||||
|
||||
1. TypeScript
|
||||
2. JavaScript
|
||||
● 3. Enter a custom value
|
||||
|
||||
Enter to submit · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Choice question placeholder > uses default placeholder when not provided 2`] = `
|
||||
"Select your preferred language:
|
||||
|
||||
1. TypeScript
|
||||
@@ -12,6 +23,17 @@ Enter to submit · Esc to cancel
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 1`] = `
|
||||
"Select your preferred language:
|
||||
|
||||
1. TypeScript
|
||||
2. JavaScript
|
||||
● 3. Type another language...
|
||||
|
||||
Enter to submit · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 2`] = `
|
||||
"Select your preferred language:
|
||||
|
||||
1. TypeScript
|
||||
@@ -25,6 +47,20 @@ Enter to submit · Esc to cancel
|
||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 1`] = `
|
||||
"Choose an option
|
||||
|
||||
▲
|
||||
● 1. Option 1
|
||||
Description 1
|
||||
2. Option 2
|
||||
Description 2
|
||||
▼
|
||||
|
||||
Enter to select · ↑/↓ to navigate · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 2`] = `
|
||||
"Choose an option
|
||||
|
||||
▲
|
||||
● 1. Option 1
|
||||
Description 1
|
||||
@@ -39,6 +75,45 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
|
||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 1`] = `
|
||||
"Choose an option
|
||||
|
||||
● 1. Option 1
|
||||
Description 1
|
||||
2. Option 2
|
||||
Description 2
|
||||
3. Option 3
|
||||
Description 3
|
||||
4. Option 4
|
||||
Description 4
|
||||
5. Option 5
|
||||
Description 5
|
||||
6. Option 6
|
||||
Description 6
|
||||
7. Option 7
|
||||
Description 7
|
||||
8. Option 8
|
||||
Description 8
|
||||
9. Option 9
|
||||
Description 9
|
||||
10. Option 10
|
||||
Description 10
|
||||
11. Option 11
|
||||
Description 11
|
||||
12. Option 12
|
||||
Description 12
|
||||
13. Option 13
|
||||
Description 13
|
||||
14. Option 14
|
||||
Description 14
|
||||
15. Option 15
|
||||
Description 15
|
||||
16. Enter a custom value
|
||||
|
||||
Enter to select · ↑/↓ to navigate · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 2`] = `
|
||||
"Choose an option
|
||||
|
||||
● 1. Option 1
|
||||
Description 1
|
||||
2. Option 2
|
||||
@@ -122,8 +197,8 @@ Enter to submit · Tab/Shift+Tab to edit answers · Esc to cancel
|
||||
exports[`AskUserDialog > hides progress header for single question 1`] = `
|
||||
"Which authentication method should we use?
|
||||
|
||||
● 1. OAuth 2.0
|
||||
Industry standard, supports SSO
|
||||
● 1. OAuth 2.0
|
||||
Industry standard, supports SSO
|
||||
2. JWT tokens
|
||||
Stateless, good for APIs
|
||||
3. Enter a custom value
|
||||
@@ -135,8 +210,8 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
|
||||
exports[`AskUserDialog > renders question and options 1`] = `
|
||||
"Which authentication method should we use?
|
||||
|
||||
● 1. OAuth 2.0
|
||||
Industry standard, supports SSO
|
||||
● 1. OAuth 2.0
|
||||
Industry standard, supports SSO
|
||||
2. JWT tokens
|
||||
Stateless, good for APIs
|
||||
3. Enter a custom value
|
||||
@@ -150,8 +225,8 @@ exports[`AskUserDialog > shows Review tab in progress header for multiple questi
|
||||
|
||||
Which framework?
|
||||
|
||||
● 1. React
|
||||
Component library
|
||||
● 1. React
|
||||
Component library
|
||||
2. Vue
|
||||
Progressive framework
|
||||
3. Enter a custom value
|
||||
@@ -163,8 +238,8 @@ Enter to select · ←/→ to switch questions · Esc to cancel
|
||||
exports[`AskUserDialog > shows keyboard hints 1`] = `
|
||||
"Which authentication method should we use?
|
||||
|
||||
● 1. OAuth 2.0
|
||||
Industry standard, supports SSO
|
||||
● 1. OAuth 2.0
|
||||
Industry standard, supports SSO
|
||||
2. JWT tokens
|
||||
Stateless, good for APIs
|
||||
3. Enter a custom value
|
||||
@@ -178,8 +253,8 @@ exports[`AskUserDialog > shows progress header for multiple questions 1`] = `
|
||||
|
||||
Which database should we use?
|
||||
|
||||
● 1. PostgreSQL
|
||||
Relational database
|
||||
● 1. PostgreSQL
|
||||
Relational database
|
||||
2. MongoDB
|
||||
Document database
|
||||
3. Enter a custom value
|
||||
|
||||
@@ -19,14 +19,41 @@ Files to Modify
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
● 2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
3. Type your feedback...
|
||||
|
||||
Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: false > bubbles up Ctrl+C when feedback is empty while editing 2`] = `
|
||||
"Overview
|
||||
|
||||
Add user authentication to the CLI application.
|
||||
|
||||
Implementation Steps
|
||||
|
||||
1. Create src/auth/AuthService.ts with login/logout methods
|
||||
2. Add session storage in src/storage/SessionStore.ts
|
||||
3. Update src/commands/index.ts to check auth status
|
||||
4. Add tests in src/auth/__tests__/
|
||||
|
||||
Files to Modify
|
||||
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 3. Type your feedback...
|
||||
|
||||
Enter to submit · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: false > calls onFeedback when feedback is typed and submitted 1`] = `
|
||||
"Overview
|
||||
|
||||
@@ -44,8 +71,8 @@ Files to Modify
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
3. Type your feedback...
|
||||
@@ -54,6 +81,33 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: false > calls onFeedback when feedback is typed and submitted 2`] = `
|
||||
"Overview
|
||||
|
||||
Add user authentication to the CLI application.
|
||||
|
||||
Implementation Steps
|
||||
|
||||
1. Create src/auth/AuthService.ts with login/logout methods
|
||||
2. Add session storage in src/storage/SessionStore.ts
|
||||
3. Update src/commands/index.ts to check auth status
|
||||
4. Add tests in src/auth/__tests__/
|
||||
|
||||
Files to Modify
|
||||
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 3. Add tests
|
||||
|
||||
Enter to submit · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: false > displays error state when file read fails 1`] = `
|
||||
" Error reading plan: File not found
|
||||
"
|
||||
@@ -76,8 +130,8 @@ Implementation Steps
|
||||
8. Add multi-factor authentication in src/auth/MFAService.ts
|
||||
... last 22 lines hidden (Ctrl+O to show) ...
|
||||
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
3. Type your feedback...
|
||||
@@ -103,8 +157,8 @@ Files to Modify
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
3. Type your feedback...
|
||||
@@ -132,14 +186,41 @@ Files to Modify
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
● 2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
3. Type your feedback...
|
||||
|
||||
Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: true > bubbles up Ctrl+C when feedback is empty while editing 2`] = `
|
||||
"Overview
|
||||
|
||||
Add user authentication to the CLI application.
|
||||
|
||||
Implementation Steps
|
||||
|
||||
1. Create src/auth/AuthService.ts with login/logout methods
|
||||
2. Add session storage in src/storage/SessionStore.ts
|
||||
3. Update src/commands/index.ts to check auth status
|
||||
4. Add tests in src/auth/__tests__/
|
||||
|
||||
Files to Modify
|
||||
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 3. Type your feedback...
|
||||
|
||||
Enter to submit · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: true > calls onFeedback when feedback is typed and submitted 1`] = `
|
||||
"Overview
|
||||
|
||||
@@ -157,8 +238,8 @@ Files to Modify
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
3. Type your feedback...
|
||||
@@ -167,6 +248,33 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: true > calls onFeedback when feedback is typed and submitted 2`] = `
|
||||
"Overview
|
||||
|
||||
Add user authentication to the CLI application.
|
||||
|
||||
Implementation Steps
|
||||
|
||||
1. Create src/auth/AuthService.ts with login/logout methods
|
||||
2. Add session storage in src/storage/SessionStore.ts
|
||||
3. Update src/commands/index.ts to check auth status
|
||||
4. Add tests in src/auth/__tests__/
|
||||
|
||||
Files to Modify
|
||||
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
● 3. Add tests
|
||||
|
||||
Enter to submit · Ctrl+X to edit plan · Esc to cancel
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ExitPlanModeDialog > useAlternateBuffer: true > displays error state when file read fails 1`] = `
|
||||
" Error reading plan: File not found
|
||||
"
|
||||
@@ -210,8 +318,8 @@ Testing Strategy
|
||||
- Security penetration testing
|
||||
- Load testing for session management
|
||||
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
3. Type your feedback...
|
||||
@@ -237,8 +345,8 @@ Files to Modify
|
||||
- src/index.ts - Add auth middleware
|
||||
- src/config.ts - Add auth configuration options
|
||||
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
● 1. Yes, automatically accept edits
|
||||
Approves plan and allows tools to run automatically
|
||||
2. Yes, manually accept edits
|
||||
Approves plan but requires confirmation for each tool
|
||||
3. Type your feedback...
|
||||
|
||||
@@ -12,8 +12,8 @@ exports[`InputPrompt > command search (Ctrl+R when not in shell) > expands and c
|
||||
(r:) Type your message or @path/to/file
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll →
|
||||
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
|
||||
...
|
||||
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
|
||||
...
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -22,8 +22,8 @@ exports[`InputPrompt > command search (Ctrl+R when not in shell) > expands and c
|
||||
(r:) Type your message or @path/to/file
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll ←
|
||||
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
|
||||
llllllllllllllllllllllllllllllllllllllllllllllllll
|
||||
lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
|
||||
llllllllllllllllllllllllllllllllllllllllllllllllll
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -31,7 +31,7 @@ exports[`InputPrompt > command search (Ctrl+R when not in shell) > renders match
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
(r:) commit
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
git commit -m "feat: add search" in src/app
|
||||
git commit -m "feat: add search" in src/app
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -39,7 +39,7 @@ exports[`InputPrompt > command search (Ctrl+R when not in shell) > renders match
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
(r:) commit
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
git commit -m "feat: add search" in src/app
|
||||
git commit -m "feat: add search" in src/app
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -78,6 +78,27 @@ exports[`InputPrompt > mouse interaction > should toggle paste expansion on doub
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > mouse interaction > should toggle paste expansion on double-click 4`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> [Pasted Text: 10 lines]
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > mouse interaction > should toggle paste expansion on double-click 5`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> [Pasted Text: 10 lines]
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > mouse interaction > should toggle paste expansion on double-click 6`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> [Pasted Text: 10 lines]
|
||||
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`InputPrompt > snapshots > should not show inverted cursor when shell is focused 1`] = `
|
||||
"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
||||
> Type your message or @path/to/file
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`<LoadingIndicator /> > should truncate long primary text instead of wrapping 1`] = `
|
||||
"MockRespondin This is an extremely long loading phrase that shoul… (esc to
|
||||
"MockRespondin This is an extremely long loading phrase that shoul…(esc to
|
||||
gSpinner cancel, 5s)
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -4,7 +4,7 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'ASB mode - Focuse
|
||||
"ScrollableList
|
||||
AppHeader(full)
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command Running a long command... │
|
||||
│ ⊶ Shell Command Running a long command... │
|
||||
│ │
|
||||
│ Line 10 │
|
||||
│ Line 11 │
|
||||
@@ -26,7 +26,7 @@ exports[`MainContent > MainContent Tool Output Height Logic > 'ASB mode - Unfocu
|
||||
"ScrollableList
|
||||
AppHeader(full)
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command Running a long command... │
|
||||
│ ⊶ Shell Command Running a long command... │
|
||||
│ │
|
||||
│ Line 10 │
|
||||
│ Line 11 │
|
||||
@@ -47,7 +47,7 @@ ShowMoreLines
|
||||
exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Constrained height' 1`] = `
|
||||
"AppHeader(full)
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command Running a long command... │
|
||||
│ ⊶ Shell Command Running a long command... │
|
||||
│ │
|
||||
│ ... first 11 lines hidden (Ctrl+O to show) ... │
|
||||
│ Line 12 │
|
||||
@@ -67,7 +67,7 @@ ShowMoreLines
|
||||
exports[`MainContent > MainContent Tool Output Height Logic > 'Normal mode - Unconstrained height' 1`] = `
|
||||
"AppHeader(full)
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command Running a long command... │
|
||||
│ ⊶ Shell Command Running a long command... │
|
||||
│ │
|
||||
│ Line 1 │
|
||||
│ Line 2 │
|
||||
|
||||
@@ -6,7 +6,7 @@ exports[`SessionBrowser component > enters search mode, filters sessions, and re
|
||||
Search: query (Esc to cancel)
|
||||
|
||||
Index │ Msgs │ Age │ Match
|
||||
❯ #1 │ 1 │ 10mo │ You: Query is here a… (+1 more)
|
||||
❯ #1 │ 1 │ 10mo │ You: Query is here a… (+1 more)
|
||||
▼
|
||||
"
|
||||
`;
|
||||
@@ -17,7 +17,7 @@ exports[`SessionBrowser component > renders a list of sessions and marks current
|
||||
Sort: s Reverse: r First/Last: g/G
|
||||
|
||||
Index │ Msgs │ Age │ Name
|
||||
❯ #1 │ 5 │ 10mo │ Second conversation about dogs (current)
|
||||
❯ #1 │ 5 │ 10mo │ Second conversation about dogs (current)
|
||||
#2 │ 2 │ 10mo │ First conversation about cats
|
||||
▼
|
||||
"
|
||||
|
||||
@@ -13,17 +13,17 @@
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -31,12 +31,20 @@
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -112,8 +120,12 @@
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -13,17 +13,17 @@
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -31,12 +31,20 @@
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">true*</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -112,8 +120,12 @@
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -13,17 +13,17 @@
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -31,12 +31,20 @@
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="702" height="17" fill="#394545" />
|
||||
<rect x="819" y="153" width="54" height="17" fill="#394545" />
|
||||
<text x="819" y="155" fill="#a6e3a1" textLength="54" lengthAdjust="spacingAndGlyphs">false*</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -110,8 +118,12 @@
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -13,17 +13,17 @@
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -31,12 +31,20 @@
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -112,8 +120,12 @@
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -13,17 +13,17 @@
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -31,12 +31,20 @@
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -112,8 +120,12 @@
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -109,9 +109,15 @@
|
||||
<text x="27" y="597" fill="#ffffff" textLength="90" lengthAdjust="spacingAndGlyphs" font-weight="bold">> Apply To</text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="18" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="18" lengthAdjust="spacingAndGlyphs">1.</text>
|
||||
<rect x="63" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="72" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="72" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="189" y="612" width="684" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> 2. Workspace Settings </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
@@ -13,17 +13,17 @@
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -31,12 +31,20 @@
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="702" height="17" fill="#394545" />
|
||||
<rect x="819" y="153" width="54" height="17" fill="#394545" />
|
||||
<text x="819" y="155" fill="#a6e3a1" textLength="54" lengthAdjust="spacingAndGlyphs">false*</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -111,8 +119,12 @@
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -13,17 +13,17 @@
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -31,12 +31,20 @@
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">false</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -112,8 +120,12 @@
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -13,17 +13,17 @@
|
||||
<text x="0" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="53" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="70" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="18" y="70" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="891" y="70" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="36" y="85" width="9" height="17" fill="#ffffff" />
|
||||
<text x="36" y="87" fill="#000000" textLength="9" lengthAdjust="spacingAndGlyphs">S</text>
|
||||
<text x="45" y="87" fill="#6c7086" textLength="135" lengthAdjust="spacingAndGlyphs">earch to filter</text>
|
||||
<text x="873" y="87" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="873" y="87" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="87" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="104" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="18" y="104" fill="#a6e3a1" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="891" y="104" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="121" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -31,12 +31,20 @@
|
||||
<text x="27" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">▲</text>
|
||||
<text x="891" y="138" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="153" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="155" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="153" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="153" width="72" height="17" fill="#394545" />
|
||||
<text x="45" y="155" fill="#a6e3a1" textLength="72" lengthAdjust="spacingAndGlyphs">Vim Mode</text>
|
||||
<rect x="117" y="153" width="711" height="17" fill="#394545" />
|
||||
<rect x="828" y="153" width="45" height="17" fill="#394545" />
|
||||
<text x="828" y="155" fill="#a6e3a1" textLength="45" lengthAdjust="spacingAndGlyphs">true*</text>
|
||||
<text x="891" y="155" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="170" width="18" height="17" fill="#394545" />
|
||||
<rect x="45" y="170" width="198" height="17" fill="#394545" />
|
||||
<text x="45" y="172" fill="#6c7086" textLength="198" lengthAdjust="spacingAndGlyphs">Enable Vim keybindings</text>
|
||||
<rect x="243" y="170" width="630" height="17" fill="#394545" />
|
||||
<text x="891" y="172" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="891" y="189" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
@@ -110,8 +118,12 @@
|
||||
<text x="9" y="597" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Apply To </text>
|
||||
<text x="891" y="597" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<rect x="27" y="612" width="9" height="17" fill="#394545" />
|
||||
<text x="27" y="614" fill="#a6e3a1" textLength="9" lengthAdjust="spacingAndGlyphs">●</text>
|
||||
<rect x="36" y="612" width="9" height="17" fill="#394545" />
|
||||
<rect x="45" y="612" width="117" height="17" fill="#394545" />
|
||||
<text x="45" y="614" fill="#a6e3a1" textLength="117" lengthAdjust="spacingAndGlyphs">User Settings</text>
|
||||
<rect x="162" y="612" width="711" height="17" fill="#394545" />
|
||||
<text x="891" y="614" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="631" fill="#3d3f51" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="631" fill="#ffffff" textLength="882" lengthAdjust="spacingAndGlyphs"> Workspace Settings </text>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
@@ -7,7 +7,7 @@ exports[`SuggestionsDisplay > handles scrolling 1`] = `
|
||||
Cmd 7 Description 7
|
||||
Cmd 8 Description 8
|
||||
Cmd 9 Description 9
|
||||
Cmd 10 Description 10
|
||||
Cmd 10 Description 10
|
||||
Cmd 11 Description 11
|
||||
Cmd 12 Description 12
|
||||
▼
|
||||
@@ -17,13 +17,13 @@ exports[`SuggestionsDisplay > handles scrolling 1`] = `
|
||||
|
||||
exports[`SuggestionsDisplay > highlights active item 1`] = `
|
||||
" command1 Description 1
|
||||
command2 Description 2
|
||||
command2 Description 2
|
||||
command3 Description 3
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`SuggestionsDisplay > renders MCP tag for MCP prompts 1`] = `
|
||||
" mcp-tool [MCP]
|
||||
" mcp-tool [MCP]
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -33,7 +33,7 @@ exports[`SuggestionsDisplay > renders loading state 1`] = `
|
||||
`;
|
||||
|
||||
exports[`SuggestionsDisplay > renders suggestions list 1`] = `
|
||||
" command1 Description 1
|
||||
" command1 Description 1
|
||||
command2 Description 2
|
||||
command3 Description 3
|
||||
"
|
||||
|
||||
@@ -89,7 +89,7 @@ exports[`ThemeDialog Snapshots > should render correctly in scope selector mode
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ThemeDialog Snapshots > should render correctly in theme selection mode 1`] = `
|
||||
exports[`ThemeDialog Snapshots > should render correctly in theme selection mode (isDevelopment: false) 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ > Select Theme Preview │
|
||||
@@ -113,3 +113,90 @@ exports[`ThemeDialog Snapshots > should render correctly in theme selection mode
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`ThemeDialog Snapshots > should render correctly in theme selection mode (isDevelopment: true) 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ │
|
||||
│ > Select Theme Preview │
|
||||
│ ▲ ┌─────────────────────────────────────────────────┐ │
|
||||
│ ● 1. ANSI Dark (Matches terminal) │ │ │
|
||||
│ 2. Atom One Dark │ 1 # function │ │
|
||||
│ 3. Ayu Dark │ 2 def fibonacci(n): │ │
|
||||
│ 4. Default Dark │ 3 a, b = 0, 1 │ │
|
||||
│ 5. Dracula Dark │ 4 for _ in range(n): │ │
|
||||
│ 6. GitHub Dark │ 5 a, b = b, a + b │ │
|
||||
│ 7. Holiday Dark │ 6 return a │ │
|
||||
│ 8. Shades Of Purple Dark │ │ │
|
||||
│ 9. Solarized Dark │ 1 - print("Hello, " + name) │ │
|
||||
│ 10. ANSI Light │ 1 + print(f"Hello, {name}!") │ │
|
||||
│ 11. Ayu Light │ │ │
|
||||
│ 12. Default Light └─────────────────────────────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ ╭─────────────────────────────────────────────────╮ │
|
||||
│ │ DEVELOPER TOOLS (Not visible to users) │ │
|
||||
│ │ │ │
|
||||
│ │ How do colors get applied? │ │
|
||||
│ │ • Hex: Rendered exactly by modern terminals. │ │
|
||||
│ │ Not overridden by app themes. │ │
|
||||
│ │ • Blank: Uses your terminal's default │ │
|
||||
│ │ foreground/background. │ │
|
||||
│ │ • Compatibility: On older terminals, hex is │ │
|
||||
│ │ approximated to the nearest ANSI color. │ │
|
||||
│ │ • ANSI Names: 'red', 'green', etc. are mapped │ │
|
||||
│ │ to your terminal app's palette. │ │
|
||||
│ │ │ │
|
||||
│ │ Value Name │ │
|
||||
│ │ #1E1E… backgroun Main terminal background │ │
|
||||
│ │ d.primary color │ │
|
||||
│ │ #313… backgroun Subtle background for │ │
|
||||
│ │ d.message message blocks │ │
|
||||
│ │ #313… backgroun Background for the input │ │
|
||||
│ │ d.input prompt │ │
|
||||
│ │ #39… background. Background highlight for │ │
|
||||
│ │ focus selected/focused items │ │
|
||||
│ │ #283… backgrou Background for added lines │ │
|
||||
│ │ nd.diff. in diffs │ │
|
||||
│ │ added │ │
|
||||
│ │ #430… backgroun Background for removed │ │
|
||||
│ │ d.diff.re lines in diffs │ │
|
||||
│ │ moved │ │
|
||||
│ │ (blank text.prim Primary text color (uses │ │
|
||||
│ │ ) ary terminal default if blank) │ │
|
||||
│ │ #6C7086 text.secon Secondary/dimmed text │ │
|
||||
│ │ dary color │ │
|
||||
│ │ #89B4FA text.link Hyperlink and highlighting │ │
|
||||
│ │ color │ │
|
||||
│ │ #CBA6F7 text.accen Accent color for │ │
|
||||
│ │ t emphasis │ │
|
||||
│ │ (blank) text.res Color for model response │ │
|
||||
│ │ ponse text (uses terminal default │ │
|
||||
│ │ if blank) │ │
|
||||
│ │ #3d3f51 border.def Standard border color │ │
|
||||
│ │ ault │ │
|
||||
│ │ #6C7086ui.comme Color for code comments and │ │
|
||||
│ │ nt metadata │ │
|
||||
│ │ #6C708 ui.symbol Color for technical symbols │ │
|
||||
│ │ 6 and UI icons │ │
|
||||
│ │ #89B4F ui.active Border color for active or │ │
|
||||
│ │ A running elements │ │
|
||||
│ │ #3d3f5 ui.dark Deeply dimmed color for │ │
|
||||
│ │ 1 subtle UI elements │ │
|
||||
│ │ #A6E3A ui.focus Color for focused elements │ │
|
||||
│ │ 1 (e.g. selected menu items, │ │
|
||||
│ │ focused borders) │ │
|
||||
│ │ #F38BA8status.err Color for error messages │ │
|
||||
│ │ or and critical status │ │
|
||||
│ │ #A6E3A1status.suc Color for success messages │ │
|
||||
│ │ cess and positive status │ │
|
||||
│ │ #F9E2A status.wa Color for warnings and │ │
|
||||
│ │ F rning cautionary status │ │
|
||||
│ │ #4796E4 ui.gradien │ │
|
||||
│ │ #847ACE t │ │
|
||||
│ │ #C3677F │ │
|
||||
│ ╰─────────────────────────────────────────────────╯ │
|
||||
│ │
|
||||
│ (Use Enter to select, Tab to configure scope, Esc to close) │
|
||||
│ │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -65,7 +65,7 @@ describe('<ShellToolMessage />', () => {
|
||||
['SHELL_COMMAND_NAME', SHELL_COMMAND_NAME],
|
||||
['SHELL_TOOL_NAME', SHELL_TOOL_NAME],
|
||||
])('clicks inside the shell area sets focus for %s', async (_, name) => {
|
||||
const { lastFrame, simulateClick } = renderShell(
|
||||
const { lastFrame, simulateClick, unmount } = renderShell(
|
||||
{ name },
|
||||
{ mouseEventsEnabled: true },
|
||||
);
|
||||
@@ -79,6 +79,7 @@ describe('<ShellToolMessage />', () => {
|
||||
await waitFor(() => {
|
||||
expect(mockSetEmbeddedShellFocused).toHaveBeenCalledWith(true);
|
||||
});
|
||||
unmount();
|
||||
});
|
||||
it('resets focus when shell finishes', async () => {
|
||||
let updateStatus: (s: CoreToolCallStatus) => void = () => {};
|
||||
@@ -91,7 +92,7 @@ describe('<ShellToolMessage />', () => {
|
||||
return <ShellToolMessage {...baseProps} status={status} ptyId={1} />;
|
||||
};
|
||||
|
||||
const { lastFrame } = renderWithProviders(<Wrapper />, {
|
||||
const { lastFrame, unmount } = renderWithProviders(<Wrapper />, {
|
||||
uiActions,
|
||||
uiState: {
|
||||
streamingState: StreamingState.Idle,
|
||||
@@ -115,6 +116,7 @@ describe('<ShellToolMessage />', () => {
|
||||
expect(mockSetEmbeddedShellFocused).toHaveBeenCalledWith(false);
|
||||
expect(lastFrame()).not.toContain('(Shift+Tab to unfocus)');
|
||||
});
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -164,9 +166,13 @@ describe('<ShellToolMessage />', () => {
|
||||
},
|
||||
],
|
||||
])('%s', async (_, props, options) => {
|
||||
const { lastFrame, waitUntilReady } = renderShell(props, options);
|
||||
const { lastFrame, waitUntilReady, unmount } = renderShell(
|
||||
props,
|
||||
options,
|
||||
);
|
||||
await waitUntilReady();
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -197,7 +203,7 @@ describe('<ShellToolMessage />', () => {
|
||||
false,
|
||||
],
|
||||
])('%s', async (_, availableTerminalHeight, expectedMaxLines, focused) => {
|
||||
const { lastFrame, waitUntilReady } = renderShell(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderShell(
|
||||
{
|
||||
resultDisplay: LONG_OUTPUT,
|
||||
renderOutputAsMarkdown: false,
|
||||
@@ -218,10 +224,11 @@ describe('<ShellToolMessage />', () => {
|
||||
const frame = lastFrame();
|
||||
expect(frame.match(/Line \d+/g)?.length).toBe(expectedMaxLines);
|
||||
expect(frame).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('fully expands in standard mode when availableTerminalHeight is undefined', async () => {
|
||||
const { lastFrame } = renderShell(
|
||||
const { lastFrame, unmount } = renderShell(
|
||||
{
|
||||
resultDisplay: LONG_OUTPUT,
|
||||
renderOutputAsMarkdown: false,
|
||||
@@ -236,10 +243,11 @@ describe('<ShellToolMessage />', () => {
|
||||
// Should show all 100 lines
|
||||
expect(frame.match(/Line \d+/g)?.length).toBe(100);
|
||||
});
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('fully expands in alternate buffer mode when constrainHeight is false and isExpandable is true', async () => {
|
||||
const { lastFrame, waitUntilReady } = renderShell(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderShell(
|
||||
{
|
||||
resultDisplay: LONG_OUTPUT,
|
||||
renderOutputAsMarkdown: false,
|
||||
@@ -262,10 +270,11 @@ describe('<ShellToolMessage />', () => {
|
||||
expect(frame.match(/Line \d+/g)?.length).toBe(100);
|
||||
});
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('stays constrained in alternate buffer mode when isExpandable is false even if constrainHeight is false', async () => {
|
||||
const { lastFrame, waitUntilReady } = renderShell(
|
||||
const { lastFrame, waitUntilReady, unmount } = renderShell(
|
||||
{
|
||||
resultDisplay: LONG_OUTPUT,
|
||||
renderOutputAsMarkdown: false,
|
||||
@@ -288,6 +297,7 @@ describe('<ShellToolMessage />', () => {
|
||||
expect(frame.match(/Line \d+/g)?.length).toBe(15);
|
||||
});
|
||||
expect(lastFrame()).toMatchSnapshot();
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -125,7 +125,11 @@ export const ShellToolMessage: React.FC<ShellToolMessageProps> = ({
|
||||
borderDimColor={borderDimColor}
|
||||
containerRef={headerRef}
|
||||
>
|
||||
<ToolStatusIndicator status={status} name={name} />
|
||||
<ToolStatusIndicator
|
||||
status={status}
|
||||
name={name}
|
||||
isFocused={isThisShellFocused}
|
||||
/>
|
||||
|
||||
<ToolInfo
|
||||
name={name}
|
||||
|
||||
@@ -88,7 +88,11 @@ export const ToolMessage: React.FC<ToolMessageProps> = ({
|
||||
borderColor={borderColor}
|
||||
borderDimColor={borderDimColor}
|
||||
>
|
||||
<ToolStatusIndicator status={status} name={name} />
|
||||
<ToolStatusIndicator
|
||||
status={status}
|
||||
name={name}
|
||||
isFocused={isThisShellFocused}
|
||||
/>
|
||||
<ToolInfo
|
||||
name={name}
|
||||
status={status}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Box, Text } from 'ink';
|
||||
import { ToolCallStatus, mapCoreStatusToDisplayStatus } from '../../types.js';
|
||||
import { GeminiRespondingSpinner } from '../GeminiRespondingSpinner.js';
|
||||
import { CliSpinner } from '../CliSpinner.js';
|
||||
import {
|
||||
SHELL_COMMAND_NAME,
|
||||
SHELL_NAME,
|
||||
@@ -123,7 +123,7 @@ export const FocusHint: React.FC<{
|
||||
|
||||
return (
|
||||
<Box marginLeft={1} flexShrink={0}>
|
||||
<Text color={theme.text.accent}>
|
||||
<Text color={isThisShellFocused ? theme.ui.focus : theme.ui.active}>
|
||||
{isThisShellFocused
|
||||
? `(${formatCommand(Command.UNFOCUS_SHELL_INPUT)} to unfocus)`
|
||||
: `(${formatCommand(Command.FOCUS_SHELL_INPUT)} to focus)`}
|
||||
@@ -137,15 +137,21 @@ export type TextEmphasis = 'high' | 'medium' | 'low';
|
||||
type ToolStatusIndicatorProps = {
|
||||
status: CoreToolCallStatus;
|
||||
name: string;
|
||||
isFocused?: boolean;
|
||||
};
|
||||
|
||||
export const ToolStatusIndicator: React.FC<ToolStatusIndicatorProps> = ({
|
||||
status: coreStatus,
|
||||
name,
|
||||
isFocused,
|
||||
}) => {
|
||||
const status = mapCoreStatusToDisplayStatus(coreStatus);
|
||||
const isShell = isShellTool(name);
|
||||
const statusColor = isShell ? theme.ui.symbol : theme.status.warning;
|
||||
const statusColor = isFocused
|
||||
? theme.ui.focus
|
||||
: isShell
|
||||
? theme.ui.active
|
||||
: theme.status.warning;
|
||||
|
||||
return (
|
||||
<Box minWidth={STATUS_INDICATOR_WIDTH}>
|
||||
@@ -153,10 +159,9 @@ export const ToolStatusIndicator: React.FC<ToolStatusIndicatorProps> = ({
|
||||
<Text color={theme.status.success}>{TOOL_STATUS.PENDING}</Text>
|
||||
)}
|
||||
{status === ToolCallStatus.Executing && (
|
||||
<GeminiRespondingSpinner
|
||||
spinnerType="toggle"
|
||||
nonRespondingDisplay={TOOL_STATUS.EXECUTING}
|
||||
/>
|
||||
<Text color={statusColor}>
|
||||
<CliSpinner type="toggle" />
|
||||
</Text>
|
||||
)}
|
||||
{status === ToolCallStatus.Success && (
|
||||
<Text color={theme.status.success} aria-label={'Success:'}>
|
||||
|
||||
@@ -29,7 +29,7 @@ export const UserMessage: React.FC<UserMessageProps> = ({ text, width }) => {
|
||||
const config = useConfig();
|
||||
const useBackgroundColor = config.getUseBackgroundColor();
|
||||
|
||||
const textColor = isSlashCommand ? theme.text.accent : theme.text.secondary;
|
||||
const textColor = isSlashCommand ? theme.text.accent : theme.text.primary;
|
||||
|
||||
const displayText = useMemo(() => {
|
||||
if (!text) return text;
|
||||
|
||||
@@ -7,7 +7,7 @@ Note: Command contains redirection which can be undesirable.
|
||||
Tip: Toggle auto-edit (Shift+Tab) to allow redirection in the future.
|
||||
Allow execution of: 'echo, redirection (>)'?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Allow for this session
|
||||
3. No, suggest changes (esc)
|
||||
"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
exports[`<ShellToolMessage /> > Height Constraints > defaults to ACTIVE_SHELL_MAX_LINES in alternate buffer when availableTerminalHeight is undefined 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command A shell command │
|
||||
│ ⊶ Shell Command A shell command │
|
||||
│ │
|
||||
│ Line 86 │
|
||||
│ Line 87 │
|
||||
@@ -131,7 +131,7 @@ exports[`<ShellToolMessage /> > Height Constraints > fully expands in alternate
|
||||
|
||||
exports[`<ShellToolMessage /> > Height Constraints > respects availableTerminalHeight when it is smaller than ACTIVE_SHELL_MAX_LINES 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command A shell command │
|
||||
│ ⊶ Shell Command A shell command │
|
||||
│ │
|
||||
│ Line 93 │
|
||||
│ Line 94 │
|
||||
@@ -168,7 +168,7 @@ exports[`<ShellToolMessage /> > Height Constraints > stays constrained in altern
|
||||
|
||||
exports[`<ShellToolMessage /> > Height Constraints > uses ACTIVE_SHELL_MAX_LINES when availableTerminalHeight is large 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command A shell command │
|
||||
│ ⊶ Shell Command A shell command │
|
||||
│ │
|
||||
│ Line 86 │
|
||||
│ Line 87 │
|
||||
@@ -190,7 +190,7 @@ exports[`<ShellToolMessage /> > Height Constraints > uses ACTIVE_SHELL_MAX_LINES
|
||||
|
||||
exports[`<ShellToolMessage /> > Height Constraints > uses full availableTerminalHeight when focused in alternate buffer mode 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command A shell command (Shift+Tab to unfocus) │
|
||||
│ ⊶ Shell Command A shell command (Shift+Tab to unfocus) │
|
||||
│ │
|
||||
│ Line 3 │
|
||||
│ Line 4 │
|
||||
@@ -295,7 +295,7 @@ exports[`<ShellToolMessage /> > Height Constraints > uses full availableTerminal
|
||||
|
||||
exports[`<ShellToolMessage /> > Snapshots > renders in Alternate Buffer mode while focused 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command A shell command (Shift+Tab to unfocus) │
|
||||
│ ⊶ Shell Command A shell command (Shift+Tab to unfocus) │
|
||||
│ │
|
||||
│ Test result │
|
||||
"
|
||||
@@ -303,7 +303,7 @@ exports[`<ShellToolMessage /> > Snapshots > renders in Alternate Buffer mode whi
|
||||
|
||||
exports[`<ShellToolMessage /> > Snapshots > renders in Alternate Buffer mode while unfocused 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command A shell command │
|
||||
│ ⊶ Shell Command A shell command │
|
||||
│ │
|
||||
│ Test result │
|
||||
"
|
||||
@@ -319,7 +319,7 @@ exports[`<ShellToolMessage /> > Snapshots > renders in Error state 1`] = `
|
||||
|
||||
exports[`<ShellToolMessage /> > Snapshots > renders in Executing state 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ Shell Command A shell command │
|
||||
│ ⊶ Shell Command A shell command │
|
||||
│ │
|
||||
│ Test result │
|
||||
"
|
||||
|
||||
@@ -6,7 +6,7 @@ ls -la
|
||||
whoami
|
||||
Allow execution of 3 commands?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Allow for this session
|
||||
3. No, suggest changes (esc)
|
||||
"
|
||||
@@ -19,7 +19,7 @@ URLs to fetch:
|
||||
- https://raw.githubusercontent.com/google/gemini-react/main/README.md
|
||||
Do you want to proceed?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Allow for this session
|
||||
3. No, suggest changes (esc)
|
||||
"
|
||||
@@ -29,7 +29,7 @@ exports[`ToolConfirmationMessage > should not display urls if prompt and url are
|
||||
"https://example.com
|
||||
Do you want to proceed?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Allow for this session
|
||||
3. No, suggest changes (esc)
|
||||
"
|
||||
@@ -40,7 +40,7 @@ exports[`ToolConfirmationMessage > should strip BiDi characters from MCP tool an
|
||||
Tool: testtool
|
||||
Allow execution of MCP tool "testtool" from server "testserver"?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Allow tool for this session
|
||||
3. Allow all server tools for this session
|
||||
4. No, suggest changes (esc)
|
||||
@@ -55,7 +55,7 @@ exports[`ToolConfirmationMessage > with folder trust > 'for edit confirmations'
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
Apply this change?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Modify with external editor
|
||||
3. No, suggest changes (esc)
|
||||
"
|
||||
@@ -69,7 +69,7 @@ exports[`ToolConfirmationMessage > with folder trust > 'for edit confirmations'
|
||||
╰──────────────────────────────────────────────────────────────────────────────╯
|
||||
Apply this change?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Allow for this session
|
||||
3. Modify with external editor
|
||||
4. No, suggest changes (esc)
|
||||
@@ -80,7 +80,7 @@ exports[`ToolConfirmationMessage > with folder trust > 'for exec confirmations'
|
||||
"echo "hello"
|
||||
Allow execution of: 'echo'?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. No, suggest changes (esc)
|
||||
"
|
||||
`;
|
||||
@@ -89,7 +89,7 @@ exports[`ToolConfirmationMessage > with folder trust > 'for exec confirmations'
|
||||
"echo "hello"
|
||||
Allow execution of: 'echo'?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Allow for this session
|
||||
3. No, suggest changes (esc)
|
||||
"
|
||||
@@ -99,7 +99,7 @@ exports[`ToolConfirmationMessage > with folder trust > 'for info confirmations'
|
||||
"https://example.com
|
||||
Do you want to proceed?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. No, suggest changes (esc)
|
||||
"
|
||||
`;
|
||||
@@ -108,7 +108,7 @@ exports[`ToolConfirmationMessage > with folder trust > 'for info confirmations'
|
||||
"https://example.com
|
||||
Do you want to proceed?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Allow for this session
|
||||
3. No, suggest changes (esc)
|
||||
"
|
||||
@@ -119,7 +119,7 @@ exports[`ToolConfirmationMessage > with folder trust > 'for mcp confirmations' >
|
||||
Tool: test-tool
|
||||
Allow execution of MCP tool "test-tool" from server "test-server"?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. No, suggest changes (esc)
|
||||
"
|
||||
`;
|
||||
@@ -129,7 +129,7 @@ exports[`ToolConfirmationMessage > with folder trust > 'for mcp confirmations' >
|
||||
Tool: test-tool
|
||||
Allow execution of MCP tool "test-tool" from server "test-server"?
|
||||
|
||||
● 1. Allow once
|
||||
● 1. Allow once
|
||||
2. Allow tool for this session
|
||||
3. Allow all server tools for this session
|
||||
4. No, suggest changes (esc)
|
||||
|
||||
@@ -71,7 +71,7 @@ exports[`<ToolGroupMessage /> > Golden Snapshots > renders mixed tool calls incl
|
||||
│ │
|
||||
│ Test result │
|
||||
│ │
|
||||
│ ⊷ run_shell_command Run command │
|
||||
│ ⊶ run_shell_command Run command │
|
||||
│ │
|
||||
│ Test result │
|
||||
╰──────────────────────────────────────────────────────────────────────────╯
|
||||
|
||||
@@ -29,7 +29,7 @@ exports[`<ToolMessage /> > ToolStatusIndicator rendering > shows - for Canceled
|
||||
|
||||
exports[`<ToolMessage /> > ToolStatusIndicator rendering > shows MockRespondingSpinner for Executing status when streamingState is Responding 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ MockRespondingSpinnertest-tool A tool for testing │
|
||||
│ ⊶ test-tool A tool for testing │
|
||||
│ │
|
||||
│ Test result │
|
||||
"
|
||||
@@ -45,7 +45,7 @@ exports[`<ToolMessage /> > ToolStatusIndicator rendering > shows o for Pending s
|
||||
|
||||
exports[`<ToolMessage /> > ToolStatusIndicator rendering > shows paused spinner for Executing status when streamingState is Idle 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ MockRespondingSpinnertest-tool A tool for testing │
|
||||
│ ⊶ test-tool A tool for testing │
|
||||
│ │
|
||||
│ Test result │
|
||||
"
|
||||
@@ -53,7 +53,7 @@ exports[`<ToolMessage /> > ToolStatusIndicator rendering > shows paused spinner
|
||||
|
||||
exports[`<ToolMessage /> > ToolStatusIndicator rendering > shows paused spinner for Executing status when streamingState is WaitingForConfirmation 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ MockRespondingSpinnertest-tool A tool for testing │
|
||||
│ ⊶ test-tool A tool for testing │
|
||||
│ │
|
||||
│ Test result │
|
||||
"
|
||||
@@ -94,7 +94,7 @@ exports[`<ToolMessage /> > renders DiffRenderer for diff results 1`] = `
|
||||
|
||||
exports[`<ToolMessage /> > renders McpProgressIndicator with percentage and message for executing tools 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ MockRespondingSpinnertest-tool A tool for testing │
|
||||
│ ⊶ test-tool A tool for testing │
|
||||
│ │
|
||||
│ ████████░░░░░░░░░░░░ 42% │
|
||||
│ Working on it... │
|
||||
@@ -128,7 +128,7 @@ exports[`<ToolMessage /> > renders emphasis correctly 2`] = `
|
||||
|
||||
exports[`<ToolMessage /> > renders indeterminate progress when total is missing 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ MockRespondingSpinnertest-tool A tool for testing │
|
||||
│ ⊶ test-tool A tool for testing │
|
||||
│ │
|
||||
│ ███████░░░░░░░░░░░░░ 7 │
|
||||
│ Test result │
|
||||
@@ -137,7 +137,7 @@ exports[`<ToolMessage /> > renders indeterminate progress when total is missing
|
||||
|
||||
exports[`<ToolMessage /> > renders only percentage when progressMessage is missing 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ MockRespondingSpinnertest-tool A tool for testing │
|
||||
│ ⊶ test-tool A tool for testing │
|
||||
│ │
|
||||
│ ███████████████░░░░░ 75% │
|
||||
│ Test result │
|
||||
|
||||
@@ -2,63 +2,63 @@
|
||||
|
||||
exports[`Focus Hint > 'ShellToolMessage' > shows focus hint after delay even with NO output > after-delay-no-output 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Shell Command A tool for testing (Tab to focus) │
|
||||
│ ⊶ Shell Command A tool for testing (Tab to focus) │
|
||||
│ │
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Focus Hint > 'ShellToolMessage' > shows focus hint after delay even with NO output > initial-no-output 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Shell Command A tool for testing │
|
||||
│ ⊶ Shell Command A tool for testing │
|
||||
│ │
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Focus Hint > 'ShellToolMessage' > shows focus hint after delay with output > after-delay-with-output 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Shell Command A tool for testing (Tab to focus) │
|
||||
│ ⊶ Shell Command A tool for testing (Tab to focus) │
|
||||
│ │
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Focus Hint > 'ShellToolMessage' > shows focus hint after delay with output > initial-with-output 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Shell Command A tool for testing │
|
||||
│ ⊶ Shell Command A tool for testing │
|
||||
│ │
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Focus Hint > 'ToolMessage' > shows focus hint after delay even with NO output > after-delay-no-output 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Shell Command A tool for testing (Tab to focus) │
|
||||
│ ⊶ Shell Command A tool for testing (Tab to focus) │
|
||||
│ │
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Focus Hint > 'ToolMessage' > shows focus hint after delay even with NO output > initial-no-output 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Shell Command A tool for testing │
|
||||
│ ⊶ Shell Command A tool for testing │
|
||||
│ │
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Focus Hint > 'ToolMessage' > shows focus hint after delay with output > after-delay-with-output 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Shell Command A tool for testing (Tab to focus) │
|
||||
│ ⊶ Shell Command A tool for testing (Tab to focus) │
|
||||
│ │
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Focus Hint > 'ToolMessage' > shows focus hint after delay with output > initial-with-output 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Shell Command A tool for testing │
|
||||
│ ⊶ Shell Command A tool for testing │
|
||||
│ │
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`Focus Hint > handles long descriptions by shrinking them to show the focus hint > long-description 1`] = `
|
||||
"╭──────────────────────────────────────────────────────────────────────────────╮
|
||||
│ Shell Command AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA… (Tab to focus) │
|
||||
│ ⊶ Shell Command AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA… (Tab to focus) │
|
||||
│ │
|
||||
"
|
||||
`;
|
||||
|
||||
@@ -19,13 +19,15 @@ vi.mock('../../hooks/useSelectionList.js');
|
||||
|
||||
const mockTheme = {
|
||||
text: { primary: 'COLOR_PRIMARY', secondary: 'COLOR_SECONDARY' },
|
||||
status: { success: 'COLOR_SUCCESS' },
|
||||
ui: { focus: 'COLOR_FOCUS' },
|
||||
background: { focus: 'COLOR_FOCUS_BG' },
|
||||
} as typeof theme;
|
||||
|
||||
vi.mock('../../semantic-colors.js', () => ({
|
||||
theme: {
|
||||
text: { primary: 'COLOR_PRIMARY', secondary: 'COLOR_SECONDARY' },
|
||||
status: { success: 'COLOR_SUCCESS' },
|
||||
ui: { focus: 'COLOR_FOCUS' },
|
||||
background: { focus: 'COLOR_FOCUS_BG' },
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -161,8 +163,8 @@ describe('BaseSelectionList', () => {
|
||||
expect(mockRenderItem).toHaveBeenCalledWith(
|
||||
items[0],
|
||||
expect.objectContaining({
|
||||
titleColor: mockTheme.status.success,
|
||||
numberColor: mockTheme.status.success,
|
||||
titleColor: mockTheme.ui.focus,
|
||||
numberColor: mockTheme.ui.focus,
|
||||
isSelected: true,
|
||||
}),
|
||||
);
|
||||
@@ -207,8 +209,8 @@ describe('BaseSelectionList', () => {
|
||||
expect(mockRenderItem).toHaveBeenCalledWith(
|
||||
items[1],
|
||||
expect.objectContaining({
|
||||
titleColor: mockTheme.status.success,
|
||||
numberColor: mockTheme.status.success,
|
||||
titleColor: mockTheme.ui.focus,
|
||||
numberColor: mockTheme.ui.focus,
|
||||
isSelected: true,
|
||||
}),
|
||||
);
|
||||
@@ -267,7 +269,7 @@ describe('BaseSelectionList', () => {
|
||||
items[0],
|
||||
expect.objectContaining({
|
||||
isSelected: true,
|
||||
titleColor: mockTheme.status.success,
|
||||
titleColor: mockTheme.ui.focus,
|
||||
numberColor: mockTheme.text.secondary,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -117,8 +117,8 @@ export function BaseSelectionList<
|
||||
let numberColor = theme.text.primary;
|
||||
|
||||
if (isSelected) {
|
||||
titleColor = theme.status.success;
|
||||
numberColor = theme.status.success;
|
||||
titleColor = theme.ui.focus;
|
||||
numberColor = theme.ui.focus;
|
||||
} else if (item.disabled) {
|
||||
titleColor = theme.text.secondary;
|
||||
numberColor = theme.text.secondary;
|
||||
@@ -137,11 +137,15 @@ export function BaseSelectionList<
|
||||
)}.`;
|
||||
|
||||
return (
|
||||
<Box key={item.key} alignItems="flex-start">
|
||||
<Box
|
||||
key={item.key}
|
||||
alignItems="flex-start"
|
||||
backgroundColor={isSelected ? theme.background.focus : undefined}
|
||||
>
|
||||
{/* Radio button indicator */}
|
||||
<Box minWidth={2} flexShrink={0}>
|
||||
<Text
|
||||
color={isSelected ? theme.status.success : theme.text.primary}
|
||||
color={isSelected ? theme.ui.focus : theme.text.primary}
|
||||
aria-hidden
|
||||
>
|
||||
{isSelected ? '●' : ' '}
|
||||
|
||||
@@ -459,7 +459,7 @@ export function BaseSettingsDialog({
|
||||
editingKey
|
||||
? theme.border.default
|
||||
: focusSection === 'settings'
|
||||
? theme.border.focused
|
||||
? theme.ui.focus
|
||||
: theme.border.default
|
||||
}
|
||||
paddingX={1}
|
||||
@@ -522,12 +522,17 @@ export function BaseSettingsDialog({
|
||||
|
||||
return (
|
||||
<React.Fragment key={item.key}>
|
||||
<Box marginX={1} flexDirection="row" alignItems="flex-start">
|
||||
<Box
|
||||
marginX={1}
|
||||
flexDirection="row"
|
||||
alignItems="flex-start"
|
||||
backgroundColor={
|
||||
isActive ? theme.background.focus : undefined
|
||||
}
|
||||
>
|
||||
<Box minWidth={2} flexShrink={0}>
|
||||
<Text
|
||||
color={
|
||||
isActive ? theme.status.success : theme.text.secondary
|
||||
}
|
||||
color={isActive ? theme.ui.focus : theme.text.secondary}
|
||||
>
|
||||
{isActive ? '●' : ''}
|
||||
</Text>
|
||||
@@ -544,9 +549,7 @@ export function BaseSettingsDialog({
|
||||
minWidth={0}
|
||||
>
|
||||
<Text
|
||||
color={
|
||||
isActive ? theme.status.success : theme.text.primary
|
||||
}
|
||||
color={isActive ? theme.ui.focus : theme.text.primary}
|
||||
>
|
||||
{item.label}
|
||||
{item.scopeMessage && (
|
||||
@@ -565,7 +568,7 @@ export function BaseSettingsDialog({
|
||||
<Text
|
||||
color={
|
||||
isActive
|
||||
? theme.status.success
|
||||
? theme.ui.focus
|
||||
: item.isGreyedOut
|
||||
? theme.text.secondary
|
||||
: theme.text.primary
|
||||
|
||||
@@ -29,6 +29,12 @@ vi.mock('../../semantic-colors.js', () => ({
|
||||
primary: 'COLOR_PRIMARY',
|
||||
secondary: 'COLOR_SECONDARY',
|
||||
},
|
||||
ui: {
|
||||
focus: 'COLOR_FOCUS',
|
||||
},
|
||||
background: {
|
||||
focus: 'COLOR_FOCUS_BG',
|
||||
},
|
||||
status: {
|
||||
success: 'COLOR_SUCCESS',
|
||||
},
|
||||
|
||||
@@ -27,6 +27,8 @@ vi.mock('./BaseSelectionList.js', () => ({
|
||||
vi.mock('../../semantic-colors.js', () => ({
|
||||
theme: {
|
||||
text: { secondary: 'COLOR_SECONDARY' },
|
||||
ui: { focus: 'COLOR_FOCUS' },
|
||||
background: { focus: 'COLOR_FOCUS_BG' },
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ export const EXPAND_HINT_DURATION_MS = 5000;
|
||||
|
||||
export const DEFAULT_BACKGROUND_OPACITY = 0.16;
|
||||
export const DEFAULT_INPUT_BACKGROUND_OPACITY = 0.24;
|
||||
export const DEFAULT_SELECTION_OPACITY = 0.2;
|
||||
export const DEFAULT_BORDER_OPACITY = 0.4;
|
||||
|
||||
export const KEYBOARD_SHORTCUTS_URL =
|
||||
|
||||
@@ -29,6 +29,9 @@ vi.mock('../semantic-colors.js', () => ({
|
||||
status: {
|
||||
warning: 'mock-warning-color',
|
||||
},
|
||||
ui: {
|
||||
focus: 'mock-focus-color',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ const ansiColors: ColorsTheme = {
|
||||
Comment: 'gray',
|
||||
Gray: 'gray',
|
||||
DarkGray: 'gray',
|
||||
FocusBackground: 'black',
|
||||
GradientColors: ['cyan', 'green'],
|
||||
};
|
||||
|
||||
|
||||
@@ -4,38 +4,25 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
import tinygradient from 'tinygradient';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import {
|
||||
resolveColor,
|
||||
interpolateColor,
|
||||
getThemeTypeFromBackgroundColor,
|
||||
INK_SUPPORTED_NAMES,
|
||||
INK_NAME_TO_HEX_MAP,
|
||||
getLuminance,
|
||||
CSS_NAME_TO_HEX_MAP,
|
||||
} from './theme.js';
|
||||
|
||||
// Define the set of Ink's named colors for quick lookup
|
||||
export const INK_SUPPORTED_NAMES = new Set([
|
||||
'black',
|
||||
'red',
|
||||
'green',
|
||||
'yellow',
|
||||
'blue',
|
||||
'cyan',
|
||||
'magenta',
|
||||
'white',
|
||||
'gray',
|
||||
'grey',
|
||||
'blackbright',
|
||||
'redbright',
|
||||
'greenbright',
|
||||
'yellowbright',
|
||||
'bluebright',
|
||||
'cyanbright',
|
||||
'magentabright',
|
||||
'whitebright',
|
||||
]);
|
||||
|
||||
// Use tinycolor's built-in names map for CSS colors, excluding ones Ink supports
|
||||
export const CSS_NAME_TO_HEX_MAP = Object.fromEntries(
|
||||
Object.entries(tinycolor.names)
|
||||
.filter(([name]) => !INK_SUPPORTED_NAMES.has(name))
|
||||
.map(([name, hex]) => [name, `#${hex}`]),
|
||||
);
|
||||
export {
|
||||
resolveColor,
|
||||
interpolateColor,
|
||||
getThemeTypeFromBackgroundColor,
|
||||
INK_SUPPORTED_NAMES,
|
||||
INK_NAME_TO_HEX_MAP,
|
||||
getLuminance,
|
||||
CSS_NAME_TO_HEX_MAP,
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a color string is valid (hex, Ink-supported color name, or CSS color name).
|
||||
@@ -66,45 +53,6 @@ export function isValidColor(color: string): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a CSS color value (name or hex) into an Ink-compatible color string.
|
||||
* @param colorValue The raw color string (e.g., 'blue', '#ff0000', 'darkkhaki').
|
||||
* @returns An Ink-compatible color string (hex or name), or undefined if not resolvable.
|
||||
*/
|
||||
export function resolveColor(colorValue: string): string | undefined {
|
||||
const lowerColor = colorValue.toLowerCase();
|
||||
|
||||
// 1. Check if it's already a hex code and valid
|
||||
if (lowerColor.startsWith('#')) {
|
||||
if (/^#[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$/.test(colorValue)) {
|
||||
return lowerColor;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle hex codes without #
|
||||
if (/^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$/.test(colorValue)) {
|
||||
return `#${lowerColor}`;
|
||||
}
|
||||
|
||||
// 2. Check if it's an Ink supported name (lowercase)
|
||||
if (INK_SUPPORTED_NAMES.has(lowerColor)) {
|
||||
return lowerColor; // Use Ink name directly
|
||||
}
|
||||
|
||||
// 3. Check if it's a known CSS name we can map to hex
|
||||
if (CSS_NAME_TO_HEX_MAP[lowerColor]) {
|
||||
return CSS_NAME_TO_HEX_MAP[lowerColor]; // Use mapped hex
|
||||
}
|
||||
|
||||
// 4. Could not resolve
|
||||
debugLogger.warn(
|
||||
`[ColorUtils] Could not resolve color "${colorValue}" to an Ink-compatible format.`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a "safe" background color to use in low-color terminals if the
|
||||
* terminal background is a standard black or white.
|
||||
@@ -132,73 +80,6 @@ export function getSafeLowColorBackground(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function interpolateColor(
|
||||
color1: string,
|
||||
color2: string,
|
||||
factor: number,
|
||||
) {
|
||||
if (factor <= 0 && color1) {
|
||||
return color1;
|
||||
}
|
||||
if (factor >= 1 && color2) {
|
||||
return color2;
|
||||
}
|
||||
if (!color1 || !color2) {
|
||||
return '';
|
||||
}
|
||||
const gradient = tinygradient(color1, color2);
|
||||
const color = gradient.rgbAt(factor);
|
||||
return color.toHexString();
|
||||
}
|
||||
|
||||
export function getThemeTypeFromBackgroundColor(
|
||||
backgroundColor: string | undefined,
|
||||
): 'light' | 'dark' | undefined {
|
||||
if (!backgroundColor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const resolvedColor = resolveColor(backgroundColor);
|
||||
if (!resolvedColor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const luminance = getLuminance(resolvedColor);
|
||||
return luminance > 128 ? 'light' : 'dark';
|
||||
}
|
||||
|
||||
// Mapping for ANSI bright colors that are not in tinycolor's standard CSS names
|
||||
export const INK_NAME_TO_HEX_MAP: Readonly<Record<string, string>> = {
|
||||
blackbright: '#555555',
|
||||
redbright: '#ff5555',
|
||||
greenbright: '#55ff55',
|
||||
yellowbright: '#ffff55',
|
||||
bluebright: '#5555ff',
|
||||
magentabright: '#ff55ff',
|
||||
cyanbright: '#55ffff',
|
||||
whitebright: '#ffffff',
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the relative luminance of a color.
|
||||
* See https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
||||
*
|
||||
* @param color Color string (hex or Ink-supported name)
|
||||
* @returns Luminance value (0-255)
|
||||
*/
|
||||
export function getLuminance(color: string): number {
|
||||
const resolved = color.toLowerCase();
|
||||
const hex = INK_NAME_TO_HEX_MAP[resolved] || resolved;
|
||||
|
||||
const colorObj = tinycolor(hex);
|
||||
if (!colorObj.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// tinycolor returns 0-1, we need 0-255
|
||||
return colorObj.getLuminance() * 255;
|
||||
}
|
||||
|
||||
// Hysteresis thresholds to prevent flickering when the background color
|
||||
// is ambiguous (near the midpoint).
|
||||
export const LIGHT_THEME_LUMINANCE_THRESHOLD = 140;
|
||||
|
||||
@@ -23,6 +23,7 @@ const githubLightColors: ColorsTheme = {
|
||||
Comment: '#998',
|
||||
Gray: '#999',
|
||||
DarkGray: interpolateColor('#999', '#f8f8f8', 0.5),
|
||||
FocusColor: '#458', // AccentBlue for GitHub branding
|
||||
GradientColors: ['#458', '#008080'],
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ const holidayColors: ColorsTheme = {
|
||||
Comment: '#8FBC8F',
|
||||
Gray: '#D7F5D3',
|
||||
DarkGray: interpolateColor('#D7F5D3', '#151B18', 0.5),
|
||||
FocusColor: '#33F9FF', // AccentCyan for neon pop
|
||||
GradientColors: ['#FF0000', '#FFFFFF', '#008000'],
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ const noColorColorsTheme: ColorsTheme = {
|
||||
DarkGray: '',
|
||||
InputBackground: '',
|
||||
MessageBackground: '',
|
||||
FocusBackground: '',
|
||||
};
|
||||
|
||||
const noColorSemanticColors: SemanticColors = {
|
||||
@@ -40,6 +41,7 @@ const noColorSemanticColors: SemanticColors = {
|
||||
primary: '',
|
||||
message: '',
|
||||
input: '',
|
||||
focus: '',
|
||||
diff: {
|
||||
added: '',
|
||||
removed: '',
|
||||
@@ -47,12 +49,13 @@ const noColorSemanticColors: SemanticColors = {
|
||||
},
|
||||
border: {
|
||||
default: '',
|
||||
focused: '',
|
||||
},
|
||||
ui: {
|
||||
comment: '',
|
||||
symbol: '',
|
||||
active: '',
|
||||
dark: '',
|
||||
focus: '',
|
||||
gradient: [],
|
||||
},
|
||||
status: {
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface SemanticColors {
|
||||
primary: string;
|
||||
message: string;
|
||||
input: string;
|
||||
focus: string;
|
||||
diff: {
|
||||
added: string;
|
||||
removed: string;
|
||||
@@ -25,12 +26,13 @@ export interface SemanticColors {
|
||||
};
|
||||
border: {
|
||||
default: string;
|
||||
focused: string;
|
||||
};
|
||||
ui: {
|
||||
comment: string;
|
||||
symbol: string;
|
||||
active: string;
|
||||
dark: string;
|
||||
focus: string;
|
||||
gradient: string[] | undefined;
|
||||
};
|
||||
status: {
|
||||
@@ -52,6 +54,7 @@ export const lightSemanticColors: SemanticColors = {
|
||||
primary: lightTheme.Background,
|
||||
message: lightTheme.MessageBackground!,
|
||||
input: lightTheme.InputBackground!,
|
||||
focus: lightTheme.FocusBackground!,
|
||||
diff: {
|
||||
added: lightTheme.DiffAdded,
|
||||
removed: lightTheme.DiffRemoved,
|
||||
@@ -59,12 +62,13 @@ export const lightSemanticColors: SemanticColors = {
|
||||
},
|
||||
border: {
|
||||
default: lightTheme.DarkGray,
|
||||
focused: lightTheme.AccentBlue,
|
||||
},
|
||||
ui: {
|
||||
comment: lightTheme.Comment,
|
||||
symbol: lightTheme.Gray,
|
||||
active: lightTheme.AccentBlue,
|
||||
dark: lightTheme.DarkGray,
|
||||
focus: lightTheme.AccentGreen,
|
||||
gradient: lightTheme.GradientColors,
|
||||
},
|
||||
status: {
|
||||
@@ -86,6 +90,7 @@ export const darkSemanticColors: SemanticColors = {
|
||||
primary: darkTheme.Background,
|
||||
message: darkTheme.MessageBackground!,
|
||||
input: darkTheme.InputBackground!,
|
||||
focus: darkTheme.FocusBackground!,
|
||||
diff: {
|
||||
added: darkTheme.DiffAdded,
|
||||
removed: darkTheme.DiffRemoved,
|
||||
@@ -93,12 +98,13 @@ export const darkSemanticColors: SemanticColors = {
|
||||
},
|
||||
border: {
|
||||
default: darkTheme.DarkGray,
|
||||
focused: darkTheme.AccentBlue,
|
||||
},
|
||||
ui: {
|
||||
comment: darkTheme.Comment,
|
||||
symbol: darkTheme.Gray,
|
||||
active: darkTheme.AccentBlue,
|
||||
dark: darkTheme.DarkGray,
|
||||
focus: darkTheme.AccentGreen,
|
||||
gradient: darkTheme.GradientColors,
|
||||
},
|
||||
status: {
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { type ColorsTheme, Theme } from './theme.js';
|
||||
import { type ColorsTheme, Theme, interpolateColor } from './theme.js';
|
||||
import { type SemanticColors } from './semantic-tokens.js';
|
||||
import { DEFAULT_SELECTION_OPACITY } from '../constants.js';
|
||||
|
||||
const solarizedDarkColors: ColorsTheme = {
|
||||
type: 'dark',
|
||||
@@ -38,6 +39,7 @@ const semanticColors: SemanticColors = {
|
||||
primary: '#002b36',
|
||||
message: '#073642',
|
||||
input: '#073642',
|
||||
focus: interpolateColor('#002b36', '#859900', DEFAULT_SELECTION_OPACITY),
|
||||
diff: {
|
||||
added: '#00382f',
|
||||
removed: '#3d0115',
|
||||
@@ -45,13 +47,14 @@ const semanticColors: SemanticColors = {
|
||||
},
|
||||
border: {
|
||||
default: '#073642',
|
||||
focused: '#586e75',
|
||||
},
|
||||
ui: {
|
||||
comment: '#586e75',
|
||||
symbol: '#93a1a1',
|
||||
active: '#268bd2',
|
||||
dark: '#073642',
|
||||
gradient: ['#268bd2', '#2aa198'],
|
||||
focus: '#859900',
|
||||
gradient: ['#268bd2', '#2aa198', '#859900'],
|
||||
},
|
||||
status: {
|
||||
success: '#859900',
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { type ColorsTheme, Theme } from './theme.js';
|
||||
import { type ColorsTheme, Theme, interpolateColor } from './theme.js';
|
||||
import { type SemanticColors } from './semantic-tokens.js';
|
||||
import { DEFAULT_SELECTION_OPACITY } from '../constants.js';
|
||||
|
||||
const solarizedLightColors: ColorsTheme = {
|
||||
type: 'light',
|
||||
@@ -38,6 +39,7 @@ const semanticColors: SemanticColors = {
|
||||
primary: '#fdf6e3',
|
||||
message: '#eee8d5',
|
||||
input: '#eee8d5',
|
||||
focus: interpolateColor('#fdf6e3', '#859900', DEFAULT_SELECTION_OPACITY),
|
||||
diff: {
|
||||
added: '#d7f2d7',
|
||||
removed: '#f2d7d7',
|
||||
@@ -45,13 +47,14 @@ const semanticColors: SemanticColors = {
|
||||
},
|
||||
border: {
|
||||
default: '#eee8d5',
|
||||
focused: '#93a1a1',
|
||||
},
|
||||
ui: {
|
||||
comment: '#93a1a1',
|
||||
symbol: '#586e75',
|
||||
active: '#268bd2',
|
||||
dark: '#eee8d5',
|
||||
gradient: ['#268bd2', '#2aa198'],
|
||||
focus: '#859900',
|
||||
gradient: ['#268bd2', '#2aa198', '#859900'],
|
||||
},
|
||||
status: {
|
||||
success: '#859900',
|
||||
|
||||
@@ -22,16 +22,18 @@ import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import type { Theme, ThemeType, ColorsTheme } from './theme.js';
|
||||
import type { CustomTheme } from '@google/gemini-cli-core';
|
||||
import { createCustomTheme, validateCustomTheme } from './theme.js';
|
||||
import type { SemanticColors } from './semantic-tokens.js';
|
||||
import {
|
||||
createCustomTheme,
|
||||
validateCustomTheme,
|
||||
interpolateColor,
|
||||
getThemeTypeFromBackgroundColor,
|
||||
resolveColor,
|
||||
} from './color-utils.js';
|
||||
} from './theme.js';
|
||||
import type { SemanticColors } from './semantic-tokens.js';
|
||||
import {
|
||||
DEFAULT_BACKGROUND_OPACITY,
|
||||
DEFAULT_INPUT_BACKGROUND_OPACITY,
|
||||
DEFAULT_SELECTION_OPACITY,
|
||||
DEFAULT_BORDER_OPACITY,
|
||||
} from '../constants.js';
|
||||
import { ANSI } from './ansi.js';
|
||||
@@ -369,6 +371,11 @@ class ThemeManager {
|
||||
colors.Gray,
|
||||
DEFAULT_BACKGROUND_OPACITY,
|
||||
),
|
||||
FocusBackground: interpolateColor(
|
||||
this.terminalBackground,
|
||||
activeTheme.colors.FocusColor ?? activeTheme.colors.AccentGreen,
|
||||
DEFAULT_SELECTION_OPACITY,
|
||||
),
|
||||
};
|
||||
} else {
|
||||
this.cachedColors = colors;
|
||||
@@ -402,6 +409,7 @@ class ThemeManager {
|
||||
primary: this.terminalBackground,
|
||||
message: colors.MessageBackground!,
|
||||
input: colors.InputBackground!,
|
||||
focus: colors.FocusBackground!,
|
||||
},
|
||||
border: {
|
||||
...semanticColors.border,
|
||||
@@ -410,6 +418,7 @@ class ThemeManager {
|
||||
ui: {
|
||||
...semanticColors.ui,
|
||||
dark: colors.DarkGray,
|
||||
focus: colors.FocusColor ?? colors.AccentGreen,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -8,18 +8,153 @@ import type { CSSProperties } from 'react';
|
||||
|
||||
import type { SemanticColors } from './semantic-tokens.js';
|
||||
|
||||
import {
|
||||
resolveColor,
|
||||
interpolateColor,
|
||||
getThemeTypeFromBackgroundColor,
|
||||
} from './color-utils.js';
|
||||
|
||||
import type { CustomTheme } from '@google/gemini-cli-core';
|
||||
import {
|
||||
DEFAULT_BACKGROUND_OPACITY,
|
||||
DEFAULT_INPUT_BACKGROUND_OPACITY,
|
||||
DEFAULT_SELECTION_OPACITY,
|
||||
DEFAULT_BORDER_OPACITY,
|
||||
} from '../constants.js';
|
||||
import tinygradient from 'tinygradient';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
// Define the set of Ink's named colors for quick lookup
|
||||
export const INK_SUPPORTED_NAMES = new Set([
|
||||
'black',
|
||||
'red',
|
||||
'green',
|
||||
'yellow',
|
||||
'blue',
|
||||
'cyan',
|
||||
'magenta',
|
||||
'white',
|
||||
'gray',
|
||||
'grey',
|
||||
'blackbright',
|
||||
'redbright',
|
||||
'greenbright',
|
||||
'yellowbright',
|
||||
'bluebright',
|
||||
'cyanbright',
|
||||
'magentabright',
|
||||
'whitebright',
|
||||
]);
|
||||
|
||||
// Use tinycolor's built-in names map for CSS colors, excluding ones Ink supports
|
||||
export const CSS_NAME_TO_HEX_MAP = Object.fromEntries(
|
||||
Object.entries(tinycolor.names)
|
||||
.filter(([name]) => !INK_SUPPORTED_NAMES.has(name))
|
||||
.map(([name, hex]) => [name, `#${hex}`]),
|
||||
);
|
||||
|
||||
// Mapping for ANSI bright colors that are not in tinycolor's standard CSS names
|
||||
export const INK_NAME_TO_HEX_MAP: Readonly<Record<string, string>> = {
|
||||
blackbright: '#555555',
|
||||
redbright: '#ff5555',
|
||||
greenbright: '#55ff55',
|
||||
yellowbright: '#ffff55',
|
||||
bluebright: '#5555ff',
|
||||
magentabright: '#ff55ff',
|
||||
cyanbright: '#55ffff',
|
||||
whitebright: '#ffffff',
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the relative luminance of a color.
|
||||
* See https://www.w3.org/TR/WCAG20/#relativeluminancedef
|
||||
*
|
||||
* @param color Color string (hex or Ink-supported name)
|
||||
* @returns Luminance value (0-255)
|
||||
*/
|
||||
export function getLuminance(color: string): number {
|
||||
const resolved = color.toLowerCase();
|
||||
const hex = INK_NAME_TO_HEX_MAP[resolved] || resolved;
|
||||
|
||||
const colorObj = tinycolor(hex);
|
||||
if (!colorObj.isValid()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// tinycolor returns 0-1, we need 0-255
|
||||
return colorObj.getLuminance() * 255;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a CSS color value (name or hex) into an Ink-compatible color string.
|
||||
* @param colorValue The raw color string (e.g., 'blue', '#ff0000', 'darkkhaki').
|
||||
* @returns An Ink-compatible color string (hex or name), or undefined if not resolvable.
|
||||
*/
|
||||
export function resolveColor(colorValue: string): string | undefined {
|
||||
const lowerColor = colorValue.toLowerCase();
|
||||
|
||||
// 1. Check if it's already a hex code and valid
|
||||
if (lowerColor.startsWith('#')) {
|
||||
if (/^#[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$/.test(colorValue)) {
|
||||
return lowerColor;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle hex codes without #
|
||||
if (/^[0-9A-Fa-f]{3}([0-9A-Fa-f]{3})?$/.test(colorValue)) {
|
||||
return `#${lowerColor}`;
|
||||
}
|
||||
|
||||
// 2. Check if it's an Ink supported name (lowercase)
|
||||
if (INK_SUPPORTED_NAMES.has(lowerColor)) {
|
||||
return lowerColor; // Use Ink name directly
|
||||
}
|
||||
|
||||
// 3. Check if it's a known CSS name we can map to hex
|
||||
// We can't import CSS_NAME_TO_HEX_MAP here due to circular deps,
|
||||
// but we can use tinycolor directly for named colors.
|
||||
const colorObj = tinycolor(lowerColor);
|
||||
if (colorObj.isValid()) {
|
||||
return colorObj.toHexString();
|
||||
}
|
||||
|
||||
// 4. Could not resolve
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function interpolateColor(
|
||||
color1: string,
|
||||
color2: string,
|
||||
factor: number,
|
||||
) {
|
||||
if (factor <= 0 && color1) {
|
||||
return color1;
|
||||
}
|
||||
if (factor >= 1 && color2) {
|
||||
return color2;
|
||||
}
|
||||
if (!color1 || !color2) {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
const gradient = tinygradient(color1, color2);
|
||||
const color = gradient.rgbAt(factor);
|
||||
return color.toHexString();
|
||||
} catch (_e) {
|
||||
return color1;
|
||||
}
|
||||
}
|
||||
|
||||
export function getThemeTypeFromBackgroundColor(
|
||||
backgroundColor: string | undefined,
|
||||
): 'light' | 'dark' | undefined {
|
||||
if (!backgroundColor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const resolvedColor = resolveColor(backgroundColor);
|
||||
if (!resolvedColor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const luminance = getLuminance(resolvedColor);
|
||||
return luminance > 128 ? 'light' : 'dark';
|
||||
}
|
||||
|
||||
export type { CustomTheme };
|
||||
|
||||
@@ -43,6 +178,8 @@ export interface ColorsTheme {
|
||||
DarkGray: string;
|
||||
InputBackground?: string;
|
||||
MessageBackground?: string;
|
||||
FocusBackground?: string;
|
||||
FocusColor?: string;
|
||||
GradientColors?: string[];
|
||||
}
|
||||
|
||||
@@ -70,7 +207,12 @@ export const lightTheme: ColorsTheme = {
|
||||
MessageBackground: interpolateColor(
|
||||
'#FAFAFA',
|
||||
'#97a0b0',
|
||||
DEFAULT_BACKGROUND_OPACITY,
|
||||
DEFAULT_INPUT_BACKGROUND_OPACITY,
|
||||
),
|
||||
FocusBackground: interpolateColor(
|
||||
'#FAFAFA',
|
||||
'#3CA84B',
|
||||
DEFAULT_SELECTION_OPACITY,
|
||||
),
|
||||
GradientColors: ['#4796E4', '#847ACE', '#C3677F'],
|
||||
};
|
||||
@@ -99,7 +241,12 @@ export const darkTheme: ColorsTheme = {
|
||||
MessageBackground: interpolateColor(
|
||||
'#1E1E2E',
|
||||
'#6C7086',
|
||||
DEFAULT_BACKGROUND_OPACITY,
|
||||
DEFAULT_INPUT_BACKGROUND_OPACITY,
|
||||
),
|
||||
FocusBackground: interpolateColor(
|
||||
'#1E1E2E',
|
||||
'#A6E3A1',
|
||||
DEFAULT_SELECTION_OPACITY,
|
||||
),
|
||||
GradientColors: ['#4796E4', '#847ACE', '#C3677F'],
|
||||
};
|
||||
@@ -122,6 +269,7 @@ export const ansiTheme: ColorsTheme = {
|
||||
DarkGray: 'gray',
|
||||
InputBackground: 'black',
|
||||
MessageBackground: 'black',
|
||||
FocusBackground: 'black',
|
||||
};
|
||||
|
||||
export class Theme {
|
||||
@@ -164,7 +312,7 @@ export class Theme {
|
||||
interpolateColor(
|
||||
this.colors.Background,
|
||||
this.colors.Gray,
|
||||
DEFAULT_BACKGROUND_OPACITY,
|
||||
DEFAULT_INPUT_BACKGROUND_OPACITY,
|
||||
),
|
||||
input:
|
||||
this.colors.InputBackground ??
|
||||
@@ -173,6 +321,13 @@ export class Theme {
|
||||
this.colors.Gray,
|
||||
DEFAULT_INPUT_BACKGROUND_OPACITY,
|
||||
),
|
||||
focus:
|
||||
this.colors.FocusBackground ??
|
||||
interpolateColor(
|
||||
this.colors.Background,
|
||||
this.colors.FocusColor ?? this.colors.AccentGreen,
|
||||
DEFAULT_SELECTION_OPACITY,
|
||||
),
|
||||
diff: {
|
||||
added: this.colors.DiffAdded,
|
||||
removed: this.colors.DiffRemoved,
|
||||
@@ -180,12 +335,13 @@ export class Theme {
|
||||
},
|
||||
border: {
|
||||
default: this.colors.DarkGray,
|
||||
focused: this.colors.AccentBlue,
|
||||
},
|
||||
ui: {
|
||||
comment: this.colors.Gray,
|
||||
symbol: this.colors.AccentCyan,
|
||||
active: this.colors.AccentBlue,
|
||||
dark: this.colors.DarkGray,
|
||||
focus: this.colors.FocusColor ?? this.colors.AccentGreen,
|
||||
gradient: this.colors.GradientColors,
|
||||
},
|
||||
status: {
|
||||
@@ -292,8 +448,14 @@ export function createCustomTheme(customTheme: CustomTheme): Theme {
|
||||
MessageBackground: interpolateColor(
|
||||
customTheme.background?.primary ?? customTheme.Background ?? '',
|
||||
customTheme.text?.secondary ?? customTheme.Gray ?? '',
|
||||
DEFAULT_BACKGROUND_OPACITY,
|
||||
DEFAULT_INPUT_BACKGROUND_OPACITY,
|
||||
),
|
||||
FocusBackground: interpolateColor(
|
||||
customTheme.background?.primary ?? customTheme.Background ?? '',
|
||||
customTheme.status?.success ?? customTheme.AccentGreen ?? '#3CA84B', // Fallback to a default green if not found
|
||||
DEFAULT_SELECTION_OPACITY,
|
||||
),
|
||||
FocusColor: customTheme.ui?.focus ?? customTheme.AccentGreen,
|
||||
GradientColors: customTheme.ui?.gradient ?? customTheme.GradientColors,
|
||||
};
|
||||
|
||||
@@ -450,6 +612,7 @@ export function createCustomTheme(customTheme: CustomTheme): Theme {
|
||||
primary: customTheme.background?.primary ?? colors.Background,
|
||||
message: colors.MessageBackground!,
|
||||
input: colors.InputBackground!,
|
||||
focus: colors.FocusBackground!,
|
||||
diff: {
|
||||
added: customTheme.background?.diff?.added ?? colors.DiffAdded,
|
||||
removed: customTheme.background?.diff?.removed ?? colors.DiffRemoved,
|
||||
@@ -457,12 +620,13 @@ export function createCustomTheme(customTheme: CustomTheme): Theme {
|
||||
},
|
||||
border: {
|
||||
default: colors.DarkGray,
|
||||
focused: customTheme.border?.focused ?? colors.AccentBlue,
|
||||
},
|
||||
ui: {
|
||||
comment: customTheme.ui?.comment ?? colors.Comment,
|
||||
symbol: customTheme.ui?.symbol ?? colors.Gray,
|
||||
active: customTheme.ui?.active ?? colors.AccentBlue,
|
||||
dark: colors.DarkGray,
|
||||
focus: colors.FocusColor ?? colors.AccentGreen,
|
||||
gradient: customTheme.ui?.gradient ?? colors.GradientColors,
|
||||
},
|
||||
status: {
|
||||
|
||||
@@ -23,6 +23,7 @@ const xcodeColors: ColorsTheme = {
|
||||
Comment: '#007400',
|
||||
Gray: '#c0c0c0',
|
||||
DarkGray: interpolateColor('#c0c0c0', '#fff', 0.5),
|
||||
FocusColor: '#1c00cf', // AccentBlue for more vibrance
|
||||
GradientColors: ['#1c00cf', '#007400'],
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<text x="27" y="70" fill="#6688d9" textLength="9" lengthAdjust="spacingAndGlyphs">▀</text>
|
||||
<text x="0" y="104" fill="#f9e2af" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="121" fill="#f9e2af" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="121" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs"> ⊷ </text>
|
||||
<text x="18" y="121" fill="#f9e2af" textLength="9" lengthAdjust="spacingAndGlyphs">⊶</text>
|
||||
<text x="45" y="121" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold">google_web_search</text>
|
||||
<text x="855" y="121" fill="#f9e2af" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#f9e2af" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -17,16 +17,16 @@
|
||||
<text x="45" y="53" fill="#a471a7" textLength="9" lengthAdjust="spacingAndGlyphs">▀</text>
|
||||
<text x="18" y="70" fill="#4796e4" textLength="9" lengthAdjust="spacingAndGlyphs">▝</text>
|
||||
<text x="27" y="70" fill="#6688d9" textLength="9" lengthAdjust="spacingAndGlyphs">▀</text>
|
||||
<text x="0" y="104" fill="#6c7086" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="121" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="121" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs"> ⊷ </text>
|
||||
<text x="0" y="104" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="121" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="18" y="121" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">⊶</text>
|
||||
<text x="45" y="121" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold">run_shell_command</text>
|
||||
<text x="855" y="121" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="855" y="138" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="855" y="121" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="855" y="138" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="155" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="155" fill="#ffffff" textLength="846" lengthAdjust="spacingAndGlyphs"> Running command... </text>
|
||||
<text x="855" y="155" fill="#6c7086" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#6c7086" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
<text x="855" y="155" fill="#89b4fa" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="172" fill="#89b4fa" textLength="864" lengthAdjust="spacingAndGlyphs">╰──────────────────────────────────────────────────────────────────────────────────────────────╯</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -19,7 +19,7 @@
|
||||
<text x="27" y="70" fill="#6688d9" textLength="9" lengthAdjust="spacingAndGlyphs">▀</text>
|
||||
<text x="0" y="104" fill="#f9e2af" textLength="864" lengthAdjust="spacingAndGlyphs">╭──────────────────────────────────────────────────────────────────────────────────────────────╮</text>
|
||||
<text x="0" y="121" fill="#f9e2af" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="9" y="121" fill="#ffffff" textLength="36" lengthAdjust="spacingAndGlyphs"> ⊷ </text>
|
||||
<text x="18" y="121" fill="#f9e2af" textLength="9" lengthAdjust="spacingAndGlyphs">⊶</text>
|
||||
<text x="45" y="121" fill="#ffffff" textLength="153" lengthAdjust="spacingAndGlyphs" font-weight="bold">google_web_search</text>
|
||||
<text x="855" y="121" fill="#f9e2af" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
<text x="0" y="138" fill="#f9e2af" textLength="9" lengthAdjust="spacingAndGlyphs">│</text>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -8,7 +8,7 @@ exports[`MainContent tool group border SVG snapshots > should render SVG snapsho
|
||||
▝▀
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ google_web_search │
|
||||
│ ⊶ google_web_search │
|
||||
│ │
|
||||
│ Searching... │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||
@@ -22,7 +22,7 @@ exports[`MainContent tool group border SVG snapshots > should render SVG snapsho
|
||||
▝▀
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ run_shell_command │
|
||||
│ ⊶ run_shell_command │
|
||||
│ │
|
||||
│ Running command... │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||
@@ -36,7 +36,7 @@ exports[`MainContent tool group border SVG snapshots > should render SVG snapsho
|
||||
▝▀
|
||||
|
||||
╭──────────────────────────────────────────────────────────────────────────────────────────────╮
|
||||
│ ⊷ google_web_search │
|
||||
│ ⊶ google_web_search │
|
||||
│ │
|
||||
│ Searching... │
|
||||
╰──────────────────────────────────────────────────────────────────────────────────────────────╯"
|
||||
|
||||
@@ -4,13 +4,18 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { getToolGroupBorderAppearance } from './borderStyles.js';
|
||||
import { CoreToolCallStatus } from '@google/gemini-cli-core';
|
||||
import { theme } from '../semantic-colors.js';
|
||||
import type { IndividualToolCallDisplay } from '../types.js';
|
||||
import { renderWithProviders } from '../../test-utils/render.js';
|
||||
import { MainContent } from '../components/MainContent.js';
|
||||
import { Text } from 'ink';
|
||||
|
||||
vi.mock('../components/CliSpinner.js', () => ({
|
||||
CliSpinner: () => <Text>⊶</Text>,
|
||||
}));
|
||||
|
||||
describe('getToolGroupBorderAppearance', () => {
|
||||
it('should use warning color for pending non-shell tools', () => {
|
||||
@@ -60,7 +65,7 @@ describe('getToolGroupBorderAppearance', () => {
|
||||
expect(appearance.borderDimColor).toBe(true);
|
||||
});
|
||||
|
||||
it('should use symbol color for shell tools', () => {
|
||||
it('should use active color for shell tools', () => {
|
||||
const item = {
|
||||
type: 'tool_group' as const,
|
||||
tools: [
|
||||
@@ -73,9 +78,28 @@ describe('getToolGroupBorderAppearance', () => {
|
||||
] as IndividualToolCallDisplay[],
|
||||
};
|
||||
const appearance = getToolGroupBorderAppearance(item, undefined, false, []);
|
||||
expect(appearance.borderColor).toBe(theme.ui.symbol);
|
||||
expect(appearance.borderColor).toBe(theme.ui.active);
|
||||
expect(appearance.borderDimColor).toBe(true);
|
||||
});
|
||||
|
||||
it('should use focus color for focused shell tools', () => {
|
||||
const ptyId = 123;
|
||||
const item = {
|
||||
type: 'tool_group' as const,
|
||||
tools: [
|
||||
{
|
||||
name: 'run_shell_command',
|
||||
status: CoreToolCallStatus.Executing,
|
||||
resultDisplay: '',
|
||||
callId: 'call-1',
|
||||
ptyId,
|
||||
},
|
||||
] as IndividualToolCallDisplay[],
|
||||
};
|
||||
const appearance = getToolGroupBorderAppearance(item, ptyId, true, []);
|
||||
expect(appearance.borderColor).toBe(theme.ui.focus);
|
||||
expect(appearance.borderDimColor).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('MainContent tool group border SVG snapshots', () => {
|
||||
|
||||
@@ -113,9 +113,10 @@ export function getToolGroupBorderAppearance(
|
||||
isCurrentlyInShellTurn &&
|
||||
!!embeddedShellFocused);
|
||||
|
||||
const borderColor =
|
||||
(isShell && isPending) || isEffectivelyFocused
|
||||
? theme.ui.symbol
|
||||
const borderColor = isEffectivelyFocused
|
||||
? theme.ui.focus
|
||||
: isShell && isPending
|
||||
? theme.ui.active
|
||||
: isPending
|
||||
? theme.status.warning
|
||||
: theme.border.default;
|
||||
|
||||
@@ -17,6 +17,9 @@ vi.mock('../semantic-colors.js', () => ({
|
||||
accent: 'cyan',
|
||||
link: 'blue',
|
||||
},
|
||||
ui: {
|
||||
focus: 'green',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -250,11 +250,12 @@ export interface CustomTheme {
|
||||
};
|
||||
border?: {
|
||||
default?: string;
|
||||
focused?: string;
|
||||
};
|
||||
ui?: {
|
||||
comment?: string;
|
||||
symbol?: string;
|
||||
active?: string;
|
||||
focus?: string;
|
||||
gradient?: string[];
|
||||
};
|
||||
status?: {
|
||||
|
||||