diff --git a/frontend/src/components/Common/Loading.tsx b/frontend/src/components/Common/Loading.tsx
index 004333e..45bf845 100644
--- a/frontend/src/components/Common/Loading.tsx
+++ b/frontend/src/components/Common/Loading.tsx
@@ -1,4 +1,4 @@
-import { Loader2 } from "lucide-react"
+import { FluksioLoader } from "@/components/ui/fluksio-loader"
/**
* The router's pending screen, shown while a page's code chunk is on its way.
@@ -15,7 +15,7 @@ export function PageLoading() {
data-testid="page-loading"
className="flex min-h-64 items-center justify-center"
>
-
+
)
}
diff --git a/frontend/src/components/Common/OverviewToolbar.tsx b/frontend/src/components/Common/OverviewToolbar.tsx
index 593b5ff..6174650 100644
--- a/frontend/src/components/Common/OverviewToolbar.tsx
+++ b/frontend/src/components/Common/OverviewToolbar.tsx
@@ -1,5 +1,5 @@
import { useMutation } from "@tanstack/react-query"
-import { Check, Loader2, Plus, Search, Trash2 } from "lucide-react"
+import { Check, Plus, Search, Trash2 } from "lucide-react"
import { motion } from "motion/react"
import { type ReactNode, useRef, useState } from "react"
@@ -13,6 +13,7 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
+import { FluksioLoader } from "@/components/ui/fluksio-loader"
import { Input } from "@/components/ui/input"
import {
Tooltip,
@@ -170,7 +171,7 @@ export function OverviewToolbar({
aria-label="Publish all changes"
data-testid="publish-all"
>
- {publishing ? : }
+ {publishing ? : }
diff --git a/frontend/src/components/Dashboard/DashboardEditor.tsx b/frontend/src/components/Dashboard/DashboardEditor.tsx
index 1b6a01e..97687cb 100644
--- a/frontend/src/components/Dashboard/DashboardEditor.tsx
+++ b/frontend/src/components/Dashboard/DashboardEditor.tsx
@@ -1,14 +1,6 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { useNavigate } from "@tanstack/react-router"
-import {
- Check,
- ExternalLink,
- Loader2,
- Pencil,
- Plus,
- Settings2,
- X,
-} from "lucide-react"
+import { Check, ExternalLink, Pencil, Plus, Settings2, X } from "lucide-react"
import { motion } from "motion/react"
import { type CSSProperties, useEffect, useRef, useState } from "react"
import {
@@ -36,6 +28,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
+import { FluksioLoader } from "@/components/ui/fluksio-loader"
import {
Popover,
PopoverContent,
@@ -720,7 +713,7 @@ export function DashboardEditor({
data-testid="publish-dashboard"
>
{save.isPending || publish.isPending ? (
-
+
) : (
)}
diff --git a/frontend/src/components/Flow/FlowDock.tsx b/frontend/src/components/Flow/FlowDock.tsx
index df6003f..297add5 100644
--- a/frontend/src/components/Flow/FlowDock.tsx
+++ b/frontend/src/components/Flow/FlowDock.tsx
@@ -2,7 +2,6 @@ import { useReactFlow } from "@xyflow/react"
import {
AlertCircle,
Check,
- Loader2,
Maximize2,
Pause,
Pencil,
@@ -18,6 +17,7 @@ import { useEffect, useState } from "react"
import type { ValidationIssue } from "@/client"
import { Button } from "@/components/ui/button"
+import { FluksioLoader } from "@/components/ui/fluksio-loader"
import { Separator } from "@/components/ui/separator"
import {
Tooltip,
@@ -273,7 +273,7 @@ export function FlowDock({
data-testid="run-flow"
>
{running ? (
-
+
) : (
)}
@@ -348,7 +348,7 @@ export function FlowDock({
{!connected ? (
) : saving || publishing ? (
-
+
) : (
)}
diff --git a/frontend/src/components/ui/fluksio-loader.tsx b/frontend/src/components/ui/fluksio-loader.tsx
new file mode 100644
index 0000000..3492275
--- /dev/null
+++ b/frontend/src/components/ui/fluksio-loader.tsx
@@ -0,0 +1,44 @@
+/**
+ * FluksioLoader: the app's shared loading mark.
+ *
+ * The brand mark — four neurons in a ring — drawn as one continuous stroke
+ * that traces itself and wipes away in a loop (see the `.fluksio-loader-line`
+ * rule + `fluksio-draw` keyframes in index.css, which also guard
+ * `prefers-reduced-motion`: `MotionConfig` covers JS animations, not CSS ones).
+ * Renders a bare