@@ -47,6 +47,7 @@ import (
4747 "github.com/charmbracelet/crush/internal/ui/util"
4848 "github.com/charmbracelet/crush/internal/version"
4949 uv "github.com/charmbracelet/ultraviolet"
50+ "github.com/charmbracelet/ultraviolet/layout"
5051 "github.com/charmbracelet/ultraviolet/screen"
5152 "github.com/charmbracelet/x/editor"
5253)
@@ -135,7 +136,7 @@ type UI struct {
135136 // The width and height of the terminal in cells.
136137 width int
137138 height int
138− layout layout
139+ layout uiLayout
139140
140141 isTransparent bool
141142
@@ -2235,7 +2236,7 @@ func (m *UI) updateSize() {
22352236
22362237// generateLayout calculates the layout rectangles for all UI components based
22372238// on the current UI state and terminal dimensions.
2238−func (m *UI) generateLayout(w, h int) layout {
2239+func (m *UI) generateLayout(w, h int) uiLayout {
22392240 // The screen area we're working with
22402241 area := image.Rect(0, 0, w, h)
22412242
@@ -2256,7 +2257,7 @@ func (m *UI) generateLayout(w, h int) layout {
22562257 }
22572258
22582259 // Add app margins
2259− appRect, helpRect := uv.SplitVertical(area, uv.Fixed(area.Dy()-helpHeight))
2260+ appRect, helpRect := layout.SplitVertical(area, layout.Fixed(area.Dy()-helpHeight))
22602261 appRect.Min.Y += 1
22612262 appRect.Max.Y -= 1
22622263 helpRect.Min.Y -= 1
@@ -2269,7 +2270,7 @@ func (m *UI) generateLayout(w, h int) layout {
22692270 appRect.Max.X -= 1
22702271 }
22712272
2272− layout := layout{
2273+ uiLayout := uiLayout{
22732274 area: area,
22742275 status: helpRect,
22752276 }
@@ -2285,9 +2286,9 @@ func (m *UI) generateLayout(w, h int) layout {
22852286 // ------
22862287 // help
22872288
2288− headerRect, mainRect := uv.SplitVertical(appRect, uv.Fixed(landingHeaderHeight))
2289− layout.header = headerRect
2290− layout.main = mainRect
2289+ headerRect, mainRect := layout.SplitVertical(appRect, layout.Fixed(landingHeaderHeight))
2290+ uiLayout.header = headerRect
2291+ uiLayout.main = mainRect
22912292
22922293 case uiLanding:
22932294 // Layout
@@ -2299,14 +2300,14 @@ func (m *UI) generateLayout(w, h int) layout {
22992300 // editor
23002301 // ------
23012302 // help
2302− headerRect, mainRect := uv.SplitVertical(appRect, uv.Fixed(landingHeaderHeight))
2303− mainRect, editorRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-editorHeight))
2303+ headerRect, mainRect := layout.SplitVertical(appRect, layout.Fixed(landingHeaderHeight))
2304+ mainRect, editorRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-editorHeight))
23042305 // Remove extra padding from editor (but keep it for header and main)
23052306 editorRect.Min.X -= 1
23062307 editorRect.Max.X += 1
2307− layout.header = headerRect
2308− layout.main = mainRect
2309− layout.editor = editorRect
2308+ uiLayout.header = headerRect
2309+ uiLayout.main = mainRect
2310+ uiLayout.editor = editorRect
23102311
23112312 case uiChat:
23122313 if m.isCompact {
@@ -2320,28 +2321,28 @@ func (m *UI) generateLayout(w, h int) layout {
23202321 // ------
23212322 // help
23222323 const compactHeaderHeight = 1
2323− headerRect, mainRect := uv.SplitVertical(appRect, uv.Fixed(compactHeaderHeight))
2324+ headerRect, mainRect := layout.SplitVertical(appRect, layout.Fixed(compactHeaderHeight))
23242325 detailsHeight := min(sessionDetailsMaxHeight, area.Dy()-1) // One row for the header
2325− sessionDetailsArea, _ := uv.SplitVertical(appRect, uv.Fixed(detailsHeight))
2326− layout.sessionDetails = sessionDetailsArea
2327− layout.sessionDetails.Min.Y += compactHeaderHeight // adjust for header
2326+ sessionDetailsArea, _ := layout.SplitVertical(appRect, layout.Fixed(detailsHeight))
2327+ uiLayout.sessionDetails = sessionDetailsArea
2328+ uiLayout.sessionDetails.Min.Y += compactHeaderHeight // adjust for header
23282329 // Add one line gap between header and main content
23292330 mainRect.Min.Y += 1
2330− mainRect, editorRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-editorHeight))
2331+ mainRect, editorRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-editorHeight))
23312332 mainRect.Max.X -= 1 // Add padding right
2332− layout.header = headerRect
2333+ uiLayout.header = headerRect
23332334 pillsHeight := m.pillsAreaHeight()
23342335 if pillsHeight > 0 {
23352336 pillsHeight = min(pillsHeight, mainRect.Dy())
2336− chatRect, pillsRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-pillsHeight))
2337− layout.main = chatRect
2338− layout.pills = pillsRect
2337+ chatRect, pillsRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-pillsHeight))
2338+ uiLayout.main = chatRect
2339+ uiLayout.pills = pillsRect
23392340 } else {
2340− layout.main = mainRect
2341+ uiLayout.main = mainRect
23412342 }
23422343 // Add bottom margin to main
2343− layout.main.Max.Y -= 1
2344− layout.editor = editorRect
2344+ uiLayout.main.Max.Y -= 1
2345+ uiLayout.editor = editorRect
23452346 } else {
23462347 // Layout
23472348 //
@@ -2352,40 +2353,40 @@ func (m *UI) generateLayout(w, h int) layout {
23522353 // ----------
23532354 // help
23542355
2355− mainRect, sideRect := uv.SplitHorizontal(appRect, uv.Fixed(appRect.Dx()-sidebarWidth))
2356+ mainRect, sideRect := layout.SplitHorizontal(appRect, layout.Fixed(appRect.Dx()-sidebarWidth))
23562357 // Add padding left
23572358 sideRect.Min.X += 1
2358− mainRect, editorRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-editorHeight))
2359+ mainRect, editorRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-editorHeight))
23592360 mainRect.Max.X -= 1 // Add padding right
2360− layout.sidebar = sideRect
2361+ uiLayout.sidebar = sideRect
23612362 pillsHeight := m.pillsAreaHeight()
23622363 if pillsHeight > 0 {
23632364 pillsHeight = min(pillsHeight, mainRect.Dy())
2364− chatRect, pillsRect := uv.SplitVertical(mainRect, uv.Fixed(mainRect.Dy()-pillsHeight))
2365− layout.main = chatRect
2366− layout.pills = pillsRect
2365+ chatRect, pillsRect := layout.SplitVertical(mainRect, layout.Fixed(mainRect.Dy()-pillsHeight))
2366+ uiLayout.main = chatRect
2367+ uiLayout.pills = pillsRect
23672368 } else {
2368− layout.main = mainRect
2369+ uiLayout.main = mainRect
23692370 }
23702371 // Add bottom margin to main
2371− layout.main.Max.Y -= 1
2372− layout.editor = editorRect
2372+ uiLayout.main.Max.Y -= 1
2373+ uiLayout.editor = editorRect
23732374 }
23742375 }
23752376
2376− if !layout.editor.Empty() {
2377+ if !uiLayout.editor.Empty() {
23772378 // Add editor margins 1 top and bottom
23782379 if len(m.attachments.List()) == 0 {
2379− layout.editor.Min.Y += 1
2380+ uiLayout.editor.Min.Y += 1
23802381 }
2381− layout.editor.Max.Y -= 1
2382+ uiLayout.editor.Max.Y -= 1
23822383 }
23832384
2384− return layout
2385+ return uiLayout
23852386}
23862387
2387−// layout defines the positioning of UI elements.
2388−type layout struct {
2388+// uiLayout defines the positioning of UI elements.
2389+type uiLayout struct {
23892390 // area is the overall available area.
23902391 area uv.Rectangle
23912392