Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: form and group dedicated styles #258

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions form.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type Form struct {
// options
width int
height int
theme *Theme
keymap *KeyMap
timeout time.Duration
teaOptions []tea.ProgramOption
Expand Down Expand Up @@ -240,9 +241,10 @@ func (f *Form) WithShowErrors(v bool) *Form {
// can be applied to each group and field individually for more granular
// control.
func (f *Form) WithTheme(theme *Theme) *Form {
if theme == nil {
if f.theme != nil {
return f
}
f.theme = theme
for _, group := range f.groups {
group.WithTheme(theme)
}
Expand Down Expand Up @@ -575,13 +577,23 @@ func (f *Form) isGroupHidden(page int) bool {
return hide()
}

func (f *Form) styles() *FormStyles {
theme := f.theme
if theme == nil {
theme = ThemeCharm()
}
return &theme.Form
}

// View renders the form.
func (f *Form) View() string {
if f.quitting {
return ""
}

return f.layout.View(f)
styles := f.styles()

return styles.Base.Render(f.layout.View(f))
}

// Run runs the form.
Expand Down
19 changes: 17 additions & 2 deletions group.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type Group struct {
// group options
width int
height int
theme *Theme
keymap *KeyMap
hide func() bool
active bool
Expand Down Expand Up @@ -92,6 +93,10 @@ func (g *Group) WithShowErrors(show bool) *Group {

// WithTheme sets the theme on a group.
func (g *Group) WithTheme(t *Theme) *Group {
if g.theme != nil {
return g
}
g.theme = t
g.help.Styles = t.Help
for _, field := range g.fields {
field.WithTheme(t)
Expand Down Expand Up @@ -265,6 +270,14 @@ func (g *Group) fullHeight() int {
return height
}

func (g *Group) styles() *GroupStyles {
theme := g.theme
if theme == nil {
theme = ThemeCharm()
}
return &theme.Group
}

func (g *Group) getContent() (int, string) {
var fields strings.Builder
offset := 0
Expand Down Expand Up @@ -312,6 +325,8 @@ func (g *Group) Content() string {

// Footer renders the group's footer only (no content).
func (g *Group) Footer() string {
styles := g.styles()

var view strings.Builder
view.WriteRune('\n')
errors := g.Errors()
Expand All @@ -320,8 +335,8 @@ func (g *Group) Footer() string {
}
if g.showErrors {
for _, err := range errors {
view.WriteString(ThemeCharm().Focused.ErrorMessage.Render(err.Error()))
view.WriteString(styles.ErrorMessage.Render(err.Error()))
}
}
return view.String()
return styles.Base.Render(view.String())
}
36 changes: 28 additions & 8 deletions theme.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,31 @@ import (
// Theme is a collection of styles for components of the form.
// Themes can be applied to a form using the WithTheme option.
type Theme struct {
Form lipgloss.Style
Group lipgloss.Style
Form FormStyles
Group GroupStyles
FieldSeparator lipgloss.Style
Blurred FieldStyles
Focused FieldStyles
Help help.Styles
}

// FormStyles are the styles for form.
type FormStyles struct {
Base lipgloss.Style
}

// GroupStyles are the styles for form groups.
type GroupStyles struct {
Base lipgloss.Style
ErrorMessage lipgloss.Style
}

// FieldStyles are the styles for input fields.
type FieldStyles struct {
Base lipgloss.Style
Title lipgloss.Style
Description lipgloss.Style
ErrorIndicator lipgloss.Style
ErrorMessage lipgloss.Style

// Select styles.
SelectSelector lipgloss.Style // Selection indicator
Expand Down Expand Up @@ -74,6 +84,13 @@ const (
func ThemeBase() *Theme {
var t Theme

// Form styles.
t.Form.Base = lipgloss.NewStyle()

// Group styles.
t.Group.Base = lipgloss.NewStyle()
t.Group.ErrorMessage = lipgloss.NewStyle().SetString(" *")

t.FieldSeparator = lipgloss.NewStyle().SetString("\n\n")

button := lipgloss.NewStyle().
Expand All @@ -84,7 +101,6 @@ func ThemeBase() *Theme {
t.Focused.Base = lipgloss.NewStyle().PaddingLeft(1).BorderStyle(lipgloss.ThickBorder()).BorderLeft(true)
t.Focused.Card = lipgloss.NewStyle().PaddingLeft(1)
t.Focused.ErrorIndicator = lipgloss.NewStyle().SetString(" *")
t.Focused.ErrorMessage = lipgloss.NewStyle().SetString(" *")
t.Focused.SelectSelector = lipgloss.NewStyle().SetString("> ")
t.Focused.NextIndicator = lipgloss.NewStyle().MarginLeft(1).SetString("→")
t.Focused.PrevIndicator = lipgloss.NewStyle().MarginRight(1).SetString("←")
Expand Down Expand Up @@ -120,13 +136,14 @@ func ThemeCharm() *Theme {
red = lipgloss.AdaptiveColor{Light: "#FF4672", Dark: "#ED567A"}
)

t.Group.ErrorMessage = t.Group.ErrorMessage.Foreground(red)

t.Focused.Base = t.Focused.Base.BorderForeground(lipgloss.Color("238"))
t.Focused.Title = t.Focused.Title.Foreground(indigo).Bold(true)
t.Focused.NoteTitle = t.Focused.NoteTitle.Foreground(indigo).Bold(true).MarginBottom(1)
t.Focused.Directory = t.Focused.Directory.Foreground(indigo)
t.Focused.Description = t.Focused.Description.Foreground(lipgloss.AdaptiveColor{Light: "", Dark: "243"})
t.Focused.ErrorIndicator = t.Focused.ErrorIndicator.Foreground(red)
t.Focused.ErrorMessage = t.Focused.ErrorMessage.Foreground(red)
t.Focused.SelectSelector = t.Focused.SelectSelector.Foreground(fuchsia)
t.Focused.NextIndicator = t.Focused.NextIndicator.Foreground(fuchsia)
t.Focused.PrevIndicator = t.Focused.PrevIndicator.Foreground(fuchsia)
Expand Down Expand Up @@ -167,14 +184,15 @@ func ThemeDracula() *Theme {
yellow = lipgloss.AdaptiveColor{Dark: "#f1fa8c"}
)

t.Group.ErrorMessage = t.Group.ErrorMessage.Foreground(red)

t.Focused.Base = t.Focused.Base.BorderForeground(selection)
t.Focused.Title = t.Focused.Title.Foreground(purple)
t.Focused.NoteTitle = t.Focused.NoteTitle.Foreground(purple)
t.Focused.Description = t.Focused.Description.Foreground(comment)
t.Focused.ErrorIndicator = t.Focused.ErrorIndicator.Foreground(red)
t.Focused.Directory = t.Focused.Directory.Foreground(purple)
t.Focused.File = t.Focused.File.Foreground(foreground)
t.Focused.ErrorMessage = t.Focused.ErrorMessage.Foreground(red)
t.Focused.SelectSelector = t.Focused.SelectSelector.Foreground(yellow)
t.Focused.NextIndicator = t.Focused.NextIndicator.Foreground(yellow)
t.Focused.PrevIndicator = t.Focused.PrevIndicator.Foreground(yellow)
Expand Down Expand Up @@ -203,13 +221,14 @@ func ThemeDracula() *Theme {
func ThemeBase16() *Theme {
t := ThemeBase()

t.Group.ErrorMessage = t.Group.ErrorMessage.Foreground(lipgloss.Color("9"))

t.Focused.Base = t.Focused.Base.BorderForeground(lipgloss.Color("8"))
t.Focused.Title = t.Focused.Title.Foreground(lipgloss.Color("6"))
t.Focused.NoteTitle = t.Focused.NoteTitle.Foreground(lipgloss.Color("6"))
t.Focused.Directory = t.Focused.Directory.Foreground(lipgloss.Color("6"))
t.Focused.Description = t.Focused.Description.Foreground(lipgloss.Color("8"))
t.Focused.ErrorIndicator = t.Focused.ErrorIndicator.Foreground(lipgloss.Color("9"))
t.Focused.ErrorMessage = t.Focused.ErrorMessage.Foreground(lipgloss.Color("9"))
t.Focused.SelectSelector = t.Focused.SelectSelector.Foreground(lipgloss.Color("3"))
t.Focused.NextIndicator = t.Focused.NextIndicator.Foreground(lipgloss.Color("3"))
t.Focused.PrevIndicator = t.Focused.PrevIndicator.Foreground(lipgloss.Color("3"))
Expand Down Expand Up @@ -259,13 +278,14 @@ func ThemeCatppuccin() *Theme {
cursor = lipgloss.AdaptiveColor{Light: light.Rosewater().Hex, Dark: dark.Rosewater().Hex}
)

t.Group.ErrorMessage = t.Group.ErrorMessage.Foreground(red)

t.Focused.Base = t.Focused.Base.BorderForeground(subtext1)
t.Focused.Title = t.Focused.Title.Foreground(mauve)
t.Focused.NoteTitle = t.Focused.NoteTitle.Foreground(mauve)
t.Focused.Directory = t.Focused.Directory.Foreground(mauve)
t.Focused.Description = t.Focused.Description.Foreground(subtext0)
t.Focused.ErrorIndicator = t.Focused.ErrorIndicator.Foreground(red)
t.Focused.ErrorMessage = t.Focused.ErrorMessage.Foreground(red)
t.Focused.SelectSelector = t.Focused.SelectSelector.Foreground(pink)
t.Focused.NextIndicator = t.Focused.NextIndicator.Foreground(pink)
t.Focused.PrevIndicator = t.Focused.PrevIndicator.Foreground(pink)
Expand Down
Loading