Welcome to the final chapter of our Help System tutorial!
In the previous chapter, Command Catalog Renderer, we built a smart component that organizes and displays our commands. It knows what to display, but it doesn't know how much space it has.
Terminals are elastic. Users can maximize them on a 4K monitor or squish them into a tiny corner of a laptop screen. If our help window is hard-coded to be 50 rows tall, but the user's terminal is only 20 rows tall, the application will crash or look broken.
In this chapter, we will implement Responsive Terminal Layout. We will give our Help component the ability to measure its environment and adapt its shape instantly.
Websites use CSS Media Queries to adapt to mobile phones vs. desktops. Terminal apps need something similar.
/help, they want to see a long list of commands using 50% of the screen./help, the list must shrink to fit, enabling a scrollbar instead of overflowing.To solve this, we rely on two "Sensors" (Hooks):
useTerminalSize): A hook that constantly reports the width (columns) and height (rows) of the terminal.useIsInsideModal): A hook that tells the component, "Hey, you are currently running inside a floating window, so behave accordingly."
We are working in the main container file, HelpV2.tsx. We need to calculate boundaries to pass down to our children.
First, we need to know the raw dimensions of the user's terminal. We use the useTerminalSize hook.
// HelpV2.tsx
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
export function HelpV2({ onClose, commands }: Props) {
// 1. Get current dimensions
const { rows, columns } = useTerminalSize();
// ...
}
Explanation:
rows: The height of the terminal (e.g., 40 lines).columns: The width of the terminal (e.g., 120 characters).We rarely want a Help dialog to cover 100% of the screen. Users usually want to see the error message or code they were working on behind the help window.
We set a rule: The Help window should never be taller than 50% of the screen.
// Calculate 50% of the screen height
const maxHeight = Math.floor(rows / 2);
Explanation:
rows is 40, maxHeight becomes 20.Math.floor ensures we don't end up with partial rows (like 20.5 lines), which is impossible in a terminal.Sometimes, our Help component is placed inside a pre-existing "Modal" layout handled by a different part of the app. If that's the case, the parent decides the height, not us.
import { useIsInsideModal } from '../../context/modalContext.js';
// Are we inside a managed modal?
const insideModal = useIsInsideModal();
Explanation:
insideModal is a boolean (true or false).true, we should relax our strict height rules and let the Flexbox layout handle the sizing.
Now we use a ternary operator (an if/else in one line) to decide what height to apply to our main container box.
// If in a modal, let Flexbox handle it (undefined).
// Otherwise, enforce our calculated limit.
const activeHeight = insideModal ? undefined : maxHeight;
return (
<Box flexDirection="column" height={activeHeight}>
{/* Content ... */}
</Box>
);
Explanation:
Remember the Commands component we built in Chapter 4? It needs to know these limits so it knows when to start truncating text or adding scrollbars.
<Commands
commands={builtinCommands}
maxHeight={maxHeight}
columns={columns}
// ... other props
/>
Explanation:
HelpV2) sets the outer frame, the Content (Commands) needs the math to calculate how many items to show in the list (visibleOptionCount).What actually happens when a user resizes their window?
Let's look at the actual code in HelpV2.tsx that ties this all together.
// HelpV2.tsx
export function HelpV2(props) {
// 1. The Sensors
const { rows, columns } = useTerminalSize();
const insideModal = useIsInsideModal();
// 2. The Calculation
const maxHeight = Math.floor(rows / 2);
// ... (Tab logic from Chapter 3) ...
// 3. The Decision
// If we are in a modal, we don't set a fixed height.
// If we are standalone, we cap it at maxHeight.
const containerHeight = insideModal ? undefined : maxHeight;
return (
<Box flexDirection="column" height={containerHeight}>
{/* The UI Elements */}
</Box>
);
}
This simple logic ensures that:
<Commands> component detects the smaller maxHeight and reduces the number of visible items (e.g., showing 5 items instead of 10), allowing the user to scroll.In this final chapter, we learned how to make our TUI (Terminal User Interface) Responsive.
We learned:
useTerminalSize to get the current window dimensions.maxHeight (50% of the screen) so we don't overwhelm the user.useIsInsideModal to adapt our layout strategy based on where the component is rendered.Commands so they can render lists intelligently.Congratulations! You have walked through the entire architecture of the HelpV2 system.
You now understand how to build a professional, robust, and user-friendly help interface for a terminal application. Happy coding!
Generated by Code IQ