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
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.
Discovering files · total unknown
Discovering files · total unknown
Discovering files · total unknown Discovering files
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.
Validation details
Same containment motion at narrow widths.
▸ Validation details ▾ Validation details Three checks observed; two pending review.
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 (active) Validate Publish (waiting)
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.
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.