Wrap anything to give it a hint on hover and keyboard focus — four sides, every colour, no request.
On icon buttons
An icon alone needs a word. tooltip= works on every component, and on an icon button it also becomes its accessible name.
Bold · Ctrl+B
Italic · Ctrl+I
Insert a link
Add an image
Checklist
deftoolbar()->None:withui.card(padding="sm",classes="w-fit"),ui.hstack(gap="xs"):ui.icon_button("bold",variant="ghost",tooltip="Bold · Ctrl+B")ui.icon_button("italic",variant="ghost",tooltip="Italic · Ctrl+I")ui.icon_button("link",variant="ghost",tooltip="Insert a link")ui.icon_button("image",variant="ghost",tooltip="Add an image")ui.icon_button("list-checks",variant="ghost",tooltip="Checklist")
Four sides
with ui.tooltip(...) wraps what it explains; position= picks the side.
Opens above
Opens below
Opens on the left
Opens on the right
defsides()->None:withui.hstack(gap="md",wrap=True,justify="center"):withui.tooltip("Opens above",position="top"):ui.button("Top",variant="outline")withui.tooltip("Opens below",position="bottom"):ui.button("Bottom",variant="outline")withui.tooltip("Opens on the left",position="left"):ui.button("Left",variant="outline")withui.tooltip("Opens on the right",position="right"):ui.button("Right",variant="outline")
Colours
Tint the hint to match what it explains.
Synced
Everything is up to date
Overdue
3 invoices are past their due date
Pro plan
Renews on 1 October
Admin
Available to admins only
defcolors()->None:withui.hstack(gap="md",wrap=True,justify="center"):withui.tooltip("Everything is up to date",color="success"):ui.badge("Synced",color="success",variant="soft",icon_left="check")withui.tooltip("3 invoices are past their due date",color="error"):ui.badge("Overdue",color="error",variant="soft",icon_left="circle-alert")withui.tooltip("Renews on 1 October",color="primary"):ui.badge("Pro plan",color="primary",variant="soft",icon_left="sparkles")withui.tooltip("Available to admins only",color="muted"):ui.badge("Admin",color="muted",variant="soft",icon_left="lock")
enabled is bindable: the switch writes a ClientState, and the next hover obeys it — in the browser, without a request.
Archive this conversation
Snooze until tomorrow, 9:00
classHints(ClientState):shown:bool=field(default=True)deftoggle_hints()->None:hints=Hints()withui.vstack(gap="md",align="center"):withui.hstack(gap="sm"):withui.tooltip("Archive this conversation",enabled=hints.shown):ui.button("Archive",icon_left="archive",variant="soft")withui.tooltip("Snooze until tomorrow, 9:00",enabled=hints.shown):ui.button("Snooze",icon_left="alarm-clock",variant="soft")ui.switch(checked=hints.shown,label="Show hints on hover")