Window Size
What This Example Shows
This example demonstrates how to manually check the terminal window size whenever you need it. While Bubble Tea automatically tells you when the window gets resized, sometimes you want to ask "hey, how big is the window right now?" on demand.
The key here is tea.WindowSize() - it's a command you can use to actively request the current terminal dimensions instead of waiting for a resize event.
Understanding Window Size in Terminal Apps
Terminal apps need to know how much space they have to work with. Think of it like a website needing to know the browser window size - you want to layout your content to fit properly.
Bubble Tea normally handles this automatically. When someone resizes their terminal window, your app gets a tea.WindowSizeMsg without you having to ask for it. But what if you need to know the size at some other time, like when the user presses a specific key or when you're calculating layout?
This is super useful for responsive layouts, centering content, or any time you need to make decisions based on available screen space.
That's where manual querying comes in handy. You can trigger a size check whenever you want, not just when the window changes.
How It Works
Request the Size
When you want to know the current window dimensions, return the tea.WindowSize() command:
case tea.KeyMsg:
if msg.String() == "any key except quit keys" {
return m, tea.WindowSize() // Ask for current size
}Receive the Response
Bubble Tea will send you back a tea.WindowSizeMsg with the current dimensions:
case tea.WindowSizeMsg:
// Now we know the size!
return m, tea.Printf("%dx%d", msg.Width, msg.Height)Use the Information
In this example, we just print the dimensions, but you could use them for layout calculations, responsive design decisions, or anything else you need.
This example uses tea.Printf to print outside the normal view rendering cycle. This is great for one-off messages but not for your main UI content.
Code Breakdown
The model is super simple since we don't need to store any state:
type model struct{}
func main() {
p := tea.NewProgram(model{})
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
}
func (m model) Init() tea.Cmd {
return nil // No initial commands needed
}We're not tracking window size in the model because we're just querying it on demand.
The update function handles key presses and decides what to do:
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if s := msg.String(); s == "ctrl+c" || s == "q" || s == "esc" {
return m, tea.Quit // Exit on quit keys
}
return m, tea.WindowSize() // Any other key queries size
}
return m, nil
}Any key press (except quit keys) triggers a window size query.
When Bubble Tea responds with the size information:
case tea.WindowSizeMsg:
return m, tea.Printf("%dx%d", msg.Width, msg.Height)The tea.WindowSizeMsg contains Width and Height fields with the current terminal dimensions in characters (not pixels).
The view provides simple instructions:
func (m model) View() string {
return "When you're done press q to quit. Press any other key to query the window-size.\n"
}The actual size information gets printed via tea.Printf, which outputs directly to the terminal outside of the normal view rendering.
When You'd Use This
This manual querying is particularly useful when you need window dimensions for specific calculations or decisions that aren't tied to resize events. For example, you might want to center a dialog box when the user presses a key, or adjust column widths in a table based on current available space.
Most of the time, you'll rely on the automatic resize messages that Bubble Tea sends when the window changes. But having the ability to query on demand gives you more control over when and how you handle layout decisions.
Final Code
package main
import (
"log"
tea "github.com/charmbracelet/bubbletea"
)
func main() {
p := tea.NewProgram(model{})
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
}
type model struct{}
func (m model) Init() tea.Cmd {
return nil
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyMsg:
if s := msg.String(); s == "ctrl+c" || s == "q" || s == "esc" {
return m, tea.Quit
}
return m, tea.WindowSize()
case tea.WindowSizeMsg:
return m, tea.Printf("%dx%d", msg.Width, msg.Height)
}
return m, nil
}
func (m model) View() string {
s := "When you're done press q to quit. Press any other key to query the window-size.\n"
return s
}How is this guide?