diff --git a/internal/ui/dialog/commands.go b/internal/ui/dialog/commands.go index 0b0185b03a3c992ce55ff9164ceba6115260c174..6e769e66f7217c994f877582e8ca2eca80577b9a 100644 --- a/internal/ui/dialog/commands.go +++ b/internal/ui/dialog/commands.go @@ -27,9 +27,7 @@ type CommandType uint func (c CommandType) String() string { return []string{"System", "User", "MCP"}[c] } const ( - sidebarCompactModeBreakpoint = 120 - defaultCommandsDialogMaxHeight = 20 - defaultCommandsDialogMaxWidth = 70 + sidebarCompactModeBreakpoint = 120 ) const ( @@ -155,19 +153,17 @@ func (c *Commands) HandleMsg(msg tea.Msg) Action { c.list.Focus() if c.list.IsSelectedFirst() { c.list.SelectLast() - c.list.ScrollToBottom() - break + } else { + c.list.SelectPrev() } - c.list.SelectPrev() c.list.ScrollToSelected() case key.Matches(msg, c.keyMap.Next): c.list.Focus() if c.list.IsSelectedLast() { c.list.SelectFirst() - c.list.ScrollToTop() - break + } else { + c.list.SelectNext() } - c.list.SelectNext() c.list.ScrollToSelected() case key.Matches(msg, c.keyMap.Select): if selectedItem := c.list.SelectedItem(); selectedItem != nil { @@ -240,8 +236,8 @@ func commandsRadioView(sty *styles.Styles, selected CommandType, hasUserCmds boo // Draw implements [Dialog]. func (c *Commands) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor { t := c.com.Styles - width := max(0, min(defaultCommandsDialogMaxWidth, area.Dx()-t.Dialog.View.GetHorizontalBorderSize())) - height := max(0, min(defaultCommandsDialogMaxHeight, area.Dy()-t.Dialog.View.GetVerticalBorderSize())) + width := max(0, min(defaultDialogMaxWidth, area.Dx()-t.Dialog.View.GetHorizontalBorderSize())) + height := max(0, min(defaultDialogHeight, area.Dy()-t.Dialog.View.GetVerticalBorderSize())) if area.Dx() != c.windowWidth && c.selected == SystemCommands { c.windowWidth = area.Dx() // since some items in the list depend on width (e.g. toggle sidebar command), diff --git a/internal/ui/dialog/dialog.go b/internal/ui/dialog/dialog.go index 990b4ed68174bee20d627dec5f7176d9466b77d8..15e0fa52f5ab7b181e5659e7526213d254f01931 100644 --- a/internal/ui/dialog/dialog.go +++ b/internal/ui/dialog/dialog.go @@ -11,9 +11,9 @@ import ( // Dialog sizing constants. const ( // defaultDialogMaxWidth is the maximum width for standard dialogs. - defaultDialogMaxWidth = 120 + defaultDialogMaxWidth = 70 // defaultDialogHeight is the default height for standard dialogs. - defaultDialogHeight = 30 + defaultDialogHeight = 20 // titleContentHeight is the height of the title content line. titleContentHeight = 1 // inputContentHeight is the height of the input content line. diff --git a/internal/ui/dialog/models.go b/internal/ui/dialog/models.go index 7594c2476218ae241c4b21cbb455b19f00923c47..657cdd362de044defdd84928cb01fad4477b37b0 100644 --- a/internal/ui/dialog/models.go +++ b/internal/ui/dialog/models.go @@ -174,19 +174,17 @@ func (m *Models) HandleMsg(msg tea.Msg) Action { m.list.Focus() if m.list.IsSelectedFirst() { m.list.SelectLast() - m.list.ScrollToBottom() - break + } else { + m.list.SelectPrev() } - m.list.SelectPrev() m.list.ScrollToSelected() case key.Matches(msg, m.keyMap.Next): m.list.Focus() if m.list.IsSelectedLast() { m.list.SelectFirst() - m.list.ScrollToTop() - break + } else { + m.list.SelectNext() } - m.list.SelectNext() m.list.ScrollToSelected() case key.Matches(msg, m.keyMap.Select, m.keyMap.Edit): selectedItem := m.list.SelectedItem() diff --git a/internal/ui/dialog/sessions.go b/internal/ui/dialog/sessions.go index cfb0f30623c383b775c3a960134057e6c79ce9b8..6f9b7724a796818c789e19ba9455c23e7e51c9b4 100644 --- a/internal/ui/dialog/sessions.go +++ b/internal/ui/dialog/sessions.go @@ -190,19 +190,17 @@ func (s *Session) HandleMsg(msg tea.Msg) Action { s.list.Focus() if s.list.IsSelectedFirst() { s.list.SelectLast() - s.list.ScrollToBottom() - break + } else { + s.list.SelectPrev() } - s.list.SelectPrev() s.list.ScrollToSelected() case key.Matches(msg, s.keyMap.Next): s.list.Focus() if s.list.IsSelectedLast() { s.list.SelectFirst() - s.list.ScrollToTop() - break + } else { + s.list.SelectNext() } - s.list.SelectNext() s.list.ScrollToSelected() case key.Matches(msg, s.keyMap.Select): if item := s.list.SelectedItem(); item != nil { @@ -231,9 +229,9 @@ func (s *Session) Cursor() *tea.Cursor { // Draw implements [Dialog]. func (s *Session) Draw(scr uv.Screen, area uv.Rectangle) *tea.Cursor { t := s.com.Styles - width := max(0, min(defaultDialogMaxWidth, area.Dx())) - height := max(0, min(defaultDialogHeight, area.Dy())) - innerWidth := width - t.Dialog.View.GetHorizontalFrameSize() - 2 + width := max(0, min(defaultDialogMaxWidth, area.Dx()-t.Dialog.View.GetHorizontalBorderSize())) + height := max(0, min(defaultDialogHeight, area.Dy()-t.Dialog.View.GetVerticalBorderSize())) + innerWidth := width - t.Dialog.View.GetHorizontalFrameSize() heightOffset := t.Dialog.Title.GetVerticalFrameSize() + titleContentHeight + t.Dialog.InputPrompt.GetVerticalFrameSize() + inputContentHeight + t.Dialog.HelpView.GetVerticalFrameSize() + diff --git a/internal/ui/dialog/sessions_item.go b/internal/ui/dialog/sessions_item.go index 2532e8c19a75ef061266afd42d688016ea0ab3c9..66c3be7af3da3dbae88b8a4971463bfcea40eba6 100644 --- a/internal/ui/dialog/sessions_item.go +++ b/internal/ui/dialog/sessions_item.go @@ -137,7 +137,7 @@ func renderItem(t ListItemStyles, title string, info string, focused bool, width infoWidth = lipgloss.Width(infoText) } - title = ansi.Truncate(title, max(0, lineWidth-infoWidth), "") + title = ansi.Truncate(title, max(0, lineWidth-infoWidth), "…") titleWidth := lipgloss.Width(title) gap := strings.Repeat(" ", max(0, lineWidth-titleWidth-infoWidth)) content := title @@ -154,7 +154,7 @@ func renderItem(t ListItemStyles, title string, info string, focused bool, width // because we can control the underline start and stop more // precisely via [ansi.AttrUnderline] and [ansi.AttrNoUnderline] // which only affect the underline attribute without interfering - // with other style + // with other style attributes. parts = append(parts, ansi.NewStyle().Underline(true).String(), ansi.Cut(title, start, stop+1),