Skip to content

Commit

Permalink
Set themes on fields (#219)
Browse files Browse the repository at this point in the history
* fix: allow overriding theme for specific fields

* fix: ThemeCharm is default and works for Blurred / Focused
  • Loading branch information
maaslalani authored May 4, 2024
1 parent 4b9024c commit dadcb82
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 94 deletions.
25 changes: 18 additions & 7 deletions field_confirm.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ func NewConfirm() *Confirm {
affirmative: "Yes",
negative: "No",
validate: func(bool) error { return nil },
theme: ThemeCharm(),
}
}

Expand Down Expand Up @@ -158,12 +157,20 @@ func (c *Confirm) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return c, tea.Batch(cmds...)
}

// View renders the confirm field.
func (c *Confirm) View() string {
styles := c.theme.Blurred
func (c *Confirm) activeStyles() *FieldStyles {
theme := c.theme
if theme == nil {
theme = ThemeCharm()
}
if c.focused {
styles = c.theme.Focused
return &theme.Focused
}
return &theme.Blurred
}

// View renders the confirm field.
func (c *Confirm) View() string {
styles := c.activeStyles()

var sb strings.Builder
sb.WriteString(styles.Title.Render(c.title))
Expand Down Expand Up @@ -211,10 +218,11 @@ func (c *Confirm) Run() error {

// runAccessible runs the confirm field in accessible mode.
func (c *Confirm) runAccessible() error {
fmt.Println(c.theme.Blurred.Base.Render(c.theme.Focused.Title.Render(c.title)))
styles := c.activeStyles()
fmt.Println(styles.Title.Render(c.title))
fmt.Println()
*c.value = accessibility.PromptBool()
fmt.Println(c.theme.Focused.SelectedOption.Render("Chose: "+c.String()) + "\n")
fmt.Println(styles.SelectedOption.Render("Chose: "+c.String()) + "\n")
return nil
}

Expand All @@ -227,6 +235,9 @@ func (c *Confirm) String() string {

// WithTheme sets the theme of the confirm field.
func (c *Confirm) WithTheme(theme *Theme) Field {
if c.theme != nil {
return c
}
c.theme = theme
return c
}
Expand Down
26 changes: 19 additions & 7 deletions field_filepicker.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func NewFilePicker() *FilePicker {
value: new(string),
validate: func(string) error { return nil },
picker: fp,
theme: ThemeCharm(),
}
}

Expand Down Expand Up @@ -235,12 +234,21 @@ func (f *FilePicker) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return f, cmd
}

// View renders the file field.
func (f *FilePicker) View() string {
styles := f.theme.Blurred
func (f *FilePicker) activeStyles() *FieldStyles {
theme := f.theme
if theme == nil {
theme = ThemeCharm()
}
if f.focused {
styles = f.theme.Focused
return &theme.Focused
}
return &theme.Blurred
}

// View renders the file field.
func (f *FilePicker) View() string {
styles := f.activeStyles()

var sb strings.Builder
if f.title != "" {
sb.WriteString(styles.Title.Render(f.title) + "\n")
Expand Down Expand Up @@ -286,7 +294,8 @@ func (f *FilePicker) Run() error {

// runAccessible runs an accessible file field.
func (f *FilePicker) runAccessible() error {
fmt.Println(f.theme.Blurred.Base.Render(f.theme.Focused.Title.Render(f.title)))
styles := f.activeStyles()
fmt.Println(styles.Title.Render(f.title))
fmt.Println()

validateFile := func(s string) error {
Expand All @@ -312,12 +321,15 @@ func (f *FilePicker) runAccessible() error {
}

*f.value = accessibility.PromptString("File: ", validateFile)
fmt.Println(f.theme.Focused.SelectedOption.Render(*f.value + "\n"))
fmt.Println(styles.SelectedOption.Render(*f.value + "\n"))
return nil
}

// WithTheme sets the theme of the file field.
func (f *FilePicker) WithTheme(theme *Theme) Field {
if f.theme != nil || theme == nil {
return f
}
f.theme = theme

// XXX: add specific themes
Expand Down
32 changes: 22 additions & 10 deletions field_input.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ func NewInput() *Input {
value: new(string),
textinput: input,
validate: func(string) error { return nil },
theme: ThemeCharm(),
}

return i
Expand Down Expand Up @@ -230,12 +229,20 @@ func (i *Input) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return i, tea.Batch(cmds...)
}

// View renders the input field.
func (i *Input) View() string {
styles := i.theme.Blurred
func (i *Input) activeStyles() *FieldStyles {
theme := i.theme
if theme == nil {
theme = ThemeCharm()
}
if i.focused {
styles = i.theme.Focused
return &theme.Focused
}
return &theme.Blurred
}

// View renders the input field.
func (i *Input) View() string {
styles := i.activeStyles()

// NB: since the method is on a pointer receiver these are being mutated.
// Because this runs on every render this shouldn't matter in practice,
Expand Down Expand Up @@ -278,10 +285,11 @@ func (i *Input) run() error {

// runAccessible runs the input field in accessible mode.
func (i *Input) runAccessible() error {
fmt.Println(i.theme.Blurred.Base.Render(i.theme.Focused.Title.Render(i.title)))
styles := i.activeStyles()
fmt.Println(styles.Title.Render(i.title))
fmt.Println()
*i.value = accessibility.PromptString("Input: ", i.validate)
fmt.Println(i.theme.Focused.SelectedOption.Render("Input: " + *i.value + "\n"))
fmt.Println(styles.SelectedOption.Render("Input: " + *i.value + "\n"))
return nil
}

Expand All @@ -300,17 +308,21 @@ func (i *Input) WithAccessible(accessible bool) Field {

// WithTheme sets the theme of the input field.
func (i *Input) WithTheme(theme *Theme) Field {
if i.theme != nil {
return i
}
i.theme = theme
return i
}

// WithWidth sets the width of the input field.
func (i *Input) WithWidth(width int) Field {
styles := i.activeStyles()
i.width = width
frameSize := i.theme.Blurred.Base.GetHorizontalFrameSize()
frameSize := styles.Base.GetHorizontalFrameSize()
promptWidth := lipgloss.Width(i.textinput.PromptStyle.Render(i.textinput.Prompt))
titleWidth := lipgloss.Width(i.theme.Focused.Title.Render(i.title))
descriptionWidth := lipgloss.Width(i.theme.Focused.Description.Render(i.description))
titleWidth := lipgloss.Width(styles.Title.Render(i.title))
descriptionWidth := lipgloss.Width(styles.Description.Render(i.description))
i.textinput.Width = width - frameSize - promptWidth - 1
if i.inline {
i.textinput.Width -= titleWidth
Expand Down
27 changes: 15 additions & 12 deletions field_multiselect.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func NewMultiSelect[T comparable]() *MultiSelect[T] {
validate: func([]T) error { return nil },
filtering: false,
filter: filter,
theme: ThemeCharm(),
}
}

Expand Down Expand Up @@ -306,11 +305,6 @@ func (m *MultiSelect[T]) updateViewportHeight() {
return
}

// Wait until the theme has appied or things'll panic.
if m.theme == nil {
return
}

const minHeight = 1
m.viewport.Height = max(minHeight, m.height-
lipgloss.Height(m.titleView())-
Expand Down Expand Up @@ -338,10 +332,14 @@ func (m *MultiSelect[T]) finalize() {
}

func (m *MultiSelect[T]) activeStyles() *FieldStyles {
theme := m.theme
if theme == nil {
theme = ThemeCharm()
}
if m.focused {
return &m.theme.Focused
return &theme.Focused
}
return &m.theme.Blurred
return &theme.Blurred
}

func (m *MultiSelect[T]) titleView() string {
Expand Down Expand Up @@ -419,21 +417,22 @@ func (m *MultiSelect[T]) View() string {
}

func (m *MultiSelect[T]) printOptions() {
styles := m.activeStyles()
var sb strings.Builder

sb.WriteString(m.theme.Focused.Title.Render(m.title))
sb.WriteString(styles.Title.Render(m.title))
sb.WriteString("\n")

for i, option := range m.options {
if option.selected {
sb.WriteString(m.theme.Focused.SelectedOption.Render(fmt.Sprintf("%d. %s %s", i+1, "✓", option.Key)))
sb.WriteString(styles.SelectedOption.Render(fmt.Sprintf("%d. %s %s", i+1, "✓", option.Key)))
} else {
sb.WriteString(fmt.Sprintf("%d. %s %s", i+1, " ", option.Key))
}
sb.WriteString("\n")
}

fmt.Println(m.theme.Blurred.Base.Render(sb.String()))
fmt.Println(sb.String())
}

// setFilter sets the filter of the select field.
Expand Down Expand Up @@ -464,6 +463,7 @@ func (m *MultiSelect[T]) Run() error {
// runAccessible() runs the multi-select field in accessible mode.
func (m *MultiSelect[T]) runAccessible() error {
m.printOptions()
styles := m.activeStyles()

var choice int
for {
Expand Down Expand Up @@ -503,12 +503,15 @@ func (m *MultiSelect[T]) runAccessible() error {
}
}

fmt.Println(m.theme.Focused.SelectedOption.Render("Selected:", strings.Join(values, ", ")+"\n"))
fmt.Println(styles.SelectedOption.Render("Selected:", strings.Join(values, ", ")+"\n"))
return nil
}

// WithTheme sets the theme of the multi-select field.
func (m *MultiSelect[T]) WithTheme(theme *Theme) Field {
if m.theme != nil {
return m
}
m.theme = theme
m.filter.Cursor.Style = m.theme.Focused.TextInput.Cursor
m.filter.PromptStyle = m.theme.Focused.TextInput.Prompt
Expand Down
23 changes: 16 additions & 7 deletions field_note.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ type Note struct {
func NewNote() *Note {
return &Note{
showNextButton: false,
theme: ThemeCharm(),
skip: true,
}
}
Expand Down Expand Up @@ -106,15 +105,22 @@ func (n *Note) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return n, nil
}

// View renders the note field.
func (n *Note) View() string {
styles := n.theme.Blurred
func (n *Note) activeStyles() *FieldStyles {
theme := n.theme
if theme == nil {
theme = ThemeCharm()
}
if n.focused {
styles = n.theme.Focused
return &theme.Focused
}
return &theme.Focused
}

// View renders the note field.
func (n *Note) View() string {
var (
sb strings.Builder
styles = n.activeStyles()
sb strings.Builder
)

if n.title != "" {
Expand Down Expand Up @@ -148,13 +154,16 @@ func (n *Note) runAccessible() error {

body += n.description

fmt.Println(n.theme.Blurred.Base.Render(body))
fmt.Println(body)
fmt.Println()
return nil
}

// WithTheme sets the theme on a note field.
func (n *Note) WithTheme(theme *Theme) Field {
if n.theme != nil {
return n
}
n.theme = theme
return n
}
Expand Down
Loading

0 comments on commit dadcb82

Please sign in to comment.