Motion

Guide index · Interaction · Components

Purpose

Motion is part of the Oracle language. Every animation must answer a question the reader has: what changed, where did it go, is work still happening, how far along is it, or which way does it flow. The same fact must always be available in text or counts; motion reinforces it, never replaces it.

Meaningful motion includes spinners and indeterminate bars for ongoing work; progress bars that move only to each newly observed value; regions that expand and collapse; controls that slide to match state whether the user or an external update changed it; items entering or leaving a list; and directional flow on active workflow connectors. Motion starts from a real state change or real ongoing work, settles when the state settles, and loops only while work continues.

Forbidden decoration includes breathing frames, glowing pulses, parallax, scanlines, animated gradients or lighting, idle loops, bounce or overshoot, and attention-seeking shakes or flashes. All motion looks controlled: it moves at a steady, readable pace, never darts across the screen, snaps, or flashes. Looping motion uses linear timing and seamless loops with no jump at the restart. Layout must not jump: headings and primary anchors stay fixed while metadata grows downward. Flow animation shows direction and which edges are active; it never implies success or completion by itself.

The timings below are the motion vocabulary: shared names and durations for each kind of change.

Motion vocabulary

Meaning Motion Duration Curve Reduced motion
Ongoing work Spinner turn or segmented marquee motion.spinnerCycle (1000ms) / motion.marquee (3500ms) Linear loop Static operation-specific text
Observed progress Whole segments switch on or off Whole segments: motion.progressStep (60ms), capped by motion.progressMax (1500ms) Standard Instant width update
Containment change Drawer width or disclosure height motion.drawer / motion.collapse Containment (same both ways) Instant open/close
Control state Switch thumb or tab marker slide motion.stateChange (160ms) Standard Instant position
List arrival/removal Short opacity (and optional height) motion.listEnter / motion.listExit Enter / Exit Instant show/hide
Overlay appear/dismiss Opacity on menu, tooltip, dialog motion.menuEnter / motion.menuExit Enter / Exit Instant
Flow direction Marching dashes on active connector motion.flowCycle (~1200ms) Linear loop Static arrowhead only

Timings and curves

Transition Duration Curve
Hover/focus paint 120ms (motion.hover) Standard
Press feedback 80ms (motion.press) Standard
Menu/tooltip appear 120ms (motion.menuEnter) Enter
Menu/tooltip dismiss 120ms (motion.menuExit) Exit
Drawer/disclosure 180ms (motion.drawer / motion.collapse) Containment (same both ways)
Page detail replacement 160ms on enter and exit (motion.pageDetail) Enter when appearing; exit when disappearing (same duration)
Control state change 160ms (motion.stateChange) Standard
Observed progress step 60ms per whole segment; 1500ms maximum catch-up (motion.progressStep / motion.progressMax) None
List enter / exit 160ms / 160ms Enter / Exit
Explicit scroll-to-section Up to 200ms (motion.scroll) Standard
Reduced-motion equivalent 0ms spatial transition Immediate state update

Standard is cubic-bezier(0.2, 0, 0, 1) (motion.standardCurve); enter is cubic-bezier(0, 0, 0.2, 1) (motion.enterCurve); exit is cubic-bezier(0.4, 0, 1, 1) (motion.exitCurve). Native implementations should match the response without requiring a web animation engine.

Opposite transitions are symmetrical: expand and collapse, appear and dismiss, and enter and exit use the same duration, and containment changes use one balanced ease-in-out curve (motion.containmentCurve, cubic-bezier(0.4, 0, 0.2, 1)) in both directions, so closing is never faster or slower than opening.

Animations are interruptible and start from the current rendered state. User dragging follows the pointer directly with no easing. Do not animate an external resize or delay an operation until a visual transition finishes.

Job 041 · Complete
Job 042 · Running
Opacity only, 120ms

List rows use 160ms enter and exit; menu and tooltip use 120ms. Opacity changes only; nothing translates.

Progress and ongoing work

Progress bars are always segmented, never solid: whole segments separated by 4px gaps, on the quiet track, each about 2:1 (width to height). The segment count is chosen from the bar width and the segment width flexes slightly so segments fill the bar exactly to the pixel, with running neon green for filled segments. A segment is never partially filled; progress is shown by turning whole segments on, one after another at a steady pace (60ms each (motion.progressStep), shortening the step interval for large jumps so catch-up completes within 1500ms (motion.progressMax)), until the observed value is reached, and off the same way if it decreases. The fill never partly fills a segment; reduced motion updates the whole-segment value immediately. Unknown progress uses a segmented marquee: a running-green head with a fading tail moves left to right one whole segment at a time (3500ms (motion.marquee) to cross the bar, however wide it is) and wraps seamlessly. Every segment is a single solid color, so the gradient exists only across segments, never within one, and there is no flashing or sudden jumping. Every bar is paired with operation-specific text, such as “Checking files,” and its observed count or “Total unknown.” This applies to status-bar progress, secondary bars, and bars in expanded status dialogs; each text label describes exactly the operation measured by its bar. The desktop spinner is text-sized (1em): four separated segments, the same segmented motif as the bars: squares at top left and bottom right and triangles at top right and bottom left whose diagonals cut off the outer corners like the chamfers, with one running-green segment stepping clockwise in a steady 1000ms cycle; it is never a circle. It is local to the waiting control or region.

Checking files · 3 / 8

Fill moves only when the next value is observed.

Unknown total

Discovering files · total unknown

Expand and collapse

Disclosure and drawer motion changes occupied space while the summary or header stays anchored. Never clip the only validation error or focused control.

Validation details

Expanded content keeps the title inset fixed. Height animates over motion.collapse unless reduced motion is enabled.

Controls follow state

When underlying state changes—whether from direct input or an external update—the control face moves to the new position with the same timing. Busy and disabled channels from interaction still apply.

External setting: off

Flow direction

Active workflow connectors may use marching dashes to show direction. Idle connectors stay still. Arrowheads always show direction without relying on animation. Animation never stands in for status or success.

Ingest
Validate
Publish

Running-green dashes march on the active edge only; the idle edge is static.

Boundaries

Maintain heading anchors during transitions. Prefer short opacity changes for content replacement; avoid translating whole text panes. Drawer animation changes its occupied width while its header and toggle remain anchored. A large or costly body can appear immediately rather than stutter.

Never animate a disclosure in a way that clips the only validation error or focused control. A transition cannot change focus, scroll ownership, selection or command semantics by itself. Do not announce animation frames to assistive technology.

Expanded disclosure keeps the only validation error and its focus target visible; the heading stays anchored

Connection settings

Host cannot contain spaces.

Reduced motion and terminal behavior

Honor the system/user reduced-motion preference. Remove spatial animation and smooth scrolling; update state immediately. Do not replace motion with flashing. Preserve all information in labels and counts.

Spinners and indeterminate bars become static operation-specific text such as “Validating records · total unknown”; the operation name remains visible. Flow animation becomes static arrowheads; terminal flow shows the dashes of an active edge static. Terminals use immediate repaint and optional spinner updates at at most 8 frames per second. Nerd Font is required and guaranteed; the progress bar has no ASCII, Unicode-only, or counts-only fallback. Terminal progress is drawn as segment caps and the spinner as a single lit quadrant block stepping clockwise, and filled segments as solid blocks, and flow edges are a row of segmented dashes that march toward a solid arrowhead, matching the desktop connector, the marquee traverses its available segment count in 3500ms, independent of spinner frames. Color and layout capabilities follow Terminal; they do not replace the progress-bar glyph recipe. Redirected or screen-reader output is linear, with no spinner repaint. Freeze or replace the spinner with operation-specific text for reduced motion or noninteractive output. Never redraw the entire viewport just to animate a border. Buffered log output must remain readable and must not pull a reader away from their scroll position.