Buttons and actions
Actions are what the user taps to make something happen. Bellui has one
general Button
and several specialised buttons for the MD3 patterns.
Which one to use
| You want | Use |
|---|---|
| A labelled action, the default choice | Button |
| The single most important action on a screen, floating above content | FAB (NewFAB, NewExtendedFAB) |
| A floating button that opens several related actions | FABMenu |
| A compact action shown only as an icon | IconButton |
| A choice between 2 to 5 mutually exclusive options | SegmentedButton |
| A main action with alternatives in a drop-down | SplitButton |
| Several related actions joined into one shape | ButtonGroup |
| Small actions, filters or tags among content | Chip |
| A row of icon actions along the top of a window | Toolbar |
Button
widget.NewButton
takes a label and a function that runs when the button is tapped.
NewButtonWithIcon adds a leading icon.
save := widget.NewButton("Save", func() {
status.SetText("Saved")
})
open := widget.NewButtonWithIcon("Open", theme.FolderOpenIcon(), say("Open"))Space activates a focused button, as a tap does. SetText and SetIcon
change the button later and are safe to call from any goroutine. Pass nil
to SetIcon to remove the icon.
Styles
The Style field picks one of the MD3 button variants:
filled := widget.NewButton("Filled", say("Filled"))
filled.Style = widget.ButtonStyleFilled
tonal := widget.NewButton("Tonal", say("Tonal"))
tonal.Style = widget.ButtonStyleFilledTonal
elevated := widget.NewButton("Elevated", say("Elevated"))
elevated.Style = widget.ButtonStyleElevated
outlined := widget.NewButton("Outlined", say("Outlined"))
outlined.Style = widget.ButtonStyleOutlined
text := widget.NewButton("Text", say("Text"))
text.Style = widget.ButtonStyleText| Style | Looks like |
|---|---|
ButtonStyleFilled | Primary colour fill, the strongest emphasis |
ButtonStyleFilledTonal | Secondary container fill |
ButtonStyleElevated | Low surface fill with primary-coloured text |
ButtonStyleOutlined | A border and primary-coloured text |
ButtonStyleText | Primary-coloured text only, the lightest emphasis |
Importance
When Style is left at ButtonStyleDefault, the Importance field chooses
the colours instead:
HighImportancedraws the button asButtonStyleFilled.MediumImportance(the default) andLowImportancedraw it asButtonStyleFilledTonal.DangerImportance,WarningImportanceandSuccessImportancefill it with the theme’s error, warning and success colours.
A Style other than the default wins over Importance.
del := widget.NewButtonWithIcon("Delete", theme.DeleteIcon(), say("Deleted"))
del.Importance = widget.DangerImportance
next := widget.NewButtonWithIcon("Next", theme.NavigateNextIcon(), say("Next"))
next.Importance = widget.HighImportance
next.IconPlacement = widget.ButtonIconTrailingTextAlignment moves the icon and text to the leading or trailing edge
(ButtonAlignLeading, ButtonAlignTrailing), and IconPlacement puts the
icon after the text with ButtonIconTrailingText.
Icon buttons
IconButton
shows only an icon. Its Style is IconButtonStyleStandard (no background),
IconButtonStyleFilled, IconButtonStyleFilledTonal or
IconButtonStyleOutlined.
settings := widget.NewIconButton(theme.SettingsIcon(), say("Settings"))
settings.SetAccessibilityLabel("Settings")
settings.SetToolTipText("Settings")
add := widget.NewIconButton(theme.ContentAddIcon(), say("Add"))
add.Style = widget.IconButtonStyleFilledAn icon button has no text, so screen readers have nothing to announce. Give
it a name with SetAccessibilityLabel, and a hover hint with
SetToolTipText.
Button groups, segmented and split buttons
group := widget.NewButtonGroup(
widget.NewButton("Cut", say("Cut")),
widget.NewButton("Copy", say("Copy")),
widget.NewButton("Paste", say("Paste")),
)
period := widget.NewSegmentedButton([]string{"Day", "Week", "Month"}, func(i int) {
status.SetText(fmt.Sprintf("Segment %d", i))
})
period.Selected = 1
split := widget.NewSplitButton("Export", say("Export"), []*bellui.MenuItem{
bellui.NewMenuItem("Export as PDF", say("PDF")),
bellui.NewMenuItem("Export as CSV", say("CSV")),
})ButtonGroupjoins ordinary buttons into one connected shape. Each button keeps its ownOnTapped.SegmentedButtonshows a row of labels and keeps exactly one selected.OnChangedreceives the index of the new selection, andSelectedholds it (index 0 afterNewSegmentedButton; -1 selects nothing). When it has focus, the left and right arrow keys move the selection.SplitButtonhas a main action and an arrow that opens a menu ofbellui.MenuItemalternatives.
Floating action buttons
A FAB is the
floating button for a screen’s main action. NewFAB makes an icon-only
FAB. NewExtendedFAB adds a label. Style picks the colour:
FABStylePrimary (the default), FABStyleSurface, FABStyleSecondary or
FABStyleTertiary.
compose := widget.NewExtendedFAB("Compose", theme.MailComposeIcon(), func() {
status.SetText("Compose")
})
compose.Style = widget.FABStyleTertiaryA FAB is an ordinary widget, so you place it with a layout like any other. To keep it in a corner, put it at the end of a box with a spacer before it.
FAB menu
FABMenu
is the MD3 speed dial: a list of labelled mini FABs that opens over the
content. It is not a widget you place in a layout. You open it with
Show, Toggle or close it with Hide, giving the canvas and a position.
The menu opens above and to the left of that position. Tapping an item
closes the menu and calls its OnTapped.
menu := widget.NewFABMenu(theme.ContentAddIcon(), []*widget.FABMenuItem{
{Label: "Photo", Icon: theme.MediaPhotoIcon(), OnTapped: func() { status.SetText("Photo") }},
{Label: "Document", Icon: theme.DocumentIcon(), OnTapped: func() { status.SetText("Document") }},
})
var add *widget.FAB
add = widget.NewFAB(theme.ContentAddIcon(), func() {
// The menu opens above and to the left of the point you pass:
// here, the FAB's top-right corner in window coordinates.
pos := bellui.CurrentApp().Driver().AbsolutePositionForObject(add)
menu.Toggle(w.Canvas(), pos.AddXY(add.Size().Width, 0))
})Chips
A Chip is a
small rounded label. Its Style decides what it is for:
ChipStyleAssist(fromNewChip): an action, with an optional leadingIcon.ChipStyleFilter(fromNewFilterChip): a toggle. Each tap flipsSelected, fills the chip with the secondary container colour while it is selected, and calls your function with the new state.ChipStyleInput: a tag the user can remove. SetOnDeleted; a tap on the trailing close mark calls it, and a tap anywhere else callsOnTapped.ChipStyleSuggestion: an outlined label, drawn the same way as an assist chip.
There is no constructor for input and suggestion chips, so build them as a struct literal.
directions := widget.NewChip("Directions", func() {
status.SetText("Directions")
})
directions.Icon = theme.NavigateNextIcon()
running := widget.NewFilterChip("Running", func(on bool) {
status.SetText(fmt.Sprint("Running: ", on))
})
running.Selected = true
tags := container.NewHBox()
tag := &widget.Chip{Text: "golang", Style: widget.ChipStyleInput}
tag.ExtendBaseWidget(tag)
tag.OnDeleted = func() {
tags.Remove(tag)
}
tags.Add(tag)Toolbar
Toolbar
lays out a row of toolbar items:
NewToolbarAction(icon, func): an icon button. It hasDisable,EnableandSetIcon.NewTwoStateToolbarAction(offIcon, onIcon, func(on bool)): a toggle that swaps icons, such as play and pause.SetOnchanges the state from code.NewToolbarSeparator(): a thin divider between groups.NewToolbarSpacer(): empty space that stretches, which pushes the items after it to the far end. Several spacers share the space equally.
undo := widget.NewToolbarAction(theme.ContentUndoIcon(), func() {
status.SetText("Undo")
})
play := widget.NewTwoStateToolbarAction(theme.MediaPlayIcon(), theme.MediaPauseIcon(),
func(on bool) {
status.SetText(fmt.Sprint("Playing: ", on))
})
bar := widget.NewToolbar(
widget.NewToolbarAction(theme.DocumentCreateIcon(), func() { status.SetText("New") }),
widget.NewToolbarAction(theme.DocumentSaveIcon(), func() { status.SetText("Save") }),
widget.NewToolbarSeparator(),
undo,
play,
widget.NewToolbarSpacer(),
widget.NewToolbarAction(theme.HelpIcon(), func() { status.SetText("Help") }),
)
undo.Disable()Append and Prepend add items after the toolbar is created.