chore: bump bubbletea and ultraviolet dependencies

Ayman Bagabas created

Change summary

go.mod                             |  6 +-
go.sum                             | 12 ++--
internal/ui/common/capabilities.go |  3 
internal/ui/model/landing.go       |  4 
internal/ui/model/sidebar.go       |  3 
internal/ui/model/ui.go            | 79 ++++++++++++++++---------------
6 files changed, 55 insertions(+), 52 deletions(-)

Detailed changes

go.mod 🔗

@@ -4,7 +4,7 @@ go 1.25.5
 
 require (
 	charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66
-	charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251216153312-819e2e89c62e
+	charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0
 	charm.land/catwalk v0.17.1
 	charm.land/fantasy v0.7.1
 	charm.land/glamour/v2 v2.0.0-20260123212943-6014aa153a9b
@@ -22,8 +22,8 @@ require (
 	github.com/charlievieth/fastwalk v1.0.14
 	github.com/charmbracelet/colorprofile v0.4.1
 	github.com/charmbracelet/fang v0.4.4
-	github.com/charmbracelet/ultraviolet v0.0.0-20251212194010-b927aa605560
-	github.com/charmbracelet/x/ansi v0.11.4
+	github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8
+	github.com/charmbracelet/x/ansi v0.11.6
 	github.com/charmbracelet/x/editor v0.2.0
 	github.com/charmbracelet/x/etag v0.2.0
 	github.com/charmbracelet/x/exp/charmtone v0.0.0-20260109001716-2fbdffcb221f

go.sum 🔗

@@ -1,7 +1,7 @@
 charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66 h1:2BdJynsAW+8rv9xq6ZS+x0mtacfxpxjIK1KUIeTqBOs=
 charm.land/bubbles/v2 v2.0.0-rc.1.0.20260109112849-ae99f46cec66/go.mod h1:5AbN6cEd/47gkEf8TgiQ2O3RZ5QxMS14l9W+7F9fPC4=
-charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251216153312-819e2e89c62e h1:tXwTmgGpwZT7ParKF5xbEQBVjM2e1uKhKi/GpfU3mYQ=
-charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251216153312-819e2e89c62e/go.mod h1:pDM18flq3Z4njKZPA3zCvyVSSIJbMcoqlE82BdGUtL8=
+charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0 h1:HAbpM9TPjZM18D677ww3VnkKXdd2hyMQtHUsVV0HcPQ=
+charm.land/bubbletea/v2 v2.0.0-rc.2.0.20260209074636-30878e43d7b0/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ=
 charm.land/catwalk v0.17.1 h1:UsHvBi3S7CxONiIZTWKTXM+H9qla8I0fCb/SVru33ms=
 charm.land/catwalk v0.17.1/go.mod h1:kAdk/GjAJbl1AjRjmfU5c9lZfs7PeC3Uy9TgaVtlN64=
 charm.land/fantasy v0.7.1 h1:JOCYeLz32PM11y1u08/YgWl3LfPwhjOIuoyjBXjFofI=
@@ -102,10 +102,10 @@ github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco
 github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
 github.com/charmbracelet/fang v0.4.4 h1:G4qKxF6or/eTPgmAolwPuRNyuci3hTUGGX1rj1YkHJY=
 github.com/charmbracelet/fang v0.4.4/go.mod h1:P5/DNb9DddQ0Z0dbc0P3ol4/ix5Po7Ofr2KMBfAqoCo=
-github.com/charmbracelet/ultraviolet v0.0.0-20251212194010-b927aa605560 h1:j3PW2hypGoPKBy3ooKzW0TFxaxhyHK3NbkLLn4KeRFc=
-github.com/charmbracelet/ultraviolet v0.0.0-20251212194010-b927aa605560/go.mod h1:VWATWLRwYP06VYCEur7FsNR2B1xAo7Y+xl1PTbd1ePc=
-github.com/charmbracelet/x/ansi v0.11.4 h1:6G65PLu6HjmE858CnTUQY1LXT3ZUWwfvqEROLF8vqHI=
-github.com/charmbracelet/x/ansi v0.11.4/go.mod h1:/5AZ+UfWExW3int5H5ugnsG/PWjNcSQcwYsHBlPFQN4=
+github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 h1:eyFRbAmexyt43hVfeyBofiGSEmJ7krjLOYt/9CF5NKA=
+github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8/go.mod h1:SQpCTRNBtzJkwku5ye4S3HEuthAlGy2n9VXZnWkEW98=
+github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8=
+github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ=
 github.com/charmbracelet/x/editor v0.2.0 h1:7XLUKtaRaB8jN7bWU2p2UChiySyaAuIfYiIRg8gGWwk=
 github.com/charmbracelet/x/editor v0.2.0/go.mod h1:p3oQ28TSL3YPd+GKJ1fHWcp+7bVGpedHpXmo0D6t1dY=
 github.com/charmbracelet/x/etag v0.2.0 h1:Euj1VkheoHfTYA9y+TCwkeXF/hN8Fb9l4LqZl79pt04=

internal/ui/common/capabilities.go 🔗

@@ -47,7 +47,7 @@ func (c *Capabilities) Update(msg any) {
 	case tea.WindowSizeMsg:
 		c.Columns = m.Width
 		c.Rows = m.Height
-	case uv.WindowPixelSizeEvent:
+	case uv.PixelSizeEvent:
 		c.PixelX = m.Width
 		c.PixelY = m.Height
 	case uv.KittyGraphicsEvent:
@@ -71,6 +71,7 @@ func (c *Capabilities) Update(msg any) {
 func QueryCmd(env uv.Environ) tea.Cmd {
 	var sb strings.Builder
 	sb.WriteString(ansi.RequestPrimaryDeviceAttributes)
+	sb.WriteString(ansi.QueryModifyOtherKeys)
 
 	// Queries that should only be sent to "smart" normal terminals.
 	shouldQueryFor := shouldQueryCapabilities(env)

internal/ui/model/landing.go 🔗

@@ -4,7 +4,7 @@ import (
 	"charm.land/lipgloss/v2"
 	"github.com/charmbracelet/crush/internal/agent"
 	"github.com/charmbracelet/crush/internal/ui/common"
-	uv "github.com/charmbracelet/ultraviolet"
+	"github.com/charmbracelet/ultraviolet/layout"
 )
 
 // selectedLargeModel returns the currently selected large language model from
@@ -31,7 +31,7 @@ func (m *UI) landingView() string {
 	parts = append(parts, "", m.modelInfo(width))
 	infoSection := lipgloss.JoinVertical(lipgloss.Left, parts...)
 
-	_, remainingHeightArea := uv.SplitVertical(m.layout.main, uv.Fixed(lipgloss.Height(infoSection)+1))
+	_, remainingHeightArea := layout.SplitVertical(m.layout.main, layout.Fixed(lipgloss.Height(infoSection)+1))
 
 	mcpLspSectionWidth := min(30, (width-1)/2)
 

internal/ui/model/sidebar.go 🔗

@@ -8,6 +8,7 @@ import (
 	"github.com/charmbracelet/crush/internal/ui/common"
 	"github.com/charmbracelet/crush/internal/ui/logo"
 	uv "github.com/charmbracelet/ultraviolet"
+	"github.com/charmbracelet/ultraviolet/layout"
 	"golang.org/x/text/cases"
 	"golang.org/x/text/language"
 )
@@ -134,7 +135,7 @@ func (m *UI) drawSidebar(scr uv.Screen, area uv.Rectangle) {
 		blocks...,
 	)
 
-	_, remainingHeightArea := uv.SplitVertical(m.layout.sidebar, uv.Fixed(lipgloss.Height(sidebarHeader)))
+	_, remainingHeightArea := layout.SplitVertical(m.layout.sidebar, layout.Fixed(lipgloss.Height(sidebarHeader)))
 	remainingHeight := remainingHeightArea.Dy() - 10
 	maxFiles, maxLSPs, maxMCPs := getDynamicHeightLimits(remainingHeight)
 

internal/ui/model/ui.go 🔗

@@ -47,6 +47,7 @@ import (
 	"github.com/charmbracelet/crush/internal/ui/util"
 	"github.com/charmbracelet/crush/internal/version"
 	uv "github.com/charmbracelet/ultraviolet"
+	"github.com/charmbracelet/ultraviolet/layout"
 	"github.com/charmbracelet/ultraviolet/screen"
 	"github.com/charmbracelet/x/editor"
 )
@@ -135,7 +136,7 @@ type UI struct {
 	// The width and height of the terminal in cells.
 	width  int
 	height int
-	layout layout
+	layout uiLayout
 
 	isTransparent bool
 
@@ -2235,7 +2236,7 @@ func (m *UI) updateSize() {
 
 // generateLayout calculates the layout rectangles for all UI components based
 // on the current UI state and terminal dimensions.
-func (m *UI) generateLayout(w, h int) layout {
+func (m *UI) generateLayout(w, h int) uiLayout {
 	// The screen area we're working with
 	area := image.Rect(0, 0, w, h)
 
@@ -2256,7 +2257,7 @@ func (m *UI) generateLayout(w, h int) layout {
 	}
 
 	// Add app margins
-	appRect, helpRect := uv.SplitVertical(area, uv.Fixed(area.Dy()-helpHeight))
+	appRect, helpRect := layout.SplitVertical(area, layout.Fixed(area.Dy()-helpHeight))
 	appRect.Min.Y += 1
 	appRect.Max.Y -= 1
 	helpRect.Min.Y -= 1
@@ -2269,7 +2270,7 @@ func (m *UI) generateLayout(w, h int) layout {
 		appRect.Max.X -= 1
 	}
 
-	layout := layout{
+	uiLayout := uiLayout{
 		area:   area,
 		status: helpRect,
 	}
@@ -2285,9 +2286,9 @@ func (m *UI) generateLayout(w, h int) layout {
 		// ------
 		// help
 
-		headerRect, mainRect := uv.SplitVertical(appRect, uv.Fixed(landingHeaderHeight))
-		layout.header = headerRect
-		layout.main = mainRect
+		headerRect, mainRect := layout.SplitVertical(appRect, layout.Fixed(landingHeaderHeight))
+		uiLayout.header = headerRect
+		uiLayout.main = mainRect
 
 	case uiLanding:
 		// Layout
@@ -2299,14 +2300,14 @@ func (m *UI) generateLayout(w, h int) layout {
 		// editor
 		// ------
 		// help
-		headerRect, mainRect := uv.SplitVertical(appRect, uv.Fixed(landingHeaderHeight))
-		mainRect, editorRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-editorHeight))
+		headerRect, mainRect := layout.SplitVertical(appRect, layout.Fixed(landingHeaderHeight))
+		mainRect, editorRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-editorHeight))
 		// Remove extra padding from editor (but keep it for header and main)
 		editorRect.Min.X -= 1
 		editorRect.Max.X += 1
-		layout.header = headerRect
-		layout.main = mainRect
-		layout.editor = editorRect
+		uiLayout.header = headerRect
+		uiLayout.main = mainRect
+		uiLayout.editor = editorRect
 
 	case uiChat:
 		if m.isCompact {
@@ -2320,28 +2321,28 @@ func (m *UI) generateLayout(w, h int) layout {
 			// ------
 			// help
 			const compactHeaderHeight = 1
-			headerRect, mainRect := uv.SplitVertical(appRect, uv.Fixed(compactHeaderHeight))
+			headerRect, mainRect := layout.SplitVertical(appRect, layout.Fixed(compactHeaderHeight))
 			detailsHeight := min(sessionDetailsMaxHeight, area.Dy()-1) // One row for the header
-			sessionDetailsArea, _ := uv.SplitVertical(appRect, uv.Fixed(detailsHeight))
-			layout.sessionDetails = sessionDetailsArea
-			layout.sessionDetails.Min.Y += compactHeaderHeight // adjust for header
+			sessionDetailsArea, _ := layout.SplitVertical(appRect, layout.Fixed(detailsHeight))
+			uiLayout.sessionDetails = sessionDetailsArea
+			uiLayout.sessionDetails.Min.Y += compactHeaderHeight // adjust for header
 			// Add one line gap between header and main content
 			mainRect.Min.Y += 1
-			mainRect, editorRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-editorHeight))
+			mainRect, editorRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-editorHeight))
 			mainRect.Max.X -= 1 // Add padding right
-			layout.header = headerRect
+			uiLayout.header = headerRect
 			pillsHeight := m.pillsAreaHeight()
 			if pillsHeight > 0 {
 				pillsHeight = min(pillsHeight, mainRect.Dy())
-				chatRect, pillsRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-pillsHeight))
-				layout.main = chatRect
-				layout.pills = pillsRect
+				chatRect, pillsRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-pillsHeight))
+				uiLayout.main = chatRect
+				uiLayout.pills = pillsRect
 			} else {
-				layout.main = mainRect
+				uiLayout.main = mainRect
 			}
 			// Add bottom margin to main
-			layout.main.Max.Y -= 1
-			layout.editor = editorRect
+			uiLayout.main.Max.Y -= 1
+			uiLayout.editor = editorRect
 		} else {
 			// Layout
 			//
@@ -2352,40 +2353,40 @@ func (m *UI) generateLayout(w, h int) layout {
 			// ----------
 			// help
 
-			mainRect, sideRect := uv.SplitHorizontal(appRect, uv.Fixed(appRect.Dx()-sidebarWidth))
+			mainRect, sideRect := layout.SplitHorizontal(appRect, layout.Fixed(appRect.Dx()-sidebarWidth))
 			// Add padding left
 			sideRect.Min.X += 1
-			mainRect, editorRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-editorHeight))
+			mainRect, editorRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-editorHeight))
 			mainRect.Max.X -= 1 // Add padding right
-			layout.sidebar = sideRect
+			uiLayout.sidebar = sideRect
 			pillsHeight := m.pillsAreaHeight()
 			if pillsHeight > 0 {
 				pillsHeight = min(pillsHeight, mainRect.Dy())
-				chatRect, pillsRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-pillsHeight))
-				layout.main = chatRect
-				layout.pills = pillsRect
+				chatRect, pillsRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-pillsHeight))
+				uiLayout.main = chatRect
+				uiLayout.pills = pillsRect
 			} else {
-				layout.main = mainRect
+				uiLayout.main = mainRect
 			}
 			// Add bottom margin to main
-			layout.main.Max.Y -= 1
-			layout.editor = editorRect
+			uiLayout.main.Max.Y -= 1
+			uiLayout.editor = editorRect
 		}
 	}
 
-	if !layout.editor.Empty() {
+	if !uiLayout.editor.Empty() {
 		// Add editor margins 1 top and bottom
 		if len(m.attachments.List()) == 0 {
-			layout.editor.Min.Y += 1
+			uiLayout.editor.Min.Y += 1
 		}
-		layout.editor.Max.Y -= 1
+		uiLayout.editor.Max.Y -= 1
 	}
 
-	return layout
+	return uiLayout
 }
 
-// layout defines the positioning of UI elements.
-type layout struct {
+// uiLayout defines the positioning of UI elements.
+type uiLayout struct {
 	// area is the overall available area.
 	area uv.Rectangle