Repository navigation
hint
Pulsing outline highlights for individual UI elements. Draws attention to a control without needing a full tutorial flow. Hints dismiss on click or after a timeout.
The module is exposed as wu.Hint.
local wu = GetMod("WindowUtils")
local hint = wu.Hint
local controls = wu.Controls
-- Give your control an elementId
controls.Button("Settings", "inactive", 0, 0, { elementId = "settings_btn" })
-- Show a hint on it
hint.show("settings_btn")hint.show("my_control_id")The hint pulses until the user left-clicks the target element. Only left clicks count, and the element must be reporting bounds that frame, which it does automatically while any hint is active.
hint.show("my_control_id", { dismiss = "timeout", duration = 5.0 })The hint disappears after 5 seconds regardless of user interaction.
An empty or non-string elementId is logged and ignored.
hint.hide("my_control_id")Immediately removes the hint. No-op if no hint is active for that ID.
Calling show() on an ID that already has an active hint replaces it (resets dismiss timer/mode).
hint.show("my_btn", { dismiss = "timeout", duration = 3.0 })
-- Later, switch to click-dismiss:
hint.show("my_btn", { dismiss = "click" })-- Show hint only on first use
if not hasSeenFeature then
hint.show("new_feature_btn")
endhint.show("step_1_btn")
hint.show("step_2_slider")
hint.show("step_3_combo")
-- Each dismisses independentlyHints work alongside tutorials. Both systems share the same bounds tracking infrastructure, so a control with an elementId can be targeted by either system. However, hints are fully independent of tutorial state: they render even when no tutorial is active.
| Function | Parameters | Description |
|---|---|---|
hint.show(elementId, opts?) |
elementId: string, opts: table |
Show a pulsing hint on the target element |
hint.hide(elementId) |
elementId: string |
Remove a hint immediately |
hint.shouldReport() |
- | Returns true if any hints are active (internal) |
hint.update() |
- | Process dismissals for the frame (internal, called by WindowUtils) |
hint.render() |
- | Draw the pulsing strokes (internal, called by WindowUtils) |
There is no "clear all hints" call. Track your own ids and call hide for each one.
| Field | Type | Default | Description |
|---|---|---|---|
dismiss |
"click" or "timeout"
|
"click" |
How the hint is dismissed |
duration |
number | nil | Seconds before timeout dismissal (required when dismiss = "timeout") |
"click" and "timeout" are the only values the update loop handles:
dismiss value |
Behaviour |
|---|---|
"click" (default) |
Cleared when the target is left-clicked |
"timeout" with a numeric duration
|
Cleared once duration seconds have elapsed since show()
|
"timeout" without duration
|
Never cleared automatically |
anything else, e.g. "manual" or "hover"
|
Never cleared automatically |
Unsupported values are not validated or logged, so a typo leaves the hint pulsing indefinitely. In that case only hint.hide(elementId) removes it. Hints also survive overlay close and reopen: nothing clears them on their own.
Hints share stroke settings with the tutorial system (configure via Tutorial.setSetting()):
-
strokeMin/strokeMax— outline thickness range -
pulseSpeed— animation speed -
pulseEasing— pulse curve:linear,easeIn,easeOut,easeInOut,bounce -
spotlightRoundingsets the corner rounding of the outline (negative values match the UI frame rounding)
The stroke color is fixed (teal, with opacity riding the pulse) and the outline is padded 4 pixels around the element rect. Neither is configurable.
The target element needs an elementId in its control opts. The bounds tracker only captures positions when hint.shouldReport() or tutorial.shouldReport() returns true — init.lua handles this automatically.