Welcome to Interactive Wizard Steps!
In the previous chapter, Wizard Orchestrator, we learned about the "Game Master" that controls the flow of our application. Now, we are going to look at the Scenes that the Game Master describes.
Imagine you are building a house. You wouldn't hire one person to do the plumbing, electrical, painting, and roofing all at the exact same moment.
If we wrote our CLI tool in one big file, we would have code for asking for a repository mixed in with code for checking API keys and code for showing success messages. It would be impossible to read.
We solve this by creating Step Components.
Think of each step as a single page in a setup assistant.
Every step in our wizard follows a simple contract. It receives data from the parent (Orchestrator) via Props, and it communicates back using Functions (Callbacks).
Let's look at CheckGitHubStep.tsx. This step doesn't ask the user for anything; it just tells them something is happening.
// CheckGitHubStep.tsx
import React from 'react';
import { Text } from 'ink';
export function CheckGitHubStep() {
// Just render text. No user input required here.
return <Text>Checking GitHub CLI installationβ¦</Text>;
}
Explanation: This is a "dumb" component. It just renders text. The Orchestrator shows this while it runs background checks (which we will cover in GitHub Infrastructure Logic).
Now let's look at ChooseRepoStep.tsx. This is where the user types in a repository name.
This component needs two things from the Orchestrator:
repoUrl: The text currently in the box.onRepoUrlChange: A function to call when the user types.// Define what this step needs
interface ChooseRepoStepProps {
repoUrl: string;
onRepoUrlChange: (value: string) => void;
onSubmit: () => void;
}
Here is how we render the input box using the TextInput component:
// Inside ChooseRepoStep component
<TextInput
value={repoUrl}
onChange={(value) => {
// Tell the Orchestrator the text changed
onRepoUrlChange(value);
}}
onSubmit={onSubmit} // Tell Orchestrator "We are done!"
placeholder="owner/repo"
/>
Explanation: The Step doesn't strictly control the state itself. It acts as a middleman. When you type 'A', it tells the Orchestrator "The user typed A". The Orchestrator updates the state, and the Step re-renders showing 'A'.
Let's visualize how a specific step (like choosing a repository) handles user interaction.
Our wizard handles different types of steps:
ChooseRepoStep): Uses a text cursor and accepts strings.InstallAppStep): Just waits for the user to press "Enter".ExistingWorkflowStep): Lets the user pick from a list (Update, Skip, Exit).
Let's look at how Confirmation works in InstallAppStep.tsx. It uses a custom hook for keybindings.
// InstallAppStep.tsx
import { useKeybinding } from '../../keybindings/useKeybinding.js';
export function InstallAppStep({ onSubmit }) {
// Listen specifically for the "Enter" key
useKeybinding("confirm:yes", onSubmit);
return (
<Box>
<Text>Press Enter once you've installed the app...</Text>
</Box>
);
}
Explanation: There is no text box here. We just listen for the "confirm:yes" signal (mapped to the Enter key). When detected, we run onSubmit, which tells the Orchestrator to proceed.
The final piece of the puzzle is giving feedback. The SuccessStep.tsx receives boolean flags to decide what to show.
// SuccessStep.tsx
if (props.skipWorkflow) {
return <Text>Your workflow file was kept unchanged.</Text>;
}
return (
<Box>
<Text color="success">β GitHub Actions workflow created!</Text>
<Text>1. A pre-filled PR page has been created</Text>
</Box>
);
Explanation: This logic is purely presentational. The Step doesn't calculate if the workflow was skipped; the Orchestrator passes that fact down as props.skipWorkflow. The Step just decides how to style it.
By isolating these steps, we make our code modular.
ChooseRepoStep.tsx.However, these steps are just the "Face" of the application. They don't actually talk to GitHub, and they don't know how to authenticate.
In this chapter, we learned:
props and report actions via callbacks.Now that we have our User Interface ready, let's learn about the heavy lifting happening in the background.
Next Chapter: GitHub Infrastructure Logic
Generated by Code IQ