ActionButton
Use ActionButton for save, retry, refresh, download or any other action worth reporting on. It runs a sync or async action, walks itself through ready → pending → success | error, blocks duplicate activation while pending, hands the result or the thrown error to callbacks and snippets, and returns to ready after reset_ms. Set reset_ms={0} to keep the terminal state until the next activation.
The button reserves the width of its widest label up front, so swapping Save for Saving… never nudges the layout around it.
States and labels
labels maps each of the four states to { icon?, text? }. text renders as text, so markup in it shows up literally — pass an icon for a glyph, or take over rendering entirely with the children snippet.
bind:state exposes the current state, and on_success / on_error receive the resolved value or the thrown error. The demo below fails every second run so you can watch the error path and the reset_ms countdown back to ready.
Custom rendering
The children snippet receives { state, icon, text, disabled, result, error } and replaces the default icon-plus-text body, which is the way to render markup, a spinner or the result itself inside the button. as swaps the underlying element when a <button> will not do.
CopyButton
CopyButton composes ActionButton into a copy-to-clipboard control with bindable state, custom labels, success/error callbacks and configurable reset timing. This site mounts one in global mode on every code block.