@@ -4,6 +4,8 @@ import (
44 "charm.land/bubbles/v2/key"
55 tea "charm.land/bubbletea/v2"
66 "charm.land/lipgloss/v2"
7+ "github.com/charmbracelet/crush/internal/ui/common"
8+ uv "github.com/charmbracelet/ultraviolet"
79)
810
911// CloseKey is the default key binding to close dialogs.
@@ -12,35 +14,11 @@ var CloseKey = key.NewBinding(
1214 key.WithHelp("esc", "exit"),
1315)
1416
15−// OverlayKeyMap defines key bindings for dialogs.
16−type OverlayKeyMap struct {
17− Close key.Binding
18−}
19−
20−// ActionType represents the type of action taken by a dialog.
21−type ActionType int
22−
23−const (
24− // ActionNone indicates no action.
25− ActionNone ActionType = iota
26− // ActionClose indicates that the dialog should be closed.
27− ActionClose
28− // ActionSelect indicates that an item has been selected.
29− ActionSelect
30−)
31−
32−// Action represents an action taken by a dialog.
33−// It can be used to signal closing or other operations.
34−type Action struct {
35− Type ActionType
36− Payload any
37−}
38−
3917// Dialog is a component that can be displayed on top of the UI.
4018type Dialog interface {
4119 ID() string
42− Update(msg tea.Msg) (Action, tea.Cmd)
43− Layer() *lipgloss.Layer
20+ Update(msg tea.Msg) tea.Cmd
21+ View() string
4422}
4523
4624// Overlay manages multiple dialogs as an overlay.
@@ -122,27 +100,26 @@ func (d *Overlay) Update(msg tea.Msg) (*Overlay, tea.Cmd) {
122100 }
123101 }
124102
125− action, cmd := dialog.Update(msg)
126− switch action.Type {
127− case ActionClose:
103+ if cmd := dialog.Update(msg); cmd != nil {
128104 // Close the current dialog
129105 d.removeDialog(idx)
130106 return d, cmd
131− case ActionSelect:
132− // Pass the action up (without modifying the dialog stack)
133− return d, cmd
134107 }
135108
136− return d, cmd
109+ return d, nil
137110}
138111
139−// Layers returns the current stack of dialogs as lipgloss layers.
140−func (d *Overlay) Layers() []*lipgloss.Layer {
141− layers := make([]*lipgloss.Layer, len(d.dialogs))
142− for i, dialog := range d.dialogs {
143− layers[i] = dialog.Layer()
112+// Draw renders the overlay and its dialogs.
113+func (d *Overlay) Draw(scr uv.Screen, area uv.Rectangle) {
114+ for _, dialog := range d.dialogs {
115+ view := dialog.View()
116+ viewWidth := lipgloss.Width(view)
117+ viewHeight := lipgloss.Height(view)
118+ center := common.CenterRect(area, viewWidth, viewHeight)
119+ if area.Overlaps(center) {
120+ uv.NewStyledString(view).Draw(scr, center)
121+ }
144122 }
145− return layers
146123}
147124
148125// removeDialog removes a dialog from the stack.