core/button/widget.go
Functions
func Children
func (w *Widget) Children() []widget.Widget {
return nil
}
func Draw
Draw renders the button to the canvas.
func (w *Widget) Draw(ctx widget.Context, canvas widget.Canvas) {
w.painter.PaintButton(canvas, PaintState{
Text: w.cfg.ResolvedText(),
Variant: w.cfg.variant,
Size: w.cfg.size,
Hovered: w.state == stateHover,
Pressed: w.state == statePressed,
Focused: w.IsFocused(),
Disabled: w.cfg.ResolvedDisabled(),
Bounds: w.Bounds(),
Background: w.cfg.background,
Radius: w.cfg.rounded,
})
}
func Event
Event handles an input event and returns true if consumed.
func (w *Widget) Event(ctx widget.Context, e event.Event) bool {
return handleEvent(w, ctx, e)
}
func IsFocusable
IsFocusable reports whether the button can currently receive focus.
A button is focusable when it is visible, enabled, and not disabled.
func (w *Widget) IsFocusable() bool {
return w.IsVisible() && w.IsEnabled() && !w.cfg.ResolvedDisabled()
}
func Layout
Layout calculates the button's preferred size within the given constraints.
func (w *Widget) Layout(_ widget.Context, constraints geometry.Constraints) geometry.Size {
height := sizeHeight(w.cfg.size)
// Estimate text width: approximate at ~7px per character for medium font.
text := w.cfg.ResolvedText()
fontSize := sizeFontSize(w.cfg.size)
textWidth := float32(len(text)) * fontSize * charWidthRatio
totalWidth := textWidth + w.paddingX*2
totalHeight := height
// Apply min/max width overrides.
if w.minWidth > 0 && totalWidth < w.minWidth {
totalWidth = w.minWidth
}
if w.maxWidth > 0 && totalWidth > w.maxWidth {
totalWidth = w.maxWidth
}
// Ensure height accounts for vertical padding.
if totalHeight < w.paddingY*2 {
totalHeight = w.paddingY * 2
}
preferred := geometry.Sz(totalWidth, totalHeight)
return constraints.Constrain(preferred)
}
func Mount
Mount creates signal bindings for push-based invalidation.
Implements [widget.Lifecycle].
func (w *Widget) Mount(ctx widget.Context) {
sched := ctx.Scheduler()
if sched == nil {
return
}
if w.cfg.readonlyTextSignal != nil {
b := state.BindToScheduler(w.cfg.readonlyTextSignal, w, sched)
w.AddBinding(b)
} else if w.cfg.textSignal != nil {
b := state.BindToScheduler(w.cfg.textSignal, w, sched)
w.AddBinding(b)
}
if w.cfg.readonlyDisabledSignal != nil {
b := state.BindToScheduler(w.cfg.readonlyDisabledSignal, w, sched)
w.AddBinding(b)
} else if w.cfg.disabledSignal != nil {
b := state.BindToScheduler(w.cfg.disabledSignal, w, sched)
w.AddBinding(b)
}
}
func New
New creates a new button Widget with the given options.
The returned widget is visible, enabled, and focusable by default.
Use options to configure text, click handler, variant, and size.
func New(opts ...Option) *Widget {
w := &Widget{
paddingX: defaultPaddingX,
paddingY: defaultPaddingY,
painter: DefaultPainter{},
}
w.SetVisible(true)
w.SetEnabled(true)
// Default size is Medium.
w.cfg.size = Medium
for _, opt := range opts {
opt(&w.cfg)
}
// Apply painter from config if set.
if w.cfg.painter != nil {
w.painter = w.cfg.painter
}
return w
}
func Unmount
Unmount is called when the button is removed from the widget tree.
Implements [widget.Lifecycle].
func (w *Widget) Unmount() {
// Bindings are cleaned up automatically by WidgetBase.CleanupBindings().
}
Structs
type Widget struct
Widget implements a clickable button with configurable appearance and behavior.
A button is created with [New] using functional options:
btn := button.New(
button.Text("Submit"),
button.OnClick(handleSubmit),
button.VariantOpt(button.Filled),
)
Fluent styling methods may be chained after construction:
btn.Padding(16).Background(theme.Primary).Rounded(8)
type Widget struct {
widget.WidgetBase
cfg config
state interactionState
painter Painter
// Styling overrides set via fluent methods.
paddingX float32
paddingY float32
minWidth float32
maxWidth float32
}
Children returns nil because a button is a leaf widget.