Button
Six variants × seven sizes × any color, options-driven.
One button, configured by ButtonOpts. State lives in the caller's
widget.Clickable; every visual state below walks the theme's tokens and scale
steps, so a custom theme restyles all of it. Pressing nudges the button 1dp down — the same
tactile response on every variant; the pointer cursor signals interactivity. Anchor-style
rendering (as-link) and RTL are "from the web": a Link-variant button IS the link here, and RTL
layout is not yet supported by the toolkit.
Installation
Use the module import (the default), or own the source: lotusui add
vendors the component into your app and lotusui update keeps the copy mergeable —
see Registry.
go get github.com/ikaito-com/lotusui
# or vendor the source into your app:
go run github.com/ikaito-com/lotusui/cmd/lotusui add button
Usage
var save widget.Clickable
if save.Clicked(gtx) { /* … */ }
lotusui.Button(th, &save, "Button", lotusui.ButtonOpts{})
Secondary
The muted solid for auxiliary actions — quiet next to a Default.
lotusui.Button(th, &b, "Secondary", lotusui.ButtonOpts{Variant: lotusui.ButtonSecondary})
Destructive
The danger solid — Delete-class actions exclusively.
lotusui.Button(th, &b, "Destructive", lotusui.ButtonOpts{Variant: lotusui.ButtonDestructive})
Outline
Bordered with quiet ink; fills faintly on hover.
lotusui.Button(th, &b, "Outline", lotusui.ButtonOpts{Variant: lotusui.ButtonOutline})
Ghost
No chrome until hovered — toolbars, dense rows.
lotusui.Button(th, &b, "Ghost", lotusui.ButtonOpts{Variant: lotusui.ButtonGhost})
Link
Primary ink only; underlines on hover, like the link it imitates.
lotusui.Button(th, &b, "Link", lotusui.ButtonOpts{Variant: lotusui.ButtonLink})
Icon
An empty label with IconStart renders an icon-only, square-padded
button.
lotusui.Button(th, &b, "", lotusui.ButtonOpts{
Variant: lotusui.ButtonOutline, IconStart: lotusui.IconSettings})
With icon
IconStart/IconEnd render beside the label, tinted with
the button's own ink and sized to its text.
lotusui.Button(th, &add, "Add item", lotusui.ButtonOpts{IconStart: lotusui.IconAdd})
lotusui.Button(th, &next, "Continue", lotusui.ButtonOpts{
Variant: lotusui.ButtonOutline, IconEnd: lotusui.IconExpand})
Rounded
Rounded renders the pill form — full-round corners on any variant.
lotusui.Button(th, &b, "Rounded", lotusui.ButtonOpts{Rounded: true})
Loading
Loading disables input and shows a spinner over the label (width
preserved); LoadingText swaps the label instead, spinner at the start.
lotusui.Button(th, &save, "Save", lotusui.ButtonOpts{Loading: saving})
lotusui.Button(th, &save, "Save", lotusui.ButtonOpts{
Loading: saving, LoadingText: "Saving…"})
Sizes
Seven presets on the shared Size scale — 2XS through
2XL, text and padding moving together.
lotusui.Button(th, &btn, "2XS", lotusui.ButtonOpts{Size: lotusui.Size2XS})
lotusui.Button(th, &btn, "2XL", lotusui.ButtonOpts{Size: lotusui.Size2XL})
Color
Color re-colors any variant from a ColorScale — one
anchor in, the whole interaction ladder out (.500 base, .600 hover, .700 pressed): a custom
color can never fall out of step with its hover and pressed states.
lotusui.Button(th, &go1, "Teal", lotusui.ButtonOpts{Color: lotusui.Teal})
lotusui.Button(th, &go2, "Brand", lotusui.ButtonOpts{Color: lotusui.ScaleFrom(brand)})
Scheme
Scheme wins over Color and the variant's role scheme:
full manual control of every slot.
soft := lotusui.Teal.SoftScheme()
lotusui.Button(th, &go1, "Go", lotusui.ButtonOpts{Scheme: &soft})
Disabled
lotusui.Button(th, &btn, "Disabled", lotusui.ButtonOpts{Disabled: true})
Cursor
Buttons render the pointer cursor whenever they are enabled — interactivity is signalled by the cursor, the hover fill, and the press nudge together. Disabled buttons drop all three.
Group
There is no group component on purpose: HStack IS the group —
buttons are widgets, so grouping is ordinary composition. (An attached, shared-border group is
on the roadmap.)
lotusui.HStack(th.Space.SM,
lotusui.Button(th, &cancel, "Cancel", lotusui.ButtonOpts{Variant: lotusui.ButtonOutline}),
lotusui.Button(th, &save, "Save", lotusui.ButtonOpts{}),
)
Keyboard focus
A focused button renders a 2dp ring in the theme's FocusRing token —
focus is never signalled by color alone. FullWidth makes any button span the
column; RightAligned anchors a dialog's button row to the right edge.
API
| Option | Type | Description |
|---|---|---|
Variant | ButtonVariant | ButtonDefault (default), ButtonSecondary, ButtonDestructive, ButtonOutline, ButtonGhost, ButtonLink. |
Size | Size | Size2XS … Size2XL, SizeMD default — the shared size presets. |
Color | ColorScale | Re-colors the variant from a scale; the interaction ladder derives from it. |
Scheme | *Scheme | Wins over Color: full manual slot control — e.g. Teal.SoftScheme(). |
IconStart / IconEnd | string | Embedded icon names beside the label; empty label + IconStart = icon-only. |
Rounded | bool | The pill form — full-round corners. |
Loading | bool | Spinner over the label (width kept), input off. |
LoadingText | string | Replaces the label while Loading, spinner at the start. |
Disabled | bool | Renders quietly and swallows clicks. |