Sophic Interface Systems
Foundations

Animations

Named motion styles for product UI — a shared vocabulary for humans and agents.

Named animations we reuse across the system. Prefer these names in specs, tickets, and prompts so designers, engineers, and agents describe the same behavior.

TermWhat it is
spring-popEnter motion style — scale overshoot + fade in
soft-dismissExit motion style — quiet opacity fade
spin-slowDecorative loop — slow continuous rotation
SpringRevealReact component — pairs spring-pop + soft-dismiss with height collapse
HeightRevealReact component — height-only accordion, no scale
morph-buttonFull-width CTA that expands up into confirm / success, then reverse-morphs back onto the same button. See Morph Button.

Motion styles (spring-pop, soft-dismiss, spin-slow) are CSS utilities in @sophic/portal-ui/theme.css — use the classnames when you own the shell.

Animation components (SpringReveal, HeightReveal) are React helpers in @sophic/portal-ui that wire enter/exit for common open/close patterns. Prefer them over hand-rolling the grid + class toggles below.

Motion styles

Spring pop

Name: spring-pop Class: animate-spring-pop-in

In-place reveal that grows from the center with a short overshoot, then settles. Feels springy rather than a hard cut or a plain fade.

SpecValue
Duration480ms
Easingcubic-bezier(0.22, 1.45, 0.36, 1)
Scale0.92 → 1.02 → 1
Opacity0 → 1

Use when: Settings panels, inline cards, or style that should “pop” into place from a trigger nearby (e.g. gear → chart settings).

Avoid when: Full-page transitions, continuous loops, or large surfaces where overshoot would feel jumpy.

<div className="origin-center animate-spring-pop-in motion-reduce:animate-none">
  {/* panel content */}
</div>
spring-pop enter — scale overshoot + fade

Soft dismiss

Name: soft-dismiss Class: animate-soft-dismiss

Exit companion to spring-pop. Quiet opacity fade only — no exit scale. Pair it with a slow height collapse on the shell (grid-rows ~320ms) so content below slides up instead of popping away.

SpecValue
Fadeanimate-soft-dismiss — opacity 1 → 0, 320ms, ease-out
Height (shell)1fr → 0fr, ~320ms, cubic-bezier(0.22, 1, 0.36, 1)
Scalenone on exit

Use when: Closing anything that entered with spring-pop.

import { cn } from "@sophic/portal-ui/lib/utils";

{/* Fade utility */}
<div className="animate-soft-dismiss motion-reduce:animate-none">
  {/* panel content */}
</div>

{/* Typical shell: height morph + fade (prefer SpringReveal) */}
<div
  className={cn(
    "grid transition-[grid-template-rows] duration-[320ms]",
    "ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:transition-none",
    open ? "grid-rows-[1fr]" : "grid-rows-[0fr]",
  )}
>
  <div className="min-h-0 overflow-hidden">
    <div
      className={
        open
          ? "origin-center animate-spring-pop-in"
          : "animate-soft-dismiss motion-reduce:animate-none"
      }
    >
      {children}
    </div>
  </div>
</div>
soft-dismiss — opacity fade only

Spin slow

Name: spin-slow Class: animate-spin-slow

Quiet continuous rotation for small decorative glyphs — not a loading spinner. Product home greeting uses it on the morning sun only (9s full turn); afternoon / evening / night icons stay static.

SpecValue
Duration9s
Easinglinear
Loopinfinite

Use when: Morning greeting sun, other tiny ambient style that should rotate slowly — not every icon in a set.

Avoid when: Loading states — use default animate-spin with SpinnerGapIcon instead. Large surfaces where rotation feels distracting.

Always pair with motion-reduce:animate-none.

<SunIcon
  size={20}
  weight="bold"
  className="text-warning-foreground animate-spin-slow motion-reduce:animate-none"
  aria-hidden
/>

spin-slow — 9s linear loop for small decorative glyphs (e.g. home greeting).

Animation components

React components in @sophic/portal-ui — import and pass open to drive enter/exit. Use these instead of hand-rolling the motion-style shells above.

SpringReveal

React component — @sophic/portal-ui/components/ui/spring-reveal

Pairs spring-pop (enter) with soft-dismiss + height collapse (exit). Use for settings panels and similar in-flow reveals.

Content below moves up as the panel folds away.

Combined enter/exit via the SpringReveal React component (not the raw CSS classes alone).

import { SpringReveal } from "@sophic/portal-ui/components/ui/spring-reveal";

<SpringReveal open={open}>{children}</SpringReveal>
{/* Chart gear settings keep the bounce: */}
<SpringReveal open={open} spring="springy">{children}</SpringReveal>

Import from @sophic/portal-ui/components/ui/spring-reveal. Pass open to drive enter/exit; optional className lands on the height-morph shell. Enter defaults to soft (spring="soft"); pass spring="springy" for the original overshoot (chart gear). Mounting already open skips the enter pop.

HeightReveal

React component — @sophic/portal-ui/components/ui/height-reveal

Height-only accordion (0fr ↔ 1fr). No scale enter. Clips while collapsed and during the height morph; content fades from washed-out to full in parallel. overflow-visible once fully open so list hover washes (-mx) are not clipped.

Use when: See more / accordion lists on instrument and fund sections.

Avoid when: Gear / settings panels — use SpringReveal instead.

  • Extra row one
  • Extra row two
  • Extra row three

Height morph with a washed-out fade-in — no scale pop. Open state keeps overflow visible for list hover washes.

import { HeightReveal } from "@sophic/portal-ui/components/ui/height-reveal";

<HeightReveal open={open}>{children}</HeightReveal>

Pass open; optional className lands on the height-morph shell.

Changelog

  • 5 August 2026 — spin-slow decorative loop (animate-spin-slow, 9s) for small glyphs; first use on home greeting icons. Full notes
  • 5 August 2026 — Home greeting time-of-day icons; morning sun spins with spin-slow, other periods static. Full notes
  • 4 August 2026 — HeightReveal promoted to @sophic/portal-ui (peer of SpringReveal) for list See more expands. Full notes
  • 4 August 2026 — SpringReveal enter defaults to soft; spring="springy" restores the foundation bounce (gear settings).
  • 1 August 2026 — Chart details strip uses SpringReveal (same enter / exit as gear settings). Full notes
  • 30 July 2026 — Instrument dials adopt spring-pop / soft-dismiss via SpringReveal for settings. Full notes
  • 30 July 2026 — Animations foundation catalog + SpringReveal helper. Full notes

On this page