### Run Button Click Example
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/buttons/README.md
Execute the main Go program to run the button click example. This will allow you to interact with buttons using your mouse.
```bash
go run main.go
```
--------------------------------
### Install GolangCI-Lint in Pony
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Install the golangci-lint tool using the 'task lint:install' command.
```bash
task lint:install
```
--------------------------------
### Basic Pony TUI Example
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
A simple 'Hello, World!' example demonstrating the basic structure of a Pony template and its rendering. It uses a generic interface{} for data, suitable for simple templates.
```go
package main
import (
"fmt"
"github.com/charmbracelet/x/pony"
)
func main() {
const tmpl = `
Hello, World!Welcome to pony!
`
t := pony.MustParse[interface{}](tmpl)
output := t.Render(nil, 80, 24)
fmt.Print(output)
}
```
--------------------------------
### Logic and Behavior Test Example
Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md
Demonstrates standard Go testing assertions for verifying logic and behavior, such as layout calculations. Use `t.Errorf` for failures.
```go
func TestLayout(t *testing.T) {
size := elem.Layout(constraints)
if size.Width != expected {
t.Errorf("got %d, want %d", size.Width, expected)
}
}
```
--------------------------------
### Install pony Package
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Use this command to add the pony package to your Go project.
```bash
go get github.com/charmbracelet/x/pony
```
--------------------------------
### Render Image in Terminal with Mosaic
Source: https://github.com/charmbracelet/x/blob/main/mosaic/README.md
Use this example to load an image, initialize a Mosaic renderer with specified dimensions, and render the image to the terminal. Ensure the image file exists at the specified path.
```go
package main
import (
"fmt"
"image"
"image/jpeg"
"os"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/x/mosaic"
)
func main() {
dogImg, err := loadImage("./pekinas.jpg")
if err != nil {
fmt.Print(err)
os.Exit(1)
}
m := mosaic.New().Width(80).Height(40)
fmt.Println(lipgloss.JoinVertical(lipgloss.Right, lipgloss.JoinHorizontal(lipgloss.Center, m.Render(dogImg))))
}
func loadImage(path string) (image.Image, error) {
f, err := os.Open(path)
defer f.Close()
if err != nil {
return nil, err
}
return jpeg.Decode(f)
}
```
--------------------------------
### Bubble Tea Integration Example in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Integrate Pony components with Bubble Tea by defining a model that manages state, handles messages (like window size and key presses), and renders the UI. Imports for Bubble Tea and Pony are required.
```go
import (
tea "charm.land/bubbletea/v2"
"github.com/charmbracelet/x/pony"
)
type ViewData struct {
Count int
}
type model struct {
template *pony.Template[ViewData]
count int
width int
height int
}
func (m model) Init() tea.Cmd {
return tea.RequestWindowSize
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.width = msg.Width
m.height = msg.Height
case tea.KeyPressMsg:
if msg.String() == "space" {
m.count++
}
}
return m, nil
}
func (m model) View() tea.View {
data := ViewData{Count: m.count}
output := m.template.Render(data, m.width, m.height)
return tea.NewView(output)
}
```
--------------------------------
### Golden File Test Example
Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md
Compares the rendered output of a template against a golden file. The golden file is automatically generated or updated using the `-update` flag.
```go
func TestMyRender(t *testing.T) {
output := myTemplate.Render(data, 80, 24)
golden.RequireEqual(t, output) // Compares against testdata/TestMyRender.golden
}
```
--------------------------------
### Get Component from Registry
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Retrieves a registered component factory by its name.
```go
pony.GetComponent(name)
```
--------------------------------
### Button Click Example Architecture
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/buttons/README.md
Illustrates the architecture for handling button clicks using Bubble Tea's View callback. The View function renders elements and returns a callback that performs hit testing on mouse events, emitting custom messages with element IDs to the Update function.
```text
View() renders -> returns (screen, boundsMap)
-> creates View with callback that captures boundsMap
-> callback does hit testing on mouse events
-> returns Cmd with element ID
Update() receives element ID message
-> updates model based on which button was clicked
```
--------------------------------
### Get All Registered Components
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Returns a map of all currently registered component names and their factories.
```go
pony.RegisteredComponents()
```
--------------------------------
### Utilize Props Helper Type for Property Access
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Use the Props map with helper methods like Get, GetOr, GetInt, and GetBool for convenient property access and parsing.
```go
type Props map[string]string
props.Get("key") // Get value (empty if missing)
props.GetOr("key", "def") // Get with default
props.GetInt("key", 10) // Parse int with default
props.GetBool("key") // Parse bool (default false)
```
--------------------------------
### Add Template Function in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
To add a new template function, modify the `defaultTemplateFuncs` in `template.go`. This example shows how to add an `upper` function and a custom `myFunc`.
```go
func defaultTemplateFuncs() template.FuncMap {
return template.FuncMap{
"upper": strings.ToUpper,
"myFunc": func(arg string) string { ... },
}
}
```
--------------------------------
### BoundsMap API Usage in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Utilize the BoundsMap API to perform hit testing at specific coordinates, retrieve elements by their IDs, get bounds information, or list all elements with their bounds.
```go
// Hit test - find element at coordinates
// Prefers elements with explicit IDs over auto-generated ones
elem := boundsMap.HitTest(x, y) // Returns Element or nil
// Get element by ID
elem, ok := boundsMap.GetByID("button-id")
// Get bounds for element ID
bounds, ok := boundsMap.GetBounds("button-id")
// Get all elements with bounds
elements := boundsMap.AllElements() // []ElementWithBounds
```
--------------------------------
### Request Initial Window Size in Bubble Tea Init
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/bubbletea/README.md
Use `tea.RequestWindowSize` in the Init function to prompt Bubble Tea to send the initial window dimensions to the application.
```go
func (m model) Init() tea.Cmd {
return tea.RequestWindowSize
}
```
--------------------------------
### Creating and Registering Custom Components
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/README.md
Illustrates how to define and register a custom component using pony primitives. Custom components can be composed from existing elements and styled using helper methods.
```go
func NewMyComponent(props Props, children []Element) Element {
return pony.NewBox(
pony.NewVStack(children...),
).WithBorder("rounded").WithPadding(1)
}
pony.Register("mycomp", NewMyComponent)
```
--------------------------------
### Apply Text Styling (New Way)
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Demonstrates the modern, SwiftUI-style approach to applying text styles like foreground color, background color, bold, italic, and underline.
```go
// New way (SwiftUI-style)
text := pony.NewText("Hello").
ForegroundColor(pony.Hex("#FF5555")).
BackgroundColor(pony.RGB(40, 42, 54)).
Bold().
Italic().
Underline()
```
--------------------------------
### Configure Box and Text Elements with Fluent API
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Use method chaining for configuring elements like Box and Text. Ensure all elements use the fluent API pattern for consistent configuration.
```go
box := NewBox(child).
WithBorder("rounded").
WithPadding(2).
WithMargin(1)
text := NewText("Hello").
WithStyle(style).
WithAlignment"center")
```
--------------------------------
### Rendering to Screen Buffer
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Templates render to a `uv.ScreenBuffer` which can then be converted to a string for output. `RenderWithBounds` provides the screen buffer and a `BoundsMap`.
```go
scr, boundsMap := tmpl.RenderWithBounds(data, slots, width, height)
output := scr.Render() // Convert to string
```
--------------------------------
### Create Basic Text Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Constructs a new text element with specified content.
```go
pony.NewText(content)
```
--------------------------------
### Render Pony Template with Data in Bubble Tea View
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/bubbletea/README.md
In the View function, prepare the data for the template and use `RenderToSize` to generate the output based on the current window dimensions. Return the rendered output as a Bubble Tea View.
```go
func (m model) View() tea.View {
// Prepare data for template
data := map[string]interface{}{
"Count": m.count,
"Items": m.items,
}
// Render pony with window size
output := m.template.RenderToSize(data, m.width, m.height)
// Return as Bubble Tea View
return tea.NewView(output)
}
```
--------------------------------
### Create Panel Layout
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Constructs a panel layout with a child element, border style, and padding.
```go
// Basic layouts
pony.Panel(child, border, padding)
```
--------------------------------
### Render Template
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Shows how to render a parsed Pony template with provided data, slots, and dimensions.
```go
// Render
output := tmpl.Render(data, width, height)
output := tmpl.RenderWithSlots(data, slots, width, height)
```
--------------------------------
### Fluent API for Button Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Illustrates configuring a button's appearance and behavior, including its border, padding, custom style, width, and setting a unique ID.
```go
button := pony.NewButton("Click Me").
Border("rounded").
Padding(1).
Style(style).
Width(pony.NewFixedConstraint(20))
button.SetID("my-button")
```
--------------------------------
### List Available Tasks in Pony
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
List all available tasks by running 'task' without any arguments.
```bash
task
```
--------------------------------
### Template Parsing and Rendering
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Demonstrates how to parse markup into a template, render it with data, and render it with slots and bounds for mouse event handling.
```APIDOC
## Template Parsing and Rendering
### Description
Parse markup into a template with type safety, render it with data, or render it with slots and bounds for mouse event handling.
### Parse with Type Safety
```go
// Parse with type safety
tmpl, err := pony.Parse[YourDataType](markup)
tmpl := pony.MustParse[YourDataType](markup)
```
### Render
```go
// Render
output := tmpl.Render(data, width, height)
output := tmpl.RenderWithSlots(data, slots, width, height)
```
### Render with Bounds for Mouse Handling
```go
// Render with bounds for mouse handling
scr, boundsMap := tmpl.RenderWithBounds(data, slots, width, height)
```
```
--------------------------------
### Handle Mouse Clicks with Bounds Tracking in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Implement mouse click handling by rendering with bounds, enabling mouse events, and using a callback to hit test clicked elements. This allows for stateless interaction handling.
```go
type buttonClickMsg string
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case buttonClickMsg:
switch msg {
case "submit-btn":
return m, m.submitForm()
case "cancel-btn":
return m, tea.Quit
}
}
return m, nil
}
func (m model) View() tea.View {
data := ViewData{...}
// Render and get bounds map
scr, boundsMap := m.template.RenderWithBounds(data, nil, m.width, m.height)
view := tea.NewView(scr.Render())
view.MouseMode = tea.MouseModeAllMotion // Enable mouse events
// Callback captures boundsMap - no model mutation!
view.Callback = func(msg tea.Msg) tea.Cmd {
if click, ok := msg.(tea.MouseClickMsg); ok {
mouse := click.Mouse()
// Find which element was clicked
if elem := boundsMap.HitTest(mouse.X, mouse.Y); elem != nil {
return func() tea.Msg {
return buttonClickMsg(elem.ID())
}
}
}
return nil
}
return view
}
```
--------------------------------
### Render Template with Bounds for Mouse Handling
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Renders a Pony template and returns the screen output along with a BoundsMap, which is essential for implementing mouse event handling like hover detection.
```go
// Render with bounds for mouse handling
scr, boundsMap := tmpl.RenderWithBounds(data, slots, width, height)
```
--------------------------------
### Create Button Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Creates a button element with specified text.
```go
pony.NewButton(text)
```
--------------------------------
### Fluent API for Flex Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Demonstrates configuring a flex item's properties such as grow, shrink, and basis within a flex layout.
```go
flex := pony.NewFlex(child).
Grow(1).
Shrink(0).
Basis(20)
```
--------------------------------
### Create Overlay Layout
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Generates an overlay layout using a ZStack with default alignment, suitable for layering elements.
```go
// Advanced layouts
pony.Overlay(children...)
```
--------------------------------
### Fluent API for Text Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Shows how to apply various text styling options like foreground color, bold, italic, and alignment using a fluent API.
```go
text := pony.NewText("Hello").
ForegroundColor(pony.Hex("#FF5555")).
Bold().
Italic().
Alignment(pony.AlignmentCenter).
Wrap(true)
```
--------------------------------
### Create Section Layout
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Creates a section layout with a header, header color, and child elements.
```go
pony.Section(header, headerColor, children...)
```
--------------------------------
### Fluent API for Element Configuration
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Illustrates the use of the fluent API for configuring element properties like borders, padding, margins, and dimensions.
```APIDOC
## Fluent API
### Description
Chainable methods for configuring element properties.
### Example: Box Element
```go
box := pony.NewBox(child).
Border("rounded").
Padding(2).
Margin(1).
MarginTop(2).
Width(pony.NewFixedConstraint(50)).
BorderColor(pony.Hex("#00FFFF"))
```
### Example: Text Element
```go
text := pony.NewText("Hello").
ForegroundColor(pony.Hex("#FF5555")).
Bold().
Italic().
Alignment(pony.AlignmentCenter).
Wrap(true)
```
### Example: Button Element
```go
button := pony.NewButton("Click Me").
Border("rounded").
Padding(1).
Style(style).
Width(pony.NewFixedConstraint(20))
button.SetID("my-button")
```
### Example: Flex Element
```go
flex := pony.NewFlex(child).
Grow(1).
Shrink(0).
Basis(20)
```
### Example: Positioned Element
```go
positioned := pony.NewPositioned(child, 10, 5).
Right(2).
Bottom(1)
```
```
--------------------------------
### Fluent API for Box Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Demonstrates chaining methods on a Box element for configuring its border, padding, margin, and width.
```go
box := pony.NewBox(child).
Border("rounded").
Padding(2).
Margin(1).
MarginTop(2).
Width(pony.NewFixedConstraint(50)).
BorderColor(pony.Hex("#00FFFF"))
```
--------------------------------
### Run All Tests in Pony
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Execute all tests using the 'task test' command or standard Go tooling. For verbose output, use 'go test -v ./...'.
```bash
task test
go test ./...
go test -v ./...
```
--------------------------------
### Create Panel with Margin Layout
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Creates a panel layout that includes a child, border, padding, and an additional margin.
```go
pony.PanelWithMargin(child, border, padding, margin)
```
--------------------------------
### Stateful Component Implementation
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/README.md
Demonstrates the structure of a stateful component in pony, including its `Update` and `Render` methods. State is managed within the component, and its output can be rendered into templates using slots.
```go
type MyComp struct {
state string
}
func (c *MyComp) Update(msg tea.Msg) { /* handle events */ }
func (c *MyComp) Render() pony.Element {
return pony.NewText(c.state)
}
// In template:
// In View: slots["comp"] = m.comp.Render()
```
--------------------------------
### Build Style with API
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Construct styles programmatically using the pony.NewStyle() API. This allows for dynamic styling in code.
```go
style := pony.NewStyle().
Fg(pony.Hex("#FF5555")),
Bg(pony.RGB(40, 42, 54)),
Bold().
Italic().
Build()
```
--------------------------------
### Create Card Layout
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Constructs a card layout with a title, title color, border color, and multiple child elements.
```go
pony.Card(title, titleColor, borderColor, children...)
```
--------------------------------
### Run All Pony Tests
Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md
Execute all tests within the Pony project using the standard Go testing tool.
```bash
go test ./...
```
--------------------------------
### Type-Safe Template Rendering
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/README.md
Demonstrates how to use type-safe templates with custom data structures for rendering dynamic content. Ensure the terminal size is passed to the Render function.
```go
type ViewData struct {
Title string
Count int
}
tmpl := pony.MustParse[ViewData](markup)
output := tmpl.Render(ViewData{Title: "App", Count: 42}, 80, 24)
```
--------------------------------
### Implement Table-Driven Tests with Subtests
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Organize tests using table-driven approaches and subtests for clarity and maintainability. Test both logic (Layout) and rendering (Draw/golden).
```go
func TestElement(t *testing.T) {
tests := []struct {
name string
// ... fields
}{
{name: "case1", ...},
{name: "case2", ...},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// test logic
})
}
}
```
--------------------------------
### Render Template with Slots in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Render a template by providing a map of slot names to Pony elements. This allows dynamic content to be injected into predefined template areas.
```go
func (m model) View() tea.View {
slots := map[string]pony.Element{
"input": m.inputComp.Render(),
}
output := m.template.RenderWithSlots(data, slots, m.width, m.height)
return tea.NewView(output)
}
```
--------------------------------
### Full UI Structure in Markup
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling-markup/README.md
Define the complete UI layout using XML markup, including headers, scrollable content, and instructional text. This demonstrates a declarative approach to UI building.
```xml
Title
{{ range .Items }}
{{ end }}
Press q to quit
```
--------------------------------
### Parse and Render Pony Template
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Demonstrates parsing a Pony template with a specific data structure and rendering it. Ensure the ViewData struct matches the template's expected data.
```go
type ViewData struct {
Title string
Count int
}
const tmpl = `
{{ .Title }}Count: {{ .Count }}
`
tmpl := pony.MustParse[ViewData](tmpl)
output := tmpl.Render(ViewData{Title: "My App", Count: 42}, 80, 24)
```
--------------------------------
### Fluent API for Positioned Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Shows how to configure a positioned element's offset from the right and bottom edges.
```go
positioned := pony.NewPositioned(child, 10, 5).
Right(2).
Bottom(1)
```
--------------------------------
### Bubble Tea Integration with Pony
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/README.md
Shows a minimal integration pattern for using pony templates within a Bubble Tea application. Handles window resize events to update the rendering dimensions.
```go
type model struct {
template *pony.Template[ViewData]
width int
height int
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.width, m.height = msg.Width, msg.Height
}
return m, nil
}
func (m model) View() tea.View {
output := m.template.Render(data, m.width, m.height)
return tea.NewView(output)
```
--------------------------------
### Go Template Loops
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Iterate over data collections and render elements for each item using Go's `range` template syntax.
```xml
{{ range .Items }}
• {{ . }}
{{ end }}
```
--------------------------------
### Implement Draw() Method with SetBounds()
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Always call SetBounds() at the beginning of the Draw() method. This is required for hit testing and proper rendering.
```go
func (e *MyElement) Draw(scr uv.Screen, area uv.Rectangle) {
e.SetBounds(area) // REQUIRED for hit testing
// ... rest of drawing logic
}
```
--------------------------------
### Register a Functional Component
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Register a simple functional component using pony.Register. This approach is suitable for less complex components.
```go
pony.Register("card", func(props pony.Props, children []pony.Element) pony.Element {
return pony.NewBox(
pony.NewVStack(children...),
).Border("rounded").Padding(1)
})
```
--------------------------------
### Model with Stateful Components in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/stateful/README.md
Defines the main model structure holding a Pony template and instances of the stateful username and email input components.
```go
type model struct {
template *pony.Template[ViewData]
username *Input // Stateful component
email *Input // Stateful component
focused string
}
```
--------------------------------
### Register Custom Component in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling-markup/README.md
Define and register a custom component in Go to be used within markup. Ensure the registration function is called during initialization.
```go
type ListItem struct {
pony.BaseElement
Text string
Selected bool
}
func NewListItemFromProps(props pony.Props, children []pony.Element) pony.Element {
text := props.Get("text")
selected := props.Get("selected") == "true"
return NewListItem(text, selected)
}
func init() {
pony.Register("listitem", NewListItemFromProps)
}
```
--------------------------------
### Run Linter in Pony
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Execute the linter using 'task lint'. For auto-fixing issues, use 'task lint:fix'.
```bash
task lint
task lint:fix
```
--------------------------------
### Fluent API for Text Styling
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Style text elements programmatically using a fluent API in Go. This allows for chaining style modifications.
```go
text := pony.NewText("Hello").
ForegroundColor(pony.Hex("#FF5555")).
BackgroundColor(pony.RGB(40, 42, 54)).
Bold().
Italic().
Alignment(pony.AlignmentCenter)
```
--------------------------------
### Define and Register a Type-Based Component
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Implement a type-based component for more control, embedding BaseElement and defining Draw, Layout, and Children methods. Register the component using pony.Register.
```go
type Card struct {
BaseElement // Required
Title string
Content []Element
}
func NewCard(props Props, children []Element) Element {
return &Card{
Title: props.Get("title"),
Content: children,
}
}
func (c *Card) Draw(scr uv.Screen, area uv.Rectangle) {
c.SetBounds(area) // Required
// Build composed structure and draw
card := NewBox(NewVStack(c.Content...)).Border("rounded")
card.Draw(scr, area)
}
func (c *Card) Layout(constraints Constraints) Size {
// Delegate to composed structure
card := NewBox(NewVStack(c.Content...)).Border("rounded")
return card.Layout(constraints)
}
func (c *Card) Children() []Element {
return c.Content
}
// Register
pony.Register("card", NewCard)
```
--------------------------------
### Store Pony Template in Bubble Tea Model
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/bubbletea/README.md
Initialize the Pony template within your Bubble Tea model. Ensure the template is parsed once during initialization for efficiency.
```go
type model struct {
template *pony.Template
// ... your app state
}
func initialModel() model {
return model{
template: pony.MustParse(markup),
}
}
```
--------------------------------
### Run Tests with Coverage in Pony
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Generate test coverage reports using the 'task test:coverage' command.
```bash
task test:coverage
```
--------------------------------
### View Fills Slots with Rendered Components in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/stateful/README.md
Implements the View method to render the template with slots filled by the rendered output of the username and email components. It passes ViewData and component elements to the template.
```go
func (m model) View() tea.View {
data := ViewData{Title: "My Form"}
slots := map[string]pony.Element{
"username": m.username.Render(), // Render to Element!
"email": m.email.Render(),
}
output := m.template.RenderWithSlots(data, slots, m.width, m.height)
return tea.NewView(output)
}
```
--------------------------------
### Create Z-Stack Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Constructs a z-stack element that layers its children on top of each other.
```go
pony.NewZStack(children...)
```
--------------------------------
### Run Pony Tests with Coverage
Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md
Execute tests and generate a coverage report to assess test coverage.
```bash
go test -cover
```
--------------------------------
### Go Template Conditionals
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Conditionally render UI elements based on data properties using Go's `if/else` template syntax.
```xml
{{ if .IsOnline }}
● Online
{{ else }}
○ Offline
{{ end }}
```
--------------------------------
### Regenerate Golden Files
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Use the `go test -update ./...` command to regenerate all golden files. This command should be run whenever rendering output changes intentionally.
```bash
go test -update ./...
```
--------------------------------
### Register Custom Component Type
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Define and register a custom component by creating a struct that implements the necessary Pony interfaces. This allows for state management and custom drawing/layout logic.
```go
// Or create a custom type for more control
type Card struct {
pony.BaseElement // Required for ID and bounds tracking
Title string
Color string
Content []pony.Element
}
func NewCard(props pony.Props, children []pony.Element) pony.Element {
return &Card{
Title: props.Get("title"),
Color: props.GetOr("color", "blue"),
Content: children,
}
}
func (c *Card) Draw(scr uv.Screen, area uv.Rectangle) {
c.SetBounds(area) // Track bounds for mouse interaction
// Build composed structure
themeColor := pony.Hex("#00FFFF")
card := pony.NewBox(
pony.NewVStack(
pony.NewText(c.Title).ForegroundColor(themeColor).Bold(),
pony.NewDivider(),
pony.NewVStack(c.Content...),
),
).Border("rounded").BorderColor(themeColor).Padding(1)
card.Draw(scr, area)
}
func (c *Card) Layout(constraints pony.Constraints) pony.Size {
// Delegate to composed structure
themeColor := pony.Hex("#00FFFF")
card := pony.NewBox(
pony.NewVStack(
pony.NewText(c.Title).ForegroundColor(themeColor).Bold(),
pony.NewDivider(),
pony.NewVStack(c.Content...),
),
).Border("rounded").BorderColor(themeColor).Padding(1)
return card.Layout(constraints)
}
func (c *Card) Children() []pony.Element {
return c.Content
}
// Register it
pony.Register("card", NewCard)
```
--------------------------------
### Handle Window Resize in Bubble Tea Update
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/bubbletea/README.md
Update the model's width and height properties when a `tea.WindowSizeMsg` is received. This ensures that subsequent renders use the correct dimensions.
```go
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.width = msg.Width
m.height = msg.Height
}
return m, nil
}
```
--------------------------------
### Using Slots for Dynamic Content
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Slots enable dynamic content injection into templates. Define a slot in the XML markup and provide the corresponding `Element` in the `slots` map during rendering.
```xml
```
```go
slots := map[string]Element{
"input": myInputComponent.Render(),
}
output := tmpl.RenderWithSlots(data, slots, w, h)
```
--------------------------------
### Format Code in Pony
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Format code using 'task fmt', which applies gofumpt and goimports.
```bash
task fmt
```
--------------------------------
### Flexible Layout with Flex
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Employ the flex component within an HStack to allow content to grow and fill available space.
```xml
Fixed sidebarMain content (grows)
```
--------------------------------
### Clean Build Artifacts in Pony
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Clean build artifacts and test cache using 'task clean'.
```bash
task clean
```
--------------------------------
### Element Constructors
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Provides a list of constructors for creating various UI elements within the Pony templating engine.
```APIDOC
## Element Constructors
### Description
Constructors for creating various UI elements.
### Constructors
```go
p পার্থক্য.NewText(content)
p পার্থক্য.NewBox(child)
p পার্থক্য.NewVStack(children...)
p পার্থক্য.NewHStack(children...)
p পার্থক্য.NewZStack(children...)
p পার্থক্য.NewButton(text)
p পার্থক্য.NewDivider()
p পার্থক্য.NewSpacer()
p পার্থক্য.NewFlex(child)
p পার্থক্য.NewPositioned(child, x, y)
p পার্থক্য.NewSlot(name)
p পার্থক্য.NewScrollView(child)
```
```
--------------------------------
### Register Component
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Registers a custom component factory with the component registry using a given name.
```go
pony.Register(name, factory)
```
--------------------------------
### Tidy Dependencies in Pony
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Tidy dependencies using 'task tidy' or 'go mod tidy'.
```bash
task tidy
go mod tidy
```
--------------------------------
### Layout Helpers
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Utility functions for common layout patterns like panels, cards, sections, and overlays.
```APIDOC
## Layout Helpers
### Description
Helper functions for creating common layout structures.
### Basic Layouts
```go
// Basic layouts
p পার্থক্য.Panel(child, border, padding)
p পার্থক্য.PanelWithMargin(child, border, padding, margin)
p পার্থক্য.Card(title, titleColor, borderColor, children...)
p পার্থক্য.Section(header, headerColor, children...)
p পার্থক্য.Separated(children...)
```
### Advanced Layouts
```go
// Advanced layouts
p পার্থক্য.Overlay(children...) // ZStack with default alignment
p পার্থক্য.FlexGrow(child, grow)
p পার্থক্য.Position(child, x, y)
p পার্থক্য.PositionRight(child, right, y)
p পার্থক্য.PositionBottom(child, x, bottom)
p পার্থক্য.PositionCorner(child, right, bottom)
```
```
--------------------------------
### Use Custom Component in Markup
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling-markup/README.md
Utilize a custom component registered in Go within your XML markup. Pass properties to customize its appearance and behavior.
```xml
```
--------------------------------
### Create Separated Layout
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Arranges multiple child elements with separators between them.
```go
pony.Separated(children...)
```
--------------------------------
### Apply Position Layout Helper
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Positions a child element at specific X and Y coordinates.
```go
pony.Position(child, x, y)
```
--------------------------------
### Stateful Component for Scrolling
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling/README.md
Create a stateful component to manage scroll position dynamically. This approach allows for interactive and dynamic scrolling, but requires state management.
```go
type ScrollableLog struct {
content []string
offset int
height int
}
func (s *ScrollableLog) Update(msg tea.Msg) {
switch msg := msg.(type) {
case tea.KeyPressMsg:
if msg.String() == "down" {
s.offset++
}
}
}
func (s *ScrollableLog) Render() pony.Element {
items := /* build elements from content */
return &pony.ScrollView{
Child: pony.NewVStack(items...),
OffsetY: s.offset, // Dynamic offset!
Height: pony.NewFixedConstraint(s.height),
}
}
// In template
// In View
slots["log"] = m.log.Render()
```
--------------------------------
### Markup-Based Scrolling
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling/README.md
Demonstrates how to use the `` element directly in markup for static scrolling.
```APIDOC
## Markup-Based Scrolling
Use `` directly in markup:
```xml
Line 1Line 2
```
**Pros**: Simple, declarative
**Cons**: Static offset (set via `offset-y` attribute)
```
--------------------------------
### Perform Golden File Rendering Tests
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Use golden files for rendering tests by comparing the output of tmpl.Render against a stored golden file. Regenerate golden files with `go test -update ./...` when rendering changes are intentional.
```go
func TestMyRender(t *testing.T) {
output := tmpl.Render(data, 80, 24)
golden.RequireEqual(t, output) // Compares against testdata/TestMyRender.golden
}
```
--------------------------------
### Mouse Support for Scrolling
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling/README.md
Explains how to enable and handle mouse events, specifically the scroll wheel, for interactive scrolling.
```APIDOC
## Mouse Support
Enable mouse in Bubble Tea:
```go
func (m model) View() tea.View {
output := m.template.Render(data, m.width, m.height)
view := tea.NewView(output)
view.MouseMode = tea.MouseModeCellMotion // Enable mouse!
return view
}
```
Then handle mouse events:
```go
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.MouseWheelMsg:
m := msg.Mouse()
if m.Button == tea.MouseWheelUp {
m.scrollable.ScrollUp(3)
} else if m.Button == tea.MouseWheelDown {
m.scrollable.ScrollDown(3)
}
}
}
```
```
--------------------------------
### Component Registry
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
APIs for registering, unregistering, and retrieving components from the component registry.
```APIDOC
## Component Registry
### Description
Manage custom components within the Pony engine.
### Register Component
```go
pony.Register(name, factory)
```
### Unregister Component
```go
pony.Unregister(name)
```
### Get Component
```go
pony.GetComponent(name)
```
### List Registered Components
```go
pony.RegisteredComponents()
```
```
--------------------------------
### Stateful Component Scrolling
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling/README.md
Illustrates creating a stateful component to manage scroll position interactively.
```APIDOC
## Stateful Component Scrolling
Create a stateful component that manages scroll position:
```go
type ScrollableLog struct {
content []string
offset int
height int
}
func (s *ScrollableLog) Update(msg tea.Msg) {
switch msg := msg.(type) {
case tea.KeyPressMsg:
if msg.String() == "down" {
s.offset++
}
}
}
func (s *ScrollableLog) Render() pony.Element {
items := /* build elements from content */
return &pony.ScrollView{
Child: pony.NewVStack(items...),
OffsetY: s.offset, // Dynamic offset!
Height: pony.NewFixedConstraint(s.height),
}
}
// In template
// In View
slots["log"] = m.log.Render()
```
**Pros**: Interactive, dynamic scrolling
**Cons**: Requires state management
```
--------------------------------
### ProgressView Component
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
The progressview component visualizes progress. Configure its value, maximum, width, and style.
```xml
```
--------------------------------
### Parse Template with Type Safety
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Demonstrates how to parse a Pony template with generic type safety or using a panic-on-error approach.
```go
// Parse with type safety
tmpl, err := pony.Parse[YourDataType](markup)
tmpl := pony.MustParse[YourDataType](markup)
```
--------------------------------
### Registering a New Component Functionally
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
To add a new built-in component that can be used in markup, register a functional component with a unique name and a function that returns an `Element`.
```go
Register("badge", func(props Props, children []Element) Element { ... })
```
--------------------------------
### Flexible Layout with Spacer
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Use the spacer component within a VStack to create flexible spacing that grows to fill available space.
```xml
HeaderFooter
```
--------------------------------
### Register Functional Component
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Register a new UI component using a simple functional approach. This is suitable for stateless components.
```go
// Simple functional component
pony.Register("card", func(props pony.Props, children []pony.Element) pony.Element {
return pony.NewBox(
pony.NewVStack(
pony.NewText(props.Get("title")).Bold(),
pony.NewDivider(),
pony.NewVStack(children...),
),
).Border("rounded").Padding(1)
})
```
--------------------------------
### Create Divider Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Inserts a visual divider element.
```go
pony.NewDivider()
```
--------------------------------
### Run Pony Tests with Verbose Output
Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md
Run all tests with verbose output enabled to see detailed test execution information.
```bash
go test -v
```
--------------------------------
### Define Stateful Input Component in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/stateful/README.md
Defines a stateful input component with value, cursor, and focus management. It handles key press events to update its value and renders as a styled Pony element.
```go
type Input struct {
value string
cursor int
focused bool
}
// Update handles events (state management)
func (i *Input) Update(msg tea.Msg) {
switch msg := msg.(type) {
case tea.KeyPressMsg:
i.value += msg.String()
i.cursor++
}
}
// Render returns pony Element (no size needed!)
func (i *Input) Render() pony.Element {
style, _ := pony.ParseStyle("fg:white")
return pony.NewBox(
pony.NewText(i.value).WithStyle(style),
).WithBorder("rounded").WithPadding(1)
```
--------------------------------
### Go Template Variables
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Embed dynamic data into text elements using Go template syntax for variable substitution.
```xml
Hello, {{ .Username }}!
```
--------------------------------
### New Feature Golden File Test
Source: https://github.com/charmbracelet/x/blob/main/pony/TESTING.md
A template for writing new golden file tests for rendering output. Ensure the output is compared against the correct golden file.
```go
func TestNewFeature(t *testing.T) {
output := tmpl.Render(data, width, height)
golden.RequireEqual(t, output)
}
```
--------------------------------
### Template with Slots in XML
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Define a template structure using XML, incorporating slots where dynamic content will be rendered. The "input" slot is defined here.
```xml
Username:
```
--------------------------------
### Create Positioned Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Creates a positioned element with explicit X and Y coordinates.
```go
pony.NewPositioned(child, x, y)
```
--------------------------------
### Apply Flex Grow Layout Helper
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Applies a flex grow factor to a child element within a flex container.
```go
pony.FlexGrow(child, grow)
```
--------------------------------
### Button Component
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Create clickable buttons using the button component. Customize text, border, and padding.
```xml
```
--------------------------------
### Hit Testing with BoundsMap
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Use the `BoundsMap` returned by `RenderWithBounds` to perform hit testing at specific coordinates. This allows you to identify the element at a given `(x, y)` position and retrieve its ID.
```go
elem := boundsMap.HitTest(x, y) // Find element at coordinates
if elem != nil {
id := elem.ID() // Get element ID for event handling
}
```
--------------------------------
### Create Vertical Stack Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Constructs a vertical stack element that arranges its children vertically.
```go
pony.NewVStack(children...)
```
--------------------------------
### Go Template Functions
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Utilize built-in Go template functions for string manipulation, arithmetic, and formatting within markup.
```xml
{{ upper .Title }}
```
```xml
{{ printf "Count: %d" .Count }}
```
--------------------------------
### Pony BaseElement Embedding Pattern
Source: https://github.com/charmbracelet/x/blob/main/pony/AGENTS.md
Demonstrates how all element types embed BaseElement to inherit ID and bounds tracking functionality. BaseElement provides methods for explicit ID setting/retrieval and recording render bounds.
```go
type MyElement struct {
BaseElement // Required for ID and bounds
// ... other fields
}
`BaseElement` provides:
- `ID()` - Returns explicit ID or pointer-based ID (`elem_%p`)
- `SetID(string)` - Set explicit ID
- `Bounds()` - Get last rendered bounds
- `SetBounds(uv.Rectangle)` - Record bounds (call at start of `Draw()`)
```
--------------------------------
### Apply Position Bottom Layout Helper
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Positions a child element relative to the bottom edge and at a specific X coordinate.
```go
pony.PositionBottom(child, x, bottom)
```
--------------------------------
### Programmatic ScrollView API
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling/README.md
Instantiate and configure a ScrollView programmatically using its builder methods. This allows for fine-grained control over scrolling behavior and appearance.
```go
scroll := pony.NewScrollView(content).
WithHeight(pony.NewFixedConstraint(20)).
WithScrollbar(true).
WithOffset(0, 10)
// Scroll methods
scroll.ScrollUp(1)
scroll.ScrollDown(5, contentHeight, viewportHeight)
scroll.ScrollLeft(3)
scroll.ScrollRight(10, contentWidth, viewportWidth)
// Get content size
size := scroll.ContentSize()
```
--------------------------------
### Use Custom Component in Markup
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Integrate custom-registered components into your UI markup just like built-in components.
```xml
Name: AliceRole: Developer
```
--------------------------------
### Create Horizontal Stack Element
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Constructs a horizontal stack element that arranges its children horizontally.
```go
pony.NewHStack(children...)
```
--------------------------------
### Scroll View with Dynamic Offset
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/scrolling-markup/README.md
Implement a scrollable view that accepts dynamic scrolling via the `offset-y` prop, controlled by template data.
```xml
{{ range .Items }}
{{ end }}
```
--------------------------------
### Basic and Styled Button in XML
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Define buttons in XML markup, specifying their text and optionally applying styles like borders, padding, and text styling.
```xml
```
--------------------------------
### Box Sizing in XML
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Define the sizing of box components using various units including percentages, fixed cells, and content-based sizing.
```xml
...
```
```xml
...
```
```xml
...
```
```xml
...
```
```xml
...
```
--------------------------------
### Define Stateful Component in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/README.md
Define a stateful component with its own state and rendering logic using the slot system. The Update method handles messages, and the Render method returns a Pony element.
```go
type Input struct {
value string
cursor int
}
func (i *Input) Update(msg tea.Msg) {
// Handle input
}
func (i *Input) Render() pony.Element {
return pony.NewBox(
pony.NewText(i.value),
).Border("rounded")
}
```
--------------------------------
### Update Routes Events to Focused Component in Go
Source: https://github.com/charmbracelet/x/blob/main/pony/examples/stateful/README.md
Implements the Update method for the main model, routing KeyPressMsg events to the currently focused input component (username or email).
```go
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyPressMsg:
// Route to focused component
switch m.focused {
case "username":
m.username.Update(msg)
case "email":
m.email.Update(msg)
}
}
return m, nil
}
```