Transition manages enter/exit animations for a single child element, driven by named "variants" (or a custom callback) that read the element's measured DOMRect and drive inline styles frame-by-frame. It's a thin declarative wrapper around the useTransition hook. A separate useTransitionGroup hook handles staggered animations for lists of keyed items.
<Transition>Notes:
children isn't exactly one valid React element, Transition throws.variant remounts the internal transition state machine (it's used as the React key).Defined in src/Transition/variants.ts. Each one computes from/to values and an onUpdate that writes directly to el.style:
You can also pass a custom TransitionVariantCallback:
tsx
const scaleY = (el: HTMLElement, rect: DOMRect) => ({ from: { scale: , opacity: }, to: { scale: , opacity: }, onUpdate: ({ scale, opacity }: any) => { el.style.transform = `scaleY(${scale})` el.style.transformOrigin = 'top' el.style.opacity = String(opacity) },})tsx
import { Transition, Tag } from 'xanui-core' export const Toast = ({ open, children }) => ( <Transition open={open} variant="fade" duration={}> <Tag px={} py={} radius={} shadow="md" bgcolor="brand.primary" color="brand.contrast" > {children} </Tag> </Transition>)tsx
<Transition open={isOpen} variant="fadeUp" duration={} easing="smooth" onEntered={() => console.log('panel expanded')} onExited={() => console.log('panel collapsed')}> <Tag component="section" px={} py={} radius={} shadow="sm"> {children} </Tag></Transition>useTransitionThe hook Transition is built on. Runs a single enter/exit animation over an arbitrary set of numeric values.
ts
import { useTransition, Easing } from 'xanui-core' const trans = useTransition({ from: { opacity: }, to: { opacity: }, duration: , easing: Easing.smooth, onUpdate: (value) => { el.style.opacity = String(value.opacity) }, onEntered: () => console.log('fully visible'),}) trans.enter() // animate toward `to`trans.exit() // animate toward `from`trans.toggle() // flip directiontrans.enter(false) // jump instantly, no animationtrans.status // "entering" | "entered" | "exiting" | "exited"trans.isEntered // booleantrans.state // ref holding the current interpolated valuetrans.isReady // whether `from`/`to` have been resolved (post-mount)UseTransitionProps<T>Extends AnimateOptions<T> (see animate below) with:
useTransitionGroupStaggered enter/exit animation for a list of keyed items, with optional mount-on-enter / unmount-on-exit support.
ts
import { useTransitionGroup } from 'xanui-core' const group = useTransitionGroup({ items: list.map((item) => ({ key: item.id, from: { y: , opacity: }, to: { y: , opacity: } })), stagger: , duration: , mountOnEnter: true, unmountOnExit: true, onUpdate: (value, key, progress) => { /* apply per-item styles */ },}) group.enter()group.exit()group.toggle()group.statuses[item.key] // "entering" | "entered" | "exiting" | "exited"group.mounted[item.key] // boolean, useful with mountOnEnter/unmountOnExitUseTransitionGroupProps<T>animate / EasingBoth useTransition and useTransitionGroup are built on the low-level animate() function, also exported directly:
ts
import { animate, Easing } from 'xanui-core' const cancel = animate({ from: { x: }, to: { x: }, duration: , easing: Easing.smooth, onUpdate: (value) => { el.style.transform = `translateX(${value.x}px)` }, onDone: () => console.log('done'),}) cancel() // stop the animation earlyBuilt-in Easing functions: default (cubic ease-out), standard, fast, smooth, linear, bounceBezier (cubic-bezier curves), plus cubicInOut, easeOutBounce, and spring.
AnimateOptions<T> also supports repeat (number of extra cycles), repeatBack (ping-pong direction on repeat), and breakpoints (per-key value thresholds that fire a callback() once when crossed during the animation).