Osy#betaRun it on Osyrin: osyrin.com

Reference / UI

The orbs kit — thinking orbs that say what a wait is for

Orb(OrbState.Searching[, size: OrbSize.Inline][, label: "…"][, speed: 1][, paused: false][, accent: false])

`Osysharp.LoadingOrbs` draws a small dotted 3D sphere for a wait — nine states (searching, composing, weaving, connecting…) at two sizes — so a loading state says WHAT is happening instead of only that something is. A port of thinking-orbs (MIT, Jakub Antalik) to pure Osy#: themed by your tokens, still under reduced motion, idle when out of view, and announced by name.

preview1 example compiled by CIuikitanimationcanvas

Summary#

A spinner says one thing: wait. An orb says what for. Orb(OrbState.Searching) is a dotted globe with a scan line sweeping it; Orb(OrbState.Composing) is a sash of dots rolling like a line being written; Orb(OrbState.Weaving) is three strands plaiting — each a hand-tuned animation from Jakub Antalik's thinking-orbs (MIT), ported to Osy# so it is an ordinary kit: one use line, no JavaScript bundle.

app Desk {
  use Osysharp.LoadingOrbs@0;
  model "model/**/*.osy";
}

Signature#

using Osysharp.LoadingOrbs;

Orb(OrbState.Searching)                                   // 64px — beside a name, in a panel
Orb(OrbState.Composing, size: OrbSize.Inline)             // 20px — in a line of text, a button, a field
Orb(OrbState.Weaving, label: "Translating from Swedish…") // what a screen reader (and a test) hears
Orb(OrbState.Working, speed: 1.5)                         // a multiplier on the tuned speed
Orb(OrbState.Connecting, paused: true)                    // hold still on the current frame
Orb(OrbState.Shaping, accent: true)                       // drawn in the theme's accent instead of its ink

Description#

The nine states — pick the one that names the wait#

statewhat it drawslabela wait it names
Workingparticles on tilted orbitsWorking…an automation or a process running
Searchinga scan meridian sweeps a dotted globeSearching…a search, similar items, a knowledge base
Solvingbands scramble in quarter turns, then click backSolving…a rule or a check being evaluated
Listeninga waveform rolls through latitude ringsListening…voice
Connectinga constellation wires itselfConnecting…a mailbox, a channel, another service
Weavingthree strands plait around the sphereWeaving…translating
Composingan undulating multi-band sashComposing…writing a draft
Breathinga face-on ring slowly morphingThinking…idle, ready
Shapinga dotted outline, circle → triangle → squareShaping…building or formatting something

Two sizes, two designs#

OrbSize.Avatar is 64px and OrbSize.Inline is 20px. They are separate tunings, not one drawing scaled: the small one has fewer, larger dots and runs faster, so it still reads at text size.

Which colour is it?#

The theme's ink — Colors.OnSurface — so a re-themed app's orb is drawn in that app's text colour, light or dark. accent: true draws it in the theme's accent (Colors.Primary) instead, for an app whose one accent means "something is working". It takes no colour of its own: an orb in a third colour is a second accent.

When to show one#

For a wait the reader can see the reason of, and that lasts longer than about 400ms. Under that, show nothing — a spinner that flashes for a fifth of a second is noise. For content arriving in a known shape, a skeleton says more (skeleton); an orb is for a PROCESS whose result has no shape yet.

What it does for you#

  • It is drawn in your theme's ink — Colors.OnSurface, at the depth-mapped strength of the original, so it is dark on a light page, light on a dark one, and follows a mode switch on the next frame.
  • Reduced motion shows the original's representative still frame, redrawn only when the theme changes.
  • Out of view it does no work — scrolled away or in a hidden tab, it runs no frames ([[ui-canvas#offscreen]]).
  • It is sharp on a high-density screen ([[ui-canvas#density]]).
  • It has a name — role: UiRole.Graphic with its state's label, so a screen reader announces "Searching…" and a test reads it: Assert.Visible("Searching…").

The same technique, for a drawing of your own#

An orb is an ordinary component: a Canvas, an on frame body, and Draw.* in theme colours. The pieces it needs are in [[ui-canvas#themed]]; the smallest version of the idea — a lamp that breathes, still when the reader asks for less motion — compiles on its own:

theme Desk { Colors { Lamp = Modes.Of(light: "#0E9AA9", dark: "#33CAD8"); } }

[Route("/lamp")]
[AllowAnonymous]
component Lamp() {
  double t = 0;
  on frame (double dt) {
    t = Theme.ReducedMotion() ? 0 : t + dt;
    var ring = 0.5 + 0.5 * Math.Sin(t * 2.6);
    Draw.Clear();
    Draw.Alpha(0.3 * (1 - ring));
    Draw.Circle(10, 10, 4 + 5 * ring, Colors.Lamp);
    Draw.Alpha(1);
    Draw.Circle(10, 10, 4, Colors.Lamp);
  }
  render { Canvas(w: 20, h: 20, density: 2, role: UiRole.Graphic, label: "Live"); }
}

Credit#

The geometry, the nine tunings and the golden vectors the kit's tests are generated from are Jakub Antalik's, under the MIT licence; kits/loading-orbs/LICENSE carries the notice. The port is checked number for number against the original's own golden vectors (kits/loading-orbs/tests/golden.test.osy).

See also#

Related

Canvas

A drawing surface, and the verbs that paint on it. Put a `Canvas` in a render block, call `Draw.*` from an `on frame`…

animation — keyframe motion, on entry, on exit, in a loop, or as it scrolls into view

An `animation` block declares reusable keyframe motion — an entrance, a shimmer, a pulse, a flash that decays. Its…

Designing an app that looks designed — direction, type, colour, composition and motion

How to make an Osy# app look like somebody designed it rather than like the default: commit to one visual direction…

theme tokens

A `theme` block names your app's design tokens — colors, spacing, radii, and more — as reusable values. A token can…

skeleton

A second render tree that stands in for a page or a component while its first read — its queries, its live server…