Skip to main content

Loading & busy state

Most of the busy feedback in a semantic-ui app is automatic. This page covers the behaviour that spans every node type; for the nodes themselves see spinner and progress.

Automatic inline loading​

Any control that dispatches a trigger — a button, an action rendered as a link, a form submit — gets an is-loading class while its request is in flight. The CSS paints a small spinner on it and blocks a second click; the class is removed when the request settles. Nothing to configure:

// Clicking this shows a spinner on the button until the POST resolves.
UiAction.primary("save", "Save").icon("save")
.onClick(UiTrigger.api("POST", "/products"));

A link can dispatch too: give link an onClick and it fires a fetch/patch — and gets the same inline loading — instead of navigating. href stays as the no-JS fallback:

UiLink.of("more", "/items?page=2", "Load more")
.onClick(UiTrigger.api("GET", "/items?page=2"));

The loading policy​

Inline feedback and the global loading indicator share one policy:

bus.setLoadingPolicy("manual"); // suppresses both the global bar and inline spinners

"auto" (the default) shows it on every dispatch. A predicate (ctx) => boolean decides per trigger — useful for a chat or streaming surface that manages its own affordances.

When the server owns the state​

The automatic behaviour covers this control's own click is in flight. When the button must stay busy across a re-render, or look busy without a click, put it in the model with loading:

UiAction.primary("save", "Saving…").loading(true); // rendered busy + disabled

The typical flow: the click returns a patch replacing the button with loading: true, and a later patch replaces it again with the finished button.

See also​

  • spinner — the standalone busy indicator.
  • progress — determinate and indeterminate bars and rings, and how to drive them from the server.
  • Triggers & actions — what a dispatch actually does.