Skip to main content

Dialog

Dialog is a modal overlay that renders a bordered, centred panel on top of the rest of the UI. While a dialog is visible:

  • keyboard focus is confined to its subtree (Tab / arrow keys cannot reach the background)
  • a full-screen scrim is painted behind the panel to dim the background
import "github.com/antoniocali/oat-latte/widget"

Constructor

dlg := widget.NewDialog("Title")

No style argument is needed — colours and border are filled in by the active theme via ApplyTheme. Use WithStyle to override specific fields.

Builder methods

MethodDescription
WithChild(c oat.Component) *DialogSets the body component rendered inside the border
WithID(id string) *DialogSets the widget ID for canvas lookup
WithTitle(title string) *DialogOverrides the title text
WithStyle(s latte.Style) *DialogOverrides visual style (theme acts as base; explicit fields take precedence)
WithMaxSize(w, h int) *DialogFixed width × height in terminal cells
WithSize(w, h DialogSize) *DialogFlexible width × height using DialogFixed or DialogPercent

Sizing

Two size helpers are available:

// Exact number of terminal cells.
widget.DialogFixed(60)

// Percentage of the available terminal dimension (1–100).
widget.DialogPercent(70)

When the terminal is resized, percent-based dialogs adapt automatically each render pass.

WithMaxSize is a shorthand for WithSize(DialogFixed(w), DialogFixed(h)). When both are called the last call wins. Default size is 60 × 20 cells.

Showing and hiding

app.ShowDialog(dlg)   // push modal overlay

// inside a button callback:
app.HideDialog() // pop topmost overlay, restore body focus

Typical usage

Fixed-size confirmation

func showConfirm(app *oat.Canvas, msg string, onYes func()) {
cancelBtn := widget.NewButton("Cancel", func() { app.HideDialog() })
okBtn := widget.NewButton("OK", func() { onYes(); app.HideDialog() })

btnRow := layout.NewHBox()
btnRow.AddChild(layout.NewHFill())
btnRow.AddChild(cancelBtn)
btnRow.AddChild(layout.NewHFill().WithMaxSize(2))
btnRow.AddChild(okBtn)

body := layout.NewPaddingUniform(layout.NewVBox(
widget.NewText(msg),
layout.NewVFill().WithMaxSize(1),
btnRow,
), 1)

app.ShowDialog(
widget.NewDialog("Confirm").
WithChild(body).
WithMaxSize(50, 9),
)
}

Percent-based form dialog

func showForm(app *oat.Canvas) {
titleIn := widget.NewEditText().
WithStyle(latte.Style{Border: latte.BorderExplicitNone}).
WithHint("Title").
WithPlaceholder("Enter title…")

bodyIn := widget.NewMultiLineEditText().
WithStyle(latte.Style{Border: latte.BorderExplicitNone}).
WithHint("Body").
WithPlaceholder("Write here…")

cancelBtn := widget.NewButton("Cancel", func() { app.HideDialog() })
saveBtn := widget.NewButton("Save", func() { /* save logic */ app.HideDialog() })

btnRow := layout.NewHBox()
btnRow.AddChild(layout.NewHFill())
btnRow.AddChild(cancelBtn)
btnRow.AddChild(layout.NewHFill().WithMaxSize(2))
btnRow.AddChild(saveBtn)

form := layout.NewVBox(titleIn)
form.AddFlexChild(bodyIn, 1)
form.AddChild(layout.NewVFill().WithMaxSize(1))
form.AddChild(btnRow)

app.ShowDialog(
widget.NewDialog("New Item").
WithChild(layout.NewPaddingUniform(form, 1)).
WithSize(widget.DialogPercent(60), widget.DialogPercent(70)),
)
}

Theme tokens

TokenApplied to
DialogBorder and background of the dialog panel
DialogTitleTitle text rendered into the top border rule
ScrimFull-screen backdrop painted behind the dialog

ApplyTheme uses the theme-as-base merge pattern — fields you set explicitly via WithStyle are preserved:

func (d *Dialog) ApplyTheme(t latte.Theme) {
d.Style = t.Dialog.Merge(d.Style) // theme is base; caller-set fields win
d.titleStyle = t.DialogTitle
d.scrimStyle = t.Scrim
}