Files
gh-human-frontier-labs-inc-…/references/design-patterns.md
2025-11-29 18:47:30 +08:00

215 lines
3.6 KiB
Markdown

# Bubble Tea Design Patterns
Common architectural patterns for TUI development.
## Pattern 1: Single-View Application
**When**: Simple, focused TUIs with one main view
**Components**: 1-3 components, single model struct
**Complexity**: Low
```go
type model struct {
mainComponent component.Model
ready bool
}
```
## Pattern 2: Multi-View State Machine
**When**: Multiple distinct screens (setup, main, done)
**Components**: State enum + view-specific components
**Complexity**: Medium
```go
type view int
const (
setupView view = iota
mainView
doneView
)
type model struct {
currentView view
// Components for each view
}
```
## Pattern 3: Composable Views
**When**: Complex UIs with reusable sub-components
**Pattern**: Embed multiple bubble models
**Example**: Dashboard with multiple panels
```go
type model struct {
panel1 Panel1Model
panel2 Panel2Model
panel3 Panel3Model
}
// Each panel is itself a Bubble Tea model
```
## Pattern 4: Master-Detail
**When**: Selection in one pane affects display in another
**Example**: File list + preview, Email list + content
**Layout**: Two-pane or three-pane
```go
type model struct {
list list.Model
detail viewport.Model
selectedItem int
}
```
## Pattern 5: Form Flow
**When**: Multi-step data collection
**Pattern**: Array of inputs + focus management
**Example**: Configuration wizard
```go
type model struct {
inputs []textinput.Model
focusIndex int
step int
}
```
## Pattern 6: Progress Tracker
**When**: Long-running sequential operations
**Pattern**: Queue + progress per item
**Example**: Installation, download manager
```go
type model struct {
items []Item
currentIndex int
progress progress.Model
spinner spinner.Model
}
```
## Layout Patterns
### Vertical Stack
```go
lipgloss.JoinVertical(lipgloss.Left,
header,
content,
footer,
)
```
### Horizontal Panels
```go
lipgloss.JoinHorizontal(lipgloss.Top,
leftPanel,
separator,
rightPanel,
)
```
### Three-Column (File Manager Style)
```go
lipgloss.JoinHorizontal(lipgloss.Top,
parentDir, // 25% width
currentDir, // 35% width
preview, // 40% width
)
```
## Message Passing Patterns
### Custom Messages
```go
type myCustomMsg struct {
data string
}
func doSomethingCmd() tea.Msg {
return myCustomMsg{data: "result"}
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case myCustomMsg:
// Handle custom message
}
}
```
### Async Operations
```go
func fetchDataCmd() tea.Cmd {
return func() tea.Msg {
// Do async work
data := fetchFromAPI()
return dataFetchedMsg{data}
}
}
```
## Error Handling Pattern
```go
type errMsg struct{ err error }
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case errMsg:
m.err = msg.err
m.errVisible = true
return m, nil
}
}
```
## Keyboard Navigation Pattern
```go
case tea.KeyMsg:
switch msg.String() {
case "up", "k":
m.cursor--
case "down", "j":
m.cursor++
case "enter":
m.selectCurrent()
case "q", "ctrl+c":
return m, tea.Quit
}
```
## Responsive Layout Pattern
```go
case tea.WindowSizeMsg:
m.width = msg.Width
m.height = msg.Height
// Update component dimensions
m.viewport.Width = msg.Width
m.viewport.Height = msg.Height - 5 // Reserve space for header/footer
```
## Help Overlay Pattern
```go
type model struct {
showHelp bool
help help.Model
}
func (m model) View() string {
if m.showHelp {
return m.help.View()
}
return m.mainView()
}
```