Skip to content

Commit

Permalink
feat(textinput): add styles for focused and blurred states
Browse files Browse the repository at this point in the history
  • Loading branch information
meowgorithm committed Oct 23, 2024
1 parent 30d7e7b commit 432972a
Showing 1 changed file with 57 additions and 24 deletions.
81 changes: 57 additions & 24 deletions textinput/textinput.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,36 @@ func DefaultKeyMap() KeyMap {
}
}

// Styles is a collection of styles for the text input. There are two states:
// one for when the input is focused and one for when it is not.
type Styles struct {
Focused StyleState
Blurred StyleState
}

// StyleState is a set of styles for the text input that pertain to focused
// and unfocused states.
type StyleState struct {
Prompt lipgloss.Style
Text lipgloss.Style
Placeholder lipgloss.Style
Completion lipgloss.Style
}

// DefaultStyles returns the default styles for the text input.
func DefaultStyles() Styles {
v := StyleState{
Prompt: lipgloss.NewStyle(),
Text: lipgloss.NewStyle(),
Placeholder: lipgloss.NewStyle().Faint(true),
Completion: lipgloss.NewStyle().Faint(true),
}
return Styles{
Focused: v,
Blurred: v,
}
}

// Model is the Bubble Tea model for this text input element.
type Model struct {
Err error
Expand All @@ -94,14 +124,7 @@ type Model struct {
EchoCharacter rune
Cursor cursor.Model

// Styles. These will be applied as inline styles.
//
// For an introduction to styling with Lip Gloss see:
// https://github.com/charmbracelet/lipgloss
PromptStyle lipgloss.Style
TextStyle lipgloss.Style
PlaceholderStyle lipgloss.Style
CompletionStyle lipgloss.Style
Styles Styles

// Validate is a function that checks whether or not the text within the
// input is valid. If it is not valid, the Err field will be set to the
Expand Down Expand Up @@ -152,14 +175,13 @@ type Model struct {
// New creates a new model with default settings.
func New() Model {
return Model{
Prompt: "> ",
EchoCharacter: '*',
CharLimit: 0,
PlaceholderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("240")),
ShowSuggestions: false,
CompletionStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("240")),
Cursor: cursor.New(),
KeyMap: DefaultKeyMap(),
Prompt: "> ",
EchoCharacter: '*',
CharLimit: 0,
ShowSuggestions: false,
Cursor: cursor.New(),
KeyMap: DefaultKeyMap(),
Styles: DefaultStyles(),

suggestions: [][]rune{},
value: nil,
Expand All @@ -168,6 +190,14 @@ func New() Model {
}
}

// styles returns the appropriate styles for the current focus state.
func (m Model) styles() StyleState {
if m.focus {
return m.Styles.Focused
}
return m.Styles.Blurred
}

// SetValue sets the value of the text input.
func (m *Model) SetValue(s string) {
// Clean up any special characters in the input provided by the
Expand Down Expand Up @@ -656,7 +686,9 @@ func (m Model) View() string {
return m.placeholderView()
}

styleText := m.TextStyle.Inline(true).Render
s := m.styles()

styleText := s.Text.Inline(true).Render

value := m.value[m.offset:m.offsetRight]
pos := max(0, m.pos-m.offset)
Expand All @@ -672,7 +704,7 @@ func (m Model) View() string {
if m.canAcceptSuggestion() {
suggestion := m.matchedSuggestions[m.currentSuggestionIndex]
if len(value) < len(suggestion) {
m.Cursor.TextStyle = m.CompletionStyle
m.Cursor.TextStyle = s.Completion
m.Cursor.SetChar(m.echoTransform(string(suggestion[pos])))
v += m.Cursor.View()
v += m.completionView(1)
Expand All @@ -697,24 +729,25 @@ func (m Model) View() string {
v += styleText(strings.Repeat(" ", padding))
}

return m.PromptStyle.Render(m.Prompt) + v
return s.Prompt.Render(m.Prompt) + v
}

// placeholderView returns the prompt and placeholder view, if any.
func (m Model) placeholderView() string {
var (
v string
p = []rune(m.Placeholder)
style = m.PlaceholderStyle.Inline(true).Render
s = m.styles()
style = s.Placeholder.Inline(true).Render
)

m.Cursor.TextStyle = m.PlaceholderStyle
m.Cursor.TextStyle = s.Placeholder
m.Cursor.SetChar(string(p[:1]))
v += m.Cursor.View()

// If the entire placeholder is already set and no padding is needed, finish
if m.Width() < 1 && len(p) <= 1 {
return m.PromptStyle.Render(m.Prompt) + v
return s.Prompt.Render(m.Prompt) + v
}

// If Width is set then size placeholder accordingly
Expand All @@ -736,7 +769,7 @@ func (m Model) placeholderView() string {
v += style(string(p[1:]))
}

return m.PromptStyle.Render(m.Prompt) + v
return s.Prompt.Render(m.Prompt) + v
}

// Blink is a command used to initialize cursor blinking.
Expand Down Expand Up @@ -777,7 +810,7 @@ func max(a, b int) int {
func (m Model) completionView(offset int) string {
var (
value = m.value
style = m.PlaceholderStyle.Inline(true).Render
style = m.styles().Placeholder.Inline(true).Render
)

if m.canAcceptSuggestion() {
Expand Down

0 comments on commit 432972a

Please sign in to comment.