Skip to content

Spinner

Spinner

Sizes

Inline with Text

Loading content...
Fetching data
import { Spinner } from "@f0rbit/ui";
<Spinner />
<Spinner size="sm" />
<Spinner size="lg" />
<span style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
<Spinner size="sm" />
Loading...
</span>

Replace button content with a spinner during async operations:

const [loading, setLoading] = createSignal(false);
const handleSubmit = async () => {
setLoading(true);
await submitForm();
setLoading(false);
};
<Button onClick={handleSubmit} disabled={loading()}>
{loading() ? (
<>
<Spinner size="sm" />
Saving...
</>
) : (
"Save changes"
)}
</Button>

For multiple button states:

<div class="cluster">
<Button disabled={loading()}>
{loading() ? <Spinner size="sm" /> : null}
{loading() ? "Loading..." : "Submit"}
</Button>
<Button variant="secondary" disabled={loading()}>
Cancel
</Button>
</div>

Display a centered spinner for page-level loading:

const PageLoader = () => (
<div
style={{
display: "flex",
"flex-direction": "column",
"align-items": "center",
"justify-content": "center",
"min-height": "50vh",
gap: "1rem",
}}
>
<Spinner size="lg" />
<p style={{ color: "var(--text-secondary)" }}>Loading your dashboard...</p>
</div>
);
const Dashboard = () => {
const [data] = createResource(fetchDashboardData);
return (
<Show when={!data.loading} fallback={<PageLoader />}>
<DashboardContent data={data()} />
</Show>
);
};

For a full-screen overlay:

const FullScreenLoader = () => (
<div
style={{
position: "fixed",
inset: 0,
display: "flex",
"align-items": "center",
"justify-content": "center",
"background-color": "var(--bg-primary)",
"z-index": 50,
}}
>
<div class="stack" style={{ "align-items": "center" }}>
<Spinner size="lg" />
<p>Please wait...</p>
</div>
</div>
);
PropTypeDefaultDescription
size"sm" | "md" | "lg""md"Size of the spinner