Components
Text area
this is Text area snippet using bubbletea and lipgloss
A text area field, akin to an <textarea /> in HTML. Allows for input that
spans multiple lines. Supports unicode, pasting, vertical scrolling when the
value exceeds the width and height of the element, and many customization
options.
Text area (chat input)
package main
// A simple program demonstrating the text area component from the Bubbles
// component library.
import (
"fmt"
"log"
"strings"
"github.com/charmbracelet/bubbles/textarea"
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
const gap = "\n\n"
func main() {
p := tea.NewProgram(initialModel())
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
}
type (
errMsg error
)
type model struct {
viewport viewport.Model
messages []string
textarea textarea.Model
senderStyle lipgloss.Style
err error
}
func initialModel() model {
ta := textarea.New()
ta.Placeholder = "Send a message..."
ta.Focus()
ta.Prompt = "┃ "
ta.CharLimit = 280
ta.SetWidth(30)
ta.SetHeight(3)
// Remove cursor line styling
ta.FocusedStyle.CursorLine = lipgloss.NewStyle()
ta.ShowLineNumbers = false
vp := viewport.New(30, 5)
vp.SetContent(`Welcome to the chat room!
Type a message and press Enter to send.`)
ta.KeyMap.InsertNewline.SetEnabled(false)
return model{
textarea: ta,
messages: []string{},
viewport: vp,
senderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("5")),
err: nil,
}
}
func (m model) Init() tea.Cmd {
return textarea.Blink
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var (
tiCmd tea.Cmd
vpCmd tea.Cmd
)
m.textarea, tiCmd = m.textarea.Update(msg)
m.viewport, vpCmd = m.viewport.Update(msg)
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.viewport.Width = msg.Width
m.textarea.SetWidth(msg.Width)
m.viewport.Height = msg.Height - m.textarea.Height() - lipgloss.Height(gap)
if len(m.messages) > 0 {
// Wrap content before setting it.
m.viewport.SetContent(lipgloss.NewStyle().Width(m.viewport.Width).Render(strings.Join(m.messages, "\n")))
}
m.viewport.GotoBottom()
case tea.KeyMsg:
switch msg.Type {
case tea.KeyCtrlC, tea.KeyEsc:
fmt.Println(m.textarea.Value())
return m, tea.Quit
case tea.KeyEnter:
m.messages = append(m.messages, m.senderStyle.Render("You: ")+m.textarea.Value())
m.viewport.SetContent(lipgloss.NewStyle().Width(m.viewport.Width).Render(strings.Join(m.messages, "\n")))
m.textarea.Reset()
m.viewport.GotoBottom()
}
// We handle errors just like any other message
case errMsg:
m.err = msg
return m, nil
}
return m, tea.Batch(tiCmd, vpCmd)
}
func (m model) View() string {
return fmt.Sprintf(
"%s%s%s",
m.viewport.View(),
gap,
m.textarea.View(),
)
}Text area (story time input)
package main
// A simple program demonstrating the textarea component from the Bubbles
// component library.
import (
"fmt"
"log"
"github.com/charmbracelet/bubbles/textarea"
tea "github.com/charmbracelet/bubbletea"
)
func main() {
p := tea.NewProgram(initialModel())
if _, err := p.Run(); err != nil {
log.Fatal(err)
}
}
type errMsg error
type model struct {
textarea textarea.Model
err error
}
func initialModel() model {
ti := textarea.New()
ti.Placeholder = "Once upon a time..."
ti.Focus()
return model{
textarea: ti,
err: nil,
}
}
func (m model) Init() tea.Cmd {
return textarea.Blink
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.Type {
case tea.KeyEsc:
if m.textarea.Focused() {
m.textarea.Blur()
}
case tea.KeyCtrlC:
return m, tea.Quit
default:
if !m.textarea.Focused() {
cmd = m.textarea.Focus()
cmds = append(cmds, cmd)
}
}
// We handle errors just like any other message
case errMsg:
m.err = msg
return m, nil
}
m.textarea, cmd = m.textarea.Update(msg)
cmds = append(cmds, cmd)
return m, tea.Batch(cmds...)
}
func (m model) View() string {
return fmt.Sprintf(
"Tell me a story.\n\n%s\n\n%s",
m.textarea.View(),
"(ctrl+c to quit)",
) + "\n\n"
}How is this guide?