Skip to content

Commit

Permalink
🚧 Add theme panel for options
Browse files Browse the repository at this point in the history
Selecting a theme is a custom setting panel that reuses the filter list
component. When in theme mode, the themes are rendered immediately to
help discover preferred themes.
  • Loading branch information
mikelorant committed Mar 1, 2023
1 parent fdb7cef commit cccbc43
Show file tree
Hide file tree
Showing 12 changed files with 556 additions and 11 deletions.
51 changes: 41 additions & 10 deletions internal/ui/colour/colour.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,15 @@ type message struct {
}

type option struct {
SectionBoundary lipgloss.TerminalColor
SectionBoundaryFocus lipgloss.TerminalColor
SettingBoundary lipgloss.TerminalColor
SettingBoundaryFocus lipgloss.TerminalColor
HelpBoundary lipgloss.TerminalColor
SectionBoundary lipgloss.TerminalColor
SectionBoundaryFocus lipgloss.TerminalColor
SettingBoundary lipgloss.TerminalColor
SettingBoundaryFocus lipgloss.TerminalColor
HelpBoundary lipgloss.TerminalColor
ThemeTitleBoundary lipgloss.TerminalColor
ThemeTitleBoundaryFocus lipgloss.TerminalColor
ThemeListBoundary lipgloss.TerminalColor
ThemeListBoundaryFocus lipgloss.TerminalColor
}

type optionSection struct {
Expand All @@ -120,6 +124,15 @@ type optionSetting struct {
SettingSquareFilled lipgloss.TerminalColor
}

type optionTheme struct {
Title lipgloss.TerminalColor
TitleFocus lipgloss.TerminalColor
TitleLabel lipgloss.TerminalColor
TitleText lipgloss.TerminalColor
Boundary lipgloss.TerminalColor
BoundaryFocus lipgloss.TerminalColor
}

type shortcut struct {
Key lipgloss.TerminalColor
Label lipgloss.TerminalColor
Expand Down Expand Up @@ -256,11 +269,15 @@ func (c *Colour) Option() option {
clr := c.registry

return option{
SectionBoundary: ToAdaptive(clr.BrightBlack()),
SectionBoundaryFocus: clr.Fg(),
SettingBoundary: ToAdaptive(clr.BrightBlack()),
SettingBoundaryFocus: clr.Fg(),
HelpBoundary: clr.Fg(),
SectionBoundary: ToAdaptive(clr.BrightBlack()),
SectionBoundaryFocus: clr.Fg(),
SettingBoundary: ToAdaptive(clr.BrightBlack()),
SettingBoundaryFocus: clr.Fg(),
HelpBoundary: clr.Fg(),
ThemeTitleBoundary: ToAdaptive(clr.BrightBlack()),
ThemeTitleBoundaryFocus: clr.Fg(),
ThemeListBoundary: ToAdaptive(clr.BrightBlack()),
ThemeListBoundaryFocus: clr.Fg(),
}
}

Expand Down Expand Up @@ -297,6 +314,20 @@ func (c *Colour) OptionSetting() optionSetting {
}
}

//nolint:revive
func (c *Colour) OptionTheme() optionTheme {
clr := c.registry

return optionTheme{
Title: ToAdaptive(clr.BrightBlack()),
TitleFocus: clr.Fg(),
TitleLabel: clr.Fg(),
TitleText: ToAdaptive(clr.BrightWhite()),
Boundary: ToAdaptive(clr.BrightBlack()),
BoundaryFocus: clr.Fg(),
}
}

//nolint:revive
func (c *Colour) Shortcut() shortcut {
clr := c.registry
Expand Down
47 changes: 47 additions & 0 deletions internal/ui/colour/colour_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ type optionSetting struct {
SettingSquareFilled Colour
}

type optionTheme struct {
Title Colour
TitleFocus Colour
TitleLabel Colour
TitleText Colour
Boundary Colour
BoundaryFocus Colour
}

type shortcut struct {
Key Colour
Label Colour
Expand Down Expand Up @@ -543,6 +552,44 @@ func TestOptionSetting(t *testing.T) {
}
}

func TestOptionTheme(t *testing.T) {
t.Parallel()

tests := []struct {
name string
optionTheme optionTheme
}{
{
name: "OptionTheme",
optionTheme: optionTheme{
Title: Colour{Dark: "#555555", Light: "#555555"},
TitleFocus: Colour{Dark: "#bbbbbb"},
TitleLabel: Colour{Dark: "#bbbbbb"},
TitleText: Colour{Dark: "#ffffff", Light: "#ffffff"},
Boundary: Colour{Dark: "#555555", Light: "#555555"},
BoundaryFocus: Colour{Dark: "#bbbbbb"},
},
},
}

for _, tt := range tests {
tt := tt

t.Run(tt.name, func(t *testing.T) {
t.Parallel()

clr := colour.New(theme.New(config.ColourAdaptive)).OptionTheme()

assert.Equal(t, tt.optionTheme.Title, toColour(clr.Title), "Title")
assert.Equal(t, tt.optionTheme.TitleFocus, toColour(clr.TitleFocus), "TitleFocus")
assert.Equal(t, tt.optionTheme.TitleLabel, toColour(clr.TitleLabel), "TitleLabel")
assert.Equal(t, tt.optionTheme.TitleText, toColour(clr.TitleText), "TitleText")
assert.Equal(t, tt.optionTheme.Boundary, toColour(clr.Boundary), "Boundary")
assert.Equal(t, tt.optionTheme.BoundaryFocus, toColour(clr.BoundaryFocus), "BoundaryFocus")
})
}
}

func TestShortcut(t *testing.T) {
t.Parallel()

Expand Down
4 changes: 4 additions & 0 deletions internal/ui/filterlist/filterlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ func (m Model) Filter() string {
return m.textInput.Value()
}

func (m *Model) Select(i int) {
m.list.Select(i)
}

//nolint:ireturn
func (m Model) SelectedItem() list.Item {
return m.list.SelectedItem()
Expand Down
59 changes: 58 additions & 1 deletion internal/ui/option/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/mikelorant/committed/internal/ui/option/help"
"github.com/mikelorant/committed/internal/ui/option/section"
"github.com/mikelorant/committed/internal/ui/option/setting"
"github.com/mikelorant/committed/internal/ui/option/theme"

tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
Expand All @@ -14,16 +15,19 @@ type Model struct {
SectionWidth int
SettingWidth int
HelpWidth int
ThemeWidth int
SectionHeight int
SettingHeight int
HelpHeight int
ThemeHeight int

Panel Panel

state *commit.State
section section.Model
setting setting.Model
help help.Model
theme theme.Model
styles Styles
}

Expand All @@ -33,27 +37,33 @@ const (
PanelSection Panel = iota
PanelSetting
PanelHelp
PanelTheme
)

const (
defaultSectionWidth = 40
defaultSettingWidth = 40
defaultHelpWidth = 40
defaultThemeWidth = 40
defaultSectionHeight = 20
defaultSettingHeight = 14
defaultHelpHeight = 3
defaultThemeHeight = 20
)

func New(state *commit.State) Model {
m := Model{
SectionWidth: defaultSectionWidth,
SettingWidth: defaultSettingWidth,
HelpWidth: defaultHelpWidth,
ThemeWidth: defaultThemeWidth,
SectionHeight: defaultSectionHeight,
SettingHeight: defaultSettingHeight,
HelpHeight: defaultHelpHeight,
ThemeHeight: defaultThemeHeight,
section: section.New(state),
setting: setting.New(state),
theme: theme.New(state),
styles: defaultStyles(state.Theme),
state: state,
}
Expand All @@ -79,6 +89,10 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case "up":
m.section.Previous()
case "right", "enter":
if m.Category() == "Theme" {
m.Panel = PanelTheme
break
}
m.setting.SelectPane(m.section.SelectedSetting())
m.Panel = PanelSetting
}
Expand Down Expand Up @@ -109,12 +123,33 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
}
}

case PanelTheme:
//nolint:gocritic
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "enter":
m.theme, _ = theme.ToModel(m.theme.Update(msg))
fallthrough
case "left":
m.theme.Blur()
m.Panel = PanelSection
}
}
}

if m.Panel == PanelTheme && !m.theme.Focused() {
m.theme.Focus()
msg = nil
}

m.setting.SwapPaneSet(m.section.SelectedCategory())
cmds := make([]tea.Cmd, 2)

cmds := make([]tea.Cmd, 3)
m.section, cmds[0] = section.ToModel(m.section.Update(msg))
m.setting, cmds[1] = setting.ToModel(m.setting.Update(msg))
m.theme, cmds[2] = theme.ToModel(m.theme.Update(msg))

return m, tea.Batch(cmds...)
}
Expand All @@ -123,19 +158,28 @@ func (m Model) View() string {
m.section.Width = m.SectionWidth
m.setting.Width = m.SettingWidth
m.help.Width = m.HelpWidth
m.theme.Width = m.ThemeWidth
m.theme.Height = m.ThemeHeight

var (
boundarySection lipgloss.Style
boundarySetting lipgloss.Style
boundaryTheme lipgloss.Style
)

switch m.Panel {
case PanelSection:
boundarySection = m.styles.sectionBoundaryFocus
boundarySetting = m.styles.settingBoundary
boundaryTheme = m.styles.themeBoundary
case PanelSetting:
boundarySection = m.styles.sectionBoundary
boundarySetting = m.styles.settingBoundaryFocus
boundaryTheme = m.styles.themeBoundary
case PanelTheme:
boundarySection = m.styles.sectionBoundary
boundarySetting = m.styles.settingBoundary
boundaryTheme = m.styles.themeBoundary
}

section := boundarySection.
Expand All @@ -153,6 +197,19 @@ func (m Model) View() string {
Height(m.HelpHeight).
Render(m.help.View())

theme := boundaryTheme.
Width(m.ThemeWidth).
Height(m.ThemeHeight).
Render(m.theme.View())

if m.Category() == "Theme" {
return lipgloss.JoinHorizontal(
lipgloss.Top,
section,
theme,
)
}

settingHelp := lipgloss.JoinVertical(
lipgloss.Top,
setting,
Expand Down
7 changes: 7 additions & 0 deletions internal/ui/option/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Styles struct {
settingBoundary lipgloss.Style
settingBoundaryFocus lipgloss.Style
helpBoundary lipgloss.Style
themeBoundary lipgloss.Style
}

func defaultStyles(th theme.Theme) Styles {
Expand Down Expand Up @@ -54,5 +55,11 @@ func defaultStyles(th theme.Theme) Styles {
BorderStyle(lipgloss.NormalBorder()).
Padding(0, 1, 0, 1).
MarginBottom(1)

s.themeBoundary = lipgloss.NewStyle().
Align(lipgloss.Left, lipgloss.Top).
Padding(0, 1, 0, 1).
MarginBottom(1)

return s
}
50 changes: 50 additions & 0 deletions internal/ui/option/theme/style.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package theme

import (
"github.com/mikelorant/committed/internal/theme"
"github.com/mikelorant/committed/internal/ui/colour"

"github.com/charmbracelet/lipgloss"
)

type Styles struct {
themeTitle lipgloss.Style
themeTitleFocus lipgloss.Style
themeTitleLabel lipgloss.Style
themeTitleText lipgloss.Style
themeListBoundary lipgloss.Style
themeListBoundaryFocus lipgloss.Style
}

func defaultStyles(th theme.Theme) Styles {
var s Styles

clr := colour.New(th).OptionTheme()

s.themeTitle = lipgloss.NewStyle().
Border(lipgloss.NormalBorder()).
BorderForeground(clr.Title).
Width(40).
Padding(0, 1, 0, 1).
MarginBottom(1)

s.themeTitleFocus = s.themeTitle.Copy().
BorderForeground(clr.TitleFocus)

s.themeTitleLabel = lipgloss.NewStyle().
Foreground(clr.TitleLabel).
SetString("Theme:")

s.themeTitleText = lipgloss.NewStyle().
Foreground(clr.TitleText)

s.themeListBoundary = lipgloss.NewStyle().
Border(lipgloss.NormalBorder()).
Width(40).
BorderForeground(clr.Boundary)

s.themeListBoundaryFocus = s.themeListBoundary.Copy().
BorderForeground(clr.BoundaryFocus)

return s
}
Loading

0 comments on commit cccbc43

Please sign in to comment.