Polish Theme Dialog (#1356)

This commit is contained in:
Jacob Richman 2025-06-23 23:43:17 +00:00 committed by GitHub
parent 8c6545bf9d
commit f741630572
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 144 additions and 91 deletions

View File

@ -30,17 +30,22 @@ export const Header: React.FC<HeaderProps> = ({
terminalWidth >= widthOfLongLogo ? longAsciiLogo : shortAsciiLogo;
}
const artWidth = getAsciiArtWidth(displayTitle);
return (
<>
<Box marginBottom={1} alignItems="flex-start">
{Colors.GradientColors ? (
<Gradient colors={Colors.GradientColors}>
<Text>{displayTitle}</Text>
</Gradient>
) : (
<Box
marginBottom={1}
alignItems="flex-start"
width={artWidth}
flexShrink={0}
>
{Colors.GradientColors ? (
<Gradient colors={Colors.GradientColors}>
<Text>{displayTitle}</Text>
)}
</Box>
</>
</Gradient>
) : (
<Text>{displayTitle}</Text>
)}
</Box>
);
};

View File

@ -115,94 +115,143 @@ export function ThemeDialog({
1,
);
const DAILOG_PADDING = 2;
const selectThemeHeight = themeItems.length + 1;
const SCOPE_SELECTION_HEIGHT = 4; // Height for the scope selection section + margin.
const SPACE_BETWEEN_THEME_SELECTION_AND_APPLY_TO = 1;
const TAB_TO_SELECT_HEIGHT = 2;
availableTerminalHeight = availableTerminalHeight ?? Number.MAX_SAFE_INTEGER;
availableTerminalHeight -= 2; // Top and bottom borders.
availableTerminalHeight -= TAB_TO_SELECT_HEIGHT;
let totalLeftHandSideHeight =
DAILOG_PADDING +
selectThemeHeight +
SCOPE_SELECTION_HEIGHT +
SPACE_BETWEEN_THEME_SELECTION_AND_APPLY_TO;
let showScopeSelection = true;
let includePadding = true;
// Remove content from the LHS that can be ommitted if it exceeds the available height.
if (totalLeftHandSideHeight > availableTerminalHeight) {
includePadding = false;
totalLeftHandSideHeight -= DAILOG_PADDING;
}
if (totalLeftHandSideHeight > availableTerminalHeight) {
// First, try hiding the scope selection
totalLeftHandSideHeight -= SCOPE_SELECTION_HEIGHT;
showScopeSelection = false;
}
// Don't focus the scope selection if it is hidden due to height constraints.
const currenFocusedSection = !showScopeSelection ? 'theme' : focusedSection;
// Vertical space taken by elements other than the two code blocks in the preview pane.
// Includes "Preview" title, borders, padding, and margin between blocks.
const PREVIEW_PANE_FIXED_VERTICAL_SPACE = 7;
const availableTerminalHeightCodeBlock = availableTerminalHeight
? Math.max(
Math.floor(
(availableTerminalHeight - PREVIEW_PANE_FIXED_VERTICAL_SPACE) / 2,
),
2,
)
: undefined;
// Includes "Preview" title, borders, and margin between blocks.
const PREVIEW_PANE_FIXED_VERTICAL_SPACE = 8;
// The right column doesn't need to ever be shorter than the left column.
availableTerminalHeight = Math.max(
availableTerminalHeight,
totalLeftHandSideHeight,
);
const availableTerminalHeightCodeBlock =
availableTerminalHeight -
PREVIEW_PANE_FIXED_VERTICAL_SPACE -
(includePadding ? 2 : 0) * 2;
// Give slightly more space to the code block as it is 3 lines longer.
const diffHeight = Math.floor(availableTerminalHeightCodeBlock / 2) - 1;
const codeBlockHeight = Math.ceil(availableTerminalHeightCodeBlock / 2) + 1;
return (
<Box
borderStyle="round"
borderColor={Colors.Gray}
flexDirection="row"
padding={1}
flexDirection="column"
paddingTop={includePadding ? 1 : 0}
paddingBottom={includePadding ? 1 : 0}
paddingLeft={1}
paddingRight={1}
width="100%"
>
{/* Left Column: Selection */}
<Box flexDirection="column" width="45%" paddingRight={2}>
<Text bold={focusedSection === 'theme'}>
{focusedSection === 'theme' ? '> ' : ' '}Select Theme{' '}
<Text color={Colors.Gray}>{otherScopeModifiedMessage}</Text>
</Text>
<RadioButtonSelect
key={selectInputKey}
items={themeItems}
initialIndex={initialThemeIndex}
onSelect={handleThemeSelect}
onHighlight={onHighlight}
isFocused={focusedSection === 'theme'}
/>
{/* Scope Selection */}
<Box marginTop={1} flexDirection="column">
<Text bold={focusedSection === 'scope'}>
{focusedSection === 'scope' ? '> ' : ' '}Apply To
<Box flexDirection="row">
{/* Left Column: Selection */}
<Box flexDirection="column" width="45%" paddingRight={2}>
<Text bold={currenFocusedSection === 'theme'} wrap="truncate">
{currenFocusedSection === 'theme' ? '> ' : ' '}Select Theme{' '}
<Text color={Colors.Gray}>{otherScopeModifiedMessage}</Text>
</Text>
<RadioButtonSelect
items={scopeItems}
initialIndex={0} // Default to User Settings
onSelect={handleScopeSelect}
onHighlight={handleScopeHighlight}
isFocused={focusedSection === 'scope'}
key={selectInputKey}
items={themeItems}
initialIndex={initialThemeIndex}
onSelect={handleThemeSelect}
onHighlight={onHighlight}
isFocused={currenFocusedSection === 'theme'}
/>
{/* Scope Selection */}
{showScopeSelection && (
<Box marginTop={1} flexDirection="column">
<Text bold={currenFocusedSection === 'scope'} wrap="truncate">
{currenFocusedSection === 'scope' ? '> ' : ' '}Apply To
</Text>
<RadioButtonSelect
items={scopeItems}
initialIndex={0} // Default to User Settings
onSelect={handleScopeSelect}
onHighlight={handleScopeHighlight}
isFocused={currenFocusedSection === 'scope'}
/>
</Box>
)}
</Box>
<Box marginTop={1}>
<Text color={Colors.Gray}>
(Use Enter to select, Tab to change focus)
</Text>
{/* Right Column: Preview */}
<Box flexDirection="column" width="55%" paddingLeft={2}>
<Text bold>Preview</Text>
<Box
borderStyle="single"
borderColor={Colors.Gray}
paddingTop={includePadding ? 1 : 0}
paddingBottom={includePadding ? 1 : 0}
paddingLeft={1}
paddingRight={1}
flexDirection="column"
>
{colorizeCode(
`# function
-def fibonacci(n):
- a, b = 0, 1
- for _ in range(n):
- a, b = b, a + b
- return a`,
'python',
codeBlockHeight,
colorizeCodeWidth,
)}
<Box marginTop={1} />
<DiffRenderer
diffContent={`--- a/old_file.txt
-+++ b/new_file.txt
-@@ -1,4 +1,5 @@
- This is a context line.
--This line was deleted.
-+This line was added.
-`}
availableTerminalHeight={diffHeight}
terminalWidth={colorizeCodeWidth}
/>
</Box>
</Box>
</Box>
{/* Right Column: Preview */}
<Box flexDirection="column" width="55%" paddingLeft={2}>
<Text bold>Preview</Text>
<Box
borderStyle="single"
borderColor={Colors.Gray}
padding={1}
flexDirection="column"
>
{colorizeCode(
`# function
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a`,
'python',
availableTerminalHeightCodeBlock,
colorizeCodeWidth,
)}
<Box marginTop={1} />
<DiffRenderer
diffContent={`--- a/old_file.txt
+++ b/new_file.txt
@@ -1,4 +1,5 @@
This is a context line.
-This line was deleted.
+This line was added.
`}
availableTerminalHeight={availableTerminalHeightCodeBlock}
terminalWidth={colorizeCodeWidth}
/>
</Box>
<Box marginTop={1}>
<Text color={Colors.Gray} wrap="truncate">
(Use Enter to select
{showScopeSelection ? ', Tab to change focus' : ''})
</Text>
</Box>
</Box>
);

View File

@ -5,7 +5,7 @@
*/
import React from 'react';
import { Text } from 'ink';
import { Text, Box } from 'ink';
import SelectInput, {
type ItemProps as InkSelectItemProps,
type IndicatorProps as InkSelectIndicatorProps,
@ -78,12 +78,11 @@ export function RadioButtonSelect<T>({
isSelected = false,
}: InkSelectIndicatorProps): React.JSX.Element {
return (
<Text
color={isSelected ? Colors.AccentGreen : Colors.Foreground}
wrap="truncate"
>
{isSelected ? '● ' : '○ '}
</Text>
<Box minWidth={2} flexShrink={0}>
<Text color={isSelected ? Colors.AccentGreen : Colors.Foreground}>
{isSelected ? '●' : '○'}
</Text>
</Box>
);
}