Welcome to the LspRecommendation project! In this first chapter, we are going to look at the heart of our application: the LspRecommendationMenu.
Imagine you are building a smart code editor tool. When a user opens a file (like a .ts TypeScript file), you realize they don't have the language tools (LSP) installed to help them write code faster.
You want to help them, but you don't want to be rude and install things without asking. You need a way to:
The LspRecommendationMenu is the React component that acts as this polite assistant.
Let's say a user, Alice, opens script.py. Our system detects she is editing Python but lacks the Python LSP.
We want to show a screen that looks roughly like this:
LSP Plugin Recommendation
Plugin: Python-LSP
Triggered by: .py files
>
Would you like to install this LSP plugin?
[ Yes ] [ No ] [ Never ]
If Alice doesn't answer within 30 seconds, the menu should automatically close so it doesn't block her workflow.
This component is built using React and Ink (a library for building user interfaces in the terminal).
To use this menu, you simply "render" it like an HTML tag, passing in the details of the tool you want to recommend.
Here is how you would use the component in your code to ask about a TypeScript plugin:
<LspRecommendationMenu
pluginName="TypeScript-LSP"
fileExtension=".ts"
pluginDescription="Provides auto-complete for TS files"
onResponse={(answer) => {
console.log("User chose:", answer);
}}
/>
What happens here?
pluginName: The name of the tool we want to install.fileExtension: Why we are asking (because the user opened a .ts file).onResponse: A function that runs when the user makes a choice.Before looking at the code, let's visualize the "lifecycle" of this menu component using a diagram. This shows what happens from the moment the menu appears until it vanishes.
Let's break down the implementation of LspRecommendationMenu.tsx into small, manageable pieces.
First, we define what information this component accepts.
type Props = {
pluginName: string;
pluginDescription?: string; // The '?' means this is optional
fileExtension: string;
// This function handles the user's answer
onResponse: (response: 'yes' | 'no' | 'never' | 'disable') => void;
};
The component returns a structure that determines how it looks in the terminal. We wrap everything in a PermissionDialog.
return (
<PermissionDialog title="LSP Plugin Recommendation">
<Box flexDirection="column" paddingX={2} paddingY={1}>
<Box marginBottom={1}>
<Text dimColor>LSP provides code intelligence...</Text>
</Box>
{/* More text details go here... */}
</Box>
</PermissionDialog>
);
PermissionDialog component here. We will explore how that wrapper works in Terminal UI Layout.PermissionDialog is like the frame of a painting, and the code inside is the canvas where we paint our text.
We need to present the user with choices. We create an array of options and pass them to a Select component.
const options = [
{
label: <Text>Yes, install <Text bold>{pluginName}</Text></Text>,
value: 'yes'
},
{ label: 'No, not now', value: 'no' },
// ... other options like 'never' or 'disable'
];
label (what the user sees) and a value (what the code sees).When a user selects an option, we need to translate that into an action.
function onSelect(value: string): void {
switch (value) {
case 'yes':
onResponse('yes');
break;
case 'no':
onResponse('no');
break;
// ... handles other cases
}
}
value (like "yes") and calls the onResponse prop we defined earlier.Finally, we don't want this menu to hang around forever. We use a React "Effect" to set a timer.
const AUTO_DISMISS_MS = 30_000; // 30 seconds
React.useEffect(() => {
// Start a timer that defaults to 'no' if time runs out
const timeoutId = setTimeout(
ref => ref.current('no'),
AUTO_DISMISS_MS,
onResponseRef
);
return () => clearTimeout(timeoutId); // Cleanup
}, []);
The LspRecommendationMenu is the friendly face of our application. It combines layout, user input, and timing logic into a single package.
You learned:
Props) into the menu.Now that we understand the component as a whole, let's zoom in on exactly how we organize the visual elements on the screen.
Next Chapter: Terminal UI Layout
Generated by Code IQ