Unify styles

This commit is contained in:
Martin Pander
2026-02-17 21:25:14 +01:00
parent 1a9fd9b4b0
commit 3ab26f658d
10 changed files with 132 additions and 324 deletions

View File

@@ -65,16 +65,9 @@ func NewContextPickerPage(common *common.Common) *ContextPickerPage {
func (p *ContextPickerPage) SetSize(width, height int) {
p.common.SetSize(width, height)
// Set list size with some padding/limits to look like a picker
listWidth := width - 4
if listWidth > 40 {
listWidth = 40
}
listHeight := height - 6
if listHeight > 20 {
listHeight = 20
}
p.picker.SetSize(listWidth, listHeight)
// Use shared modal sizing logic
modalWidth, modalHeight := p.common.Styles.GetModalSize(width, height)
p.picker.SetSize(modalWidth-2, modalHeight-2)
}
func (p *ContextPickerPage) Init() tea.Cmd {
@@ -124,20 +117,23 @@ func (p *ContextPickerPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
func (p *ContextPickerPage) View() string {
width := p.common.Width() - 4
if width > 40 {
width = 40
}
modalWidth, modalHeight := p.common.Styles.GetModalSize(p.common.Width(), p.common.Height())
content := p.picker.View()
styledContent := lipgloss.NewStyle().Width(width).Render(content)
styledContent := lipgloss.NewStyle().
Width(modalWidth).
Height(modalHeight).
Border(lipgloss.RoundedBorder()).
BorderForeground(p.common.Styles.Palette.Border.GetForeground()).
Padding(0, 1).
Render(content)
return lipgloss.Place(
p.common.Width(),
p.common.Height(),
lipgloss.Center,
lipgloss.Center,
p.common.Styles.Base.Render(styledContent),
styledContent,
)
}

View File

@@ -55,16 +55,9 @@ func NewProjectPickerPage(common *common.Common, activeProject string) *ProjectP
func (p *ProjectPickerPage) SetSize(width, height int) {
p.common.SetSize(width, height)
// Set list size with some padding/limits to look like a picker
listWidth := width - 4
if listWidth > 40 {
listWidth = 40
}
listHeight := height - 6
if listHeight > 20 {
listHeight = 20
}
p.picker.SetSize(listWidth, listHeight)
// Use shared modal sizing logic
modalWidth, modalHeight := p.common.Styles.GetModalSize(width, height)
p.picker.SetSize(modalWidth-2, modalHeight-2)
}
func (p *ProjectPickerPage) Init() tea.Cmd {
@@ -112,20 +105,23 @@ func (p *ProjectPickerPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
func (p *ProjectPickerPage) View() string {
width := p.common.Width() - 4
if width > 40 {
width = 40
}
modalWidth, modalHeight := p.common.Styles.GetModalSize(p.common.Width(), p.common.Height())
content := p.picker.View()
styledContent := lipgloss.NewStyle().Width(width).Render(content)
styledContent := lipgloss.NewStyle().
Width(modalWidth).
Height(modalHeight).
Border(lipgloss.RoundedBorder()).
BorderForeground(p.common.Styles.Palette.Border.GetForeground()).
Padding(0, 1).
Render(content)
return lipgloss.Place(
p.common.Width(),
p.common.Height(),
lipgloss.Center,
lipgloss.Center,
p.common.Styles.Base.Render(styledContent),
styledContent,
)
}

View File

@@ -335,30 +335,33 @@ func (p *ProjectTaskPickerPage) View() string {
// Create distinct styling for focused vs blurred pickers
var projectStyled, taskStyled string
focusedBorder := p.common.Styles.Palette.Accent.GetForeground()
blurredBorder := p.common.Styles.Palette.Border.GetForeground()
if p.focusedPicker == 0 {
// Project picker is focused
projectStyled = lipgloss.NewStyle().
Border(lipgloss.ThickBorder()).
BorderForeground(lipgloss.Color("6")). // Cyan for focused
BorderForeground(focusedBorder).
Padding(0, 1).
Render(projectView)
taskStyled = lipgloss.NewStyle().
Border(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("240")). // Gray for blurred
BorderForeground(blurredBorder).
Padding(0, 1).
Render(taskView)
} else {
// Task picker is focused
projectStyled = lipgloss.NewStyle().
Border(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("240")). // Gray for blurred
BorderForeground(blurredBorder).
Padding(0, 1).
Render(projectView)
taskStyled = lipgloss.NewStyle().
Border(lipgloss.ThickBorder()).
BorderForeground(lipgloss.Color("6")). // Cyan for focused
BorderForeground(focusedBorder).
Padding(0, 1).
Render(taskView)
}
@@ -376,7 +379,7 @@ func (p *ProjectTaskPickerPage) View() string {
// Add help text
helpText := "Tab/Shift+Tab: switch focus • Enter: select • a: add task • e: edit • t: track time • Esc: cancel"
helpStyled := lipgloss.NewStyle().
Foreground(lipgloss.Color("241")).
Foreground(p.common.Styles.Palette.Muted.GetForeground()).
Italic(true).
Render(helpText)

View File

@@ -57,16 +57,9 @@ func NewReportPickerPage(common *common.Common, activeReport *taskwarrior.Report
func (p *ReportPickerPage) SetSize(width, height int) {
p.common.SetSize(width, height)
// Set list size with some padding/limits to look like a picker
listWidth := width - 4
if listWidth > 40 {
listWidth = 40
}
listHeight := height - 6
if listHeight > 20 {
listHeight = 20
}
p.picker.SetSize(listWidth, listHeight)
// Use shared modal sizing logic
modalWidth, modalHeight := p.common.Styles.GetModalSize(width, height)
p.picker.SetSize(modalWidth-2, modalHeight-2)
}
func (p *ReportPickerPage) Init() tea.Cmd {
@@ -112,20 +105,23 @@ func (p *ReportPickerPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
func (p *ReportPickerPage) View() string {
width := p.common.Width() - 4
if width > 40 {
width = 40
}
modalWidth, modalHeight := p.common.Styles.GetModalSize(p.common.Width(), p.common.Height())
content := p.picker.View()
styledContent := lipgloss.NewStyle().Width(width).Render(content)
styledContent := lipgloss.NewStyle().
Width(modalWidth).
Height(modalHeight).
Border(lipgloss.RoundedBorder()).
BorderForeground(p.common.Styles.Palette.Border.GetForeground()).
Padding(0, 1).
Render(content)
return lipgloss.Place(
p.common.Width(),
p.common.Height(),
lipgloss.Center,
lipgloss.Center,
p.common.Styles.Base.Render(styledContent),
styledContent,
)
}

View File

@@ -323,11 +323,13 @@ func (p *TaskEditorPage) View() string {
tabs := ""
for i, a := range p.areas {
style := p.common.Styles.Base
if i == p.area {
tabs += p.common.Styles.Base.Bold(true).Render(fmt.Sprintf(" %s ", a.GetName()))
style = style.Bold(true).Foreground(p.common.Styles.Palette.Accent.GetForeground())
} else {
tabs += p.common.Styles.Base.Render(fmt.Sprintf(" %s ", a.GetName()))
style = style.Foreground(p.common.Styles.Palette.Muted.GetForeground())
}
tabs += style.Render(fmt.Sprintf(" %s ", a.GetName()))
}
page := lipgloss.JoinVertical(
@@ -1001,149 +1003,8 @@ func (d *detailsEdit) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (d *detailsEdit) View() string {
return d.ta.View()
// dtls := `
// # Cool Details!
// ## Things I need
// - [ ] A thing
// - [x] Done thing
// ## People
// - pe1
// - pe2
// `
// details, err := d.renderer.Render(dtls)
// if err != nil {
// slog.Error(err.Error())
// return "Could not parse markdown"
// }
// d.vp.SetContent(details)
// return d.vp.View()
}
// func (p *TaskEditorPage) SetSize(width, height int) {
// p.common.SetSize(width, height)
// }
// func (p *TaskEditorPage) Init() tea.Cmd {
// // return p.form.Init()
// return nil
// }
// func (p *TaskEditorPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// var cmds []tea.Cmd
// switch msg := msg.(type) {
// case SwitchModeMsg:
// switch mode(msg) {
// case modeNormal:
// p.mode = modeNormal
// case modeInsert:
// p.mode = modeInsert
// }
// case changeAreaMsg:
// p.selectedArea = area(msg)
// p.columns = append([]tea.Model{p.areaList}, p.areas[p.selectedArea]...)
// case nextColumnMsg:
// p.columnCursor++
// if p.columnCursor > len(p.columns)-1 {
// p.columnCursor = 0
// }
// case prevColumnMsg:
// p.columnCursor--
// if p.columnCursor < 0 {
// p.columnCursor = len(p.columns) - 1
// }
// }
// switch p.mode {
// case modeNormal:
// switch msg := msg.(type) {
// case tea.KeyMsg:
// switch {
// case key.Matches(msg, p.common.Keymap.Back):
// model, err := p.common.PopPage()
// if err != nil {
// slog.Error("page stack empty")
// return nil, tea.Quit
// }
// return model, BackCmd
// case key.Matches(msg, p.common.Keymap.Insert):
// return p, p.switchModeCmd(modeInsert)
// // case key.Matches(msg, p.common.Keymap.Ok):
// // p.form.State = huh.StateCompleted
// case key.Matches(msg, p.common.Keymap.Left):
// return p, prevColumn()
// case key.Matches(msg, p.common.Keymap.Right):
// return p, nextColumn()
// }
// }
// case modeInsert:
// switch msg := msg.(type) {
// case tea.KeyMsg:
// switch {
// case key.Matches(msg, p.common.Keymap.Back):
// return p, p.switchModeCmd(modeNormal)
// }
// }
// var cmd tea.Cmd
// if p.columnCursor == 0 {
// p.areaList, cmd = p.areaList.Update(msg)
// p.selectedArea = p.areaList.(areaList).Area()
// cmds = append(cmds, cmd)
// } else {
// p.areas[p.selectedArea][p.columnCursor-1], cmd = p.areas[p.selectedArea][p.columnCursor-1].Update(msg)
// cmds = append(cmds, cmd)
// }
// }
// var cmd tea.Cmd
// if p.columnCursor == 0 {
// p.areaList, cmd = p.areaList.Update(msg)
// p.selectedArea = p.areaList.(areaList).Area()
// cmds = append(cmds, cmd)
// } else {
// p.areas[p.selectedArea][p.columnCursor-1], cmd = p.areas[p.selectedArea][p.columnCursor-1].Update(msg)
// cmds = append(cmds, cmd)
// }
// p.statusline, cmd = p.statusline.Update(msg)
// cmds = append(cmds, cmd)
// // if p.form.State == huh.StateCompleted {
// // cmds = append(cmds, p.updateTasksCmd)
// // model, err := p.common.PopPage()
// // if err != nil {
// // slog.Error("page stack empty")
// // return nil, tea.Quit
// // }
// // return model, tea.Batch(cmds...)
// // }
// return p, tea.Batch(cmds...)
// }
// func (p *TaskEditorPage) View() string {
// columns := make([]string, len(p.columns))
// for i, c := range p.columns {
// columns[i] = c.View()
// }
// return lipgloss.JoinVertical(
// lipgloss.Left,
// lipgloss.JoinHorizontal(
// lipgloss.Top,
// // lipgloss.Place(p.common.Width(), p.common.Height()-1, 0.5, 0.5, p.form.View(), lipgloss.WithWhitespaceBackground(p.common.Styles.Warning.GetForeground())),
// // lipgloss.Place(p.common.Width(), p.common.Height()-1, 0.5, 0.5, p.form.View(), lipgloss.WithWhitespaceChars(" . ")),
// columns...,
// ),
// p.statusline.View(),
// )
// }
func (p *TaskEditorPage) updateTasksCmd() tea.Msg {
p.task.Project = p.areas[0].(*taskEdit).projectPicker.GetValue()
@@ -1160,10 +1021,6 @@ func (p *TaskEditorPage) updateTasksCmd() tea.Msg {
}
}
// if *(p.areas[0].(*taskEdit).newProjectName) != "" {
// p.task.Project = *p.areas[0].(*taskEdit).newProjectName
// }
// Sync timestamp fields from the timeEdit area (area 2)
p.areas[2].(*timeEdit).syncToTaskFields()
@@ -1172,8 +1029,6 @@ func (p *TaskEditorPage) updateTasksCmd() tea.Msg {
Entry: time.Now().Format("20060102T150405Z"),
Description: *(p.areas[0].(*taskEdit).newAnnotation),
})
// p.common.TW.AddTaskAnnotation(p.task.Uuid, *p.areas[0].(*taskEdit).newAnnotation)
}
if _, ok := p.task.Udas["details"]; ok || p.areas[3].(*detailsEdit).ta.Value() != "" {
@@ -1184,100 +1039,5 @@ func (p *TaskEditorPage) updateTasksCmd() tea.Msg {
return UpdatedTasksMsg{}
}
// type StatusLine struct {
// common *common.Common
// mode mode
// input textinput.Model
// }
// func NewStatusLine(common *common.Common, mode mode) *StatusLine {
// input := textinput.New()
// input.Placeholder = ""
// input.Prompt = ""
// input.Blur()
// return &StatusLine{
// input: textinput.New(),
// common: common,
// mode: mode,
// }
// }
// func (s *StatusLine) Init() tea.Cmd {
// s.input.Blur()
// return nil
// }
// func (s *StatusLine) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// var cmd tea.Cmd
// switch msg := msg.(type) {
// case SwitchModeMsg:
// s.mode = mode(msg)
// switch s.mode {
// case modeNormal:
// s.input.Blur()
// case modeInsert:
// s.input.Focus()
// }
// case tea.KeyMsg:
// switch {
// case key.Matches(msg, s.common.Keymap.Back):
// s.input.Blur()
// case key.Matches(msg, s.common.Keymap.Input):
// s.input.Focus()
// }
// }
// s.input, cmd = s.input.Update(msg)
// return s, cmd
// }
// func (s *StatusLine) View() string {
// var mode string
// switch s.mode {
// case modeNormal:
// mode = s.common.Styles.Base.Render("NORMAL")
// case modeInsert:
// mode = s.common.Styles.Active.Inline(true).Reverse(true).Render("INSERT")
// }
// return lipgloss.JoinHorizontal(lipgloss.Left, mode, s.input.View())
// }
// // TODO: move this to taskwarrior; add missing date formats
// type itemDelegate struct{}
// func (d itemDelegate) Height() int { return 1 }
// func (d itemDelegate) Spacing() int { return 0 }
// func (d itemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil }
// func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
// i, ok := listItem.(item)
// if !ok {
// return
// }
// str := fmt.Sprintf("%s", i)
// fn := itemStyle.Render
// if index == m.Index() {
// fn = func(s ...string) string {
// return selectedItemStyle.Render("> " + strings.Join(s, " "))
// }
// }
// fmt.Fprint(w, fn(str))
// }
// var (
// titleStyle = lipgloss.NewStyle().MarginLeft(2)
// itemStyle = lipgloss.NewStyle().PaddingLeft(4)
// selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170"))
// paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4)
// helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1)
// quitTextStyle = lipgloss.NewStyle().Margin(1, 0, 2, 4)
// )
// type item string
// func (i item) FilterValue() string { return "" }
// type StatusLine struct { ... }
// ...

View File

@@ -144,7 +144,7 @@ func (p *TimePage) renderHeader() string {
slog.Info("Rendering time page header", "text", headerText, "timespan", p.selectedTimespan)
// Make header bold and prominent
headerStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("6"))
headerStyle := lipgloss.NewStyle().Bold(true).Foreground(p.common.Styles.Palette.Accent.GetForeground())
return headerStyle.Render(headerText)
}