Polish Theme Dialog (#1356)
This commit is contained in:
parent
8c6545bf9d
commit
f741630572
|
@ -30,9 +30,15 @@ export const Header: React.FC<HeaderProps> = ({
|
||||||
terminalWidth >= widthOfLongLogo ? longAsciiLogo : shortAsciiLogo;
|
terminalWidth >= widthOfLongLogo ? longAsciiLogo : shortAsciiLogo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const artWidth = getAsciiArtWidth(displayTitle);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Box
|
||||||
<Box marginBottom={1} alignItems="flex-start">
|
marginBottom={1}
|
||||||
|
alignItems="flex-start"
|
||||||
|
width={artWidth}
|
||||||
|
flexShrink={0}
|
||||||
|
>
|
||||||
{Colors.GradientColors ? (
|
{Colors.GradientColors ? (
|
||||||
<Gradient colors={Colors.GradientColors}>
|
<Gradient colors={Colors.GradientColors}>
|
||||||
<Text>{displayTitle}</Text>
|
<Text>{displayTitle}</Text>
|
||||||
|
@ -41,6 +47,5 @@ export const Header: React.FC<HeaderProps> = ({
|
||||||
<Text>{displayTitle}</Text>
|
<Text>{displayTitle}</Text>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -115,29 +115,72 @@ export function ThemeDialog({
|
||||||
1,
|
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.
|
// Vertical space taken by elements other than the two code blocks in the preview pane.
|
||||||
// Includes "Preview" title, borders, padding, and margin between blocks.
|
// Includes "Preview" title, borders, and margin between blocks.
|
||||||
const PREVIEW_PANE_FIXED_VERTICAL_SPACE = 7;
|
const PREVIEW_PANE_FIXED_VERTICAL_SPACE = 8;
|
||||||
const availableTerminalHeightCodeBlock = availableTerminalHeight
|
|
||||||
? Math.max(
|
// The right column doesn't need to ever be shorter than the left column.
|
||||||
Math.floor(
|
availableTerminalHeight = Math.max(
|
||||||
(availableTerminalHeight - PREVIEW_PANE_FIXED_VERTICAL_SPACE) / 2,
|
availableTerminalHeight,
|
||||||
),
|
totalLeftHandSideHeight,
|
||||||
2,
|
);
|
||||||
)
|
const availableTerminalHeightCodeBlock =
|
||||||
: undefined;
|
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 (
|
return (
|
||||||
<Box
|
<Box
|
||||||
borderStyle="round"
|
borderStyle="round"
|
||||||
borderColor={Colors.Gray}
|
borderColor={Colors.Gray}
|
||||||
flexDirection="row"
|
flexDirection="column"
|
||||||
padding={1}
|
paddingTop={includePadding ? 1 : 0}
|
||||||
|
paddingBottom={includePadding ? 1 : 0}
|
||||||
|
paddingLeft={1}
|
||||||
|
paddingRight={1}
|
||||||
width="100%"
|
width="100%"
|
||||||
>
|
>
|
||||||
|
<Box flexDirection="row">
|
||||||
{/* Left Column: Selection */}
|
{/* Left Column: Selection */}
|
||||||
<Box flexDirection="column" width="45%" paddingRight={2}>
|
<Box flexDirection="column" width="45%" paddingRight={2}>
|
||||||
<Text bold={focusedSection === 'theme'}>
|
<Text bold={currenFocusedSection === 'theme'} wrap="truncate">
|
||||||
{focusedSection === 'theme' ? '> ' : ' '}Select Theme{' '}
|
{currenFocusedSection === 'theme' ? '> ' : ' '}Select Theme{' '}
|
||||||
<Text color={Colors.Gray}>{otherScopeModifiedMessage}</Text>
|
<Text color={Colors.Gray}>{otherScopeModifiedMessage}</Text>
|
||||||
</Text>
|
</Text>
|
||||||
<RadioButtonSelect
|
<RadioButtonSelect
|
||||||
|
@ -146,28 +189,24 @@ export function ThemeDialog({
|
||||||
initialIndex={initialThemeIndex}
|
initialIndex={initialThemeIndex}
|
||||||
onSelect={handleThemeSelect}
|
onSelect={handleThemeSelect}
|
||||||
onHighlight={onHighlight}
|
onHighlight={onHighlight}
|
||||||
isFocused={focusedSection === 'theme'}
|
isFocused={currenFocusedSection === 'theme'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Scope Selection */}
|
{/* Scope Selection */}
|
||||||
|
{showScopeSelection && (
|
||||||
<Box marginTop={1} flexDirection="column">
|
<Box marginTop={1} flexDirection="column">
|
||||||
<Text bold={focusedSection === 'scope'}>
|
<Text bold={currenFocusedSection === 'scope'} wrap="truncate">
|
||||||
{focusedSection === 'scope' ? '> ' : ' '}Apply To
|
{currenFocusedSection === 'scope' ? '> ' : ' '}Apply To
|
||||||
</Text>
|
</Text>
|
||||||
<RadioButtonSelect
|
<RadioButtonSelect
|
||||||
items={scopeItems}
|
items={scopeItems}
|
||||||
initialIndex={0} // Default to User Settings
|
initialIndex={0} // Default to User Settings
|
||||||
onSelect={handleScopeSelect}
|
onSelect={handleScopeSelect}
|
||||||
onHighlight={handleScopeHighlight}
|
onHighlight={handleScopeHighlight}
|
||||||
isFocused={focusedSection === 'scope'}
|
isFocused={currenFocusedSection === 'scope'}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
)}
|
||||||
<Box marginTop={1}>
|
|
||||||
<Text color={Colors.Gray}>
|
|
||||||
(Use Enter to select, Tab to change focus)
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Right Column: Preview */}
|
{/* Right Column: Preview */}
|
||||||
|
@ -176,34 +215,44 @@ export function ThemeDialog({
|
||||||
<Box
|
<Box
|
||||||
borderStyle="single"
|
borderStyle="single"
|
||||||
borderColor={Colors.Gray}
|
borderColor={Colors.Gray}
|
||||||
padding={1}
|
paddingTop={includePadding ? 1 : 0}
|
||||||
|
paddingBottom={includePadding ? 1 : 0}
|
||||||
|
paddingLeft={1}
|
||||||
|
paddingRight={1}
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
>
|
>
|
||||||
{colorizeCode(
|
{colorizeCode(
|
||||||
`# function
|
`# function
|
||||||
def fibonacci(n):
|
-def fibonacci(n):
|
||||||
a, b = 0, 1
|
- a, b = 0, 1
|
||||||
for _ in range(n):
|
- for _ in range(n):
|
||||||
a, b = b, a + b
|
- a, b = b, a + b
|
||||||
return a`,
|
- return a`,
|
||||||
'python',
|
'python',
|
||||||
availableTerminalHeightCodeBlock,
|
codeBlockHeight,
|
||||||
colorizeCodeWidth,
|
colorizeCodeWidth,
|
||||||
)}
|
)}
|
||||||
<Box marginTop={1} />
|
<Box marginTop={1} />
|
||||||
<DiffRenderer
|
<DiffRenderer
|
||||||
diffContent={`--- a/old_file.txt
|
diffContent={`--- a/old_file.txt
|
||||||
+++ b/new_file.txt
|
-+++ b/new_file.txt
|
||||||
@@ -1,4 +1,5 @@
|
-@@ -1,4 +1,5 @@
|
||||||
This is a context line.
|
- This is a context line.
|
||||||
-This line was deleted.
|
--This line was deleted.
|
||||||
+This line was added.
|
-+This line was added.
|
||||||
`}
|
-`}
|
||||||
availableTerminalHeight={availableTerminalHeightCodeBlock}
|
availableTerminalHeight={diffHeight}
|
||||||
terminalWidth={colorizeCodeWidth}
|
terminalWidth={colorizeCodeWidth}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box marginTop={1}>
|
||||||
|
<Text color={Colors.Gray} wrap="truncate">
|
||||||
|
(Use Enter to select
|
||||||
|
{showScopeSelection ? ', Tab to change focus' : ''})
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text } from 'ink';
|
import { Text, Box } from 'ink';
|
||||||
import SelectInput, {
|
import SelectInput, {
|
||||||
type ItemProps as InkSelectItemProps,
|
type ItemProps as InkSelectItemProps,
|
||||||
type IndicatorProps as InkSelectIndicatorProps,
|
type IndicatorProps as InkSelectIndicatorProps,
|
||||||
|
@ -78,12 +78,11 @@ export function RadioButtonSelect<T>({
|
||||||
isSelected = false,
|
isSelected = false,
|
||||||
}: InkSelectIndicatorProps): React.JSX.Element {
|
}: InkSelectIndicatorProps): React.JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Box minWidth={2} flexShrink={0}>
|
||||||
color={isSelected ? Colors.AccentGreen : Colors.Foreground}
|
<Text color={isSelected ? Colors.AccentGreen : Colors.Foreground}>
|
||||||
wrap="truncate"
|
{isSelected ? '●' : '○'}
|
||||||
>
|
|
||||||
{isSelected ? '● ' : '○ '}
|
|
||||||
</Text>
|
</Text>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue