Window Resizing
Relevant source files
The following files were used as context for generating this wiki page:
Window resizing in the Companion wizard project is the mechanism by which the terminal user interface (TUI) responds to changes in the terminal emulator's dimensions. It ensures that the wizard's layout, specifically the centering of questions and input fields, remains consistent and visually centered regardless of the user's window size.
This functionality is built using the Bubble Tea framework's message-passing architecture and Lip Gloss for layout styling. The system captures dimensions from the terminal and stores them within the application state to calculate the correct placement of UI elements during the rendering cycle.
Sources: main.go:88-92, README.md:1-12
Architecture and State Management
The application tracks the terminal's dimensions through the Main struct, which serves as the primary state container for the wizard. When the terminal is resized, the Bubble Tea framework sends a specific message type that the application must intercept and process to update its internal records.
State Variables
The Main struct maintains two integer fields dedicated to window dimensions:
width: Represents the current width of the terminal in characters.height: Represents the current height of the terminal in characters.
Sources: main.go:27-34
Data Flow for Window Updates
The following diagram illustrates how window size information flows from the Bubble Tea framework into the application state and finally to the rendering engine.
The application receives resize events and updates the internal state before the next UI render.
Sources: main.go:86-92, main.go:108-125
Event Handling
The Update function in main.go is responsible for handling the tea.WindowSizeMsg. This message is sent by the Bubble Tea runtime whenever the program starts (to provide initial dimensions) or whenever the user manually resizes their terminal window.
func (m Main) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
current := &m.questions[m.index]
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.width = msg.Width
m.height = msg.Height
// ... other cases
Sources: main.go:88-92
Handling Initial Load
Before the first tea.WindowSizeMsg is processed, m.width is initialized to 0. The View function includes a guard clause to prevent rendering the full UI until dimensions are known, displaying a "loading..." message instead.
Sources: main.go:116-118
Layout and Placement Logic
The project utilizes lipgloss.Place to dynamically position content based on the captured dimensions. This function uses the width and height stored in the Main struct to center the vertical stack of UI components.
Centering Mechanism
The UI is composed of a vertical join of the current question text and the rendered input field. This combined block is then placed in the center of the terminal.
| Parameter | Value | Description |
|---|---|---|
| Width | m.width | Uses the stored window width for horizontal bounds. |
| Height | m.height | Uses the stored window height for vertical bounds. |
| H-Alignment | lipgloss.Center | Horizontally centers the content block. |
| V-Alignment | lipgloss.Center | Vertically centers the content block. |
Sources: main.go:120-128
Sequence of Resize and Render
The following sequence diagram shows the interaction between the Bubble Tea runtime and the application model during a resize event.
The sequence ensures that the layout engine always uses the most recent terminal dimensions.
Sources: main.go:86-128
Style and Border Constraints
While the window resizes, the input fields maintain their own internal styling constraints. For instance, the default style for an input field includes a fixed width and specific padding, which resides within the flexible container created by the window resizing logic.
func DefaultStyles() *Styles {
s := new(Styles)
s.BorderColor = lipgloss.Color("36")
s.InputField = lipgloss.NewStyle().
BorderForeground(s.BorderColor).
BorderStyle(lipgloss.NormalBorder()).
Padding(1).
Width(80)
return s
}
Sources: main.go:19-25
Conclusion
Window resizing is a critical component of the Companion wizard, enabling a responsive TUI experience. By capturing tea.WindowSizeMsg and applying those dimensions through lipgloss.Place, the application ensures that questions and input fields remain perfectly centered regardless of how the user manipulates their terminal window.