Skip to content

motion/swap

import { … } from 'zidane-ui'ui/src/motion/swap.tsx

Crossfade (scale): spinner → check → x
Crossfade (text)
Running tests…
Presence
new
RollingText in SmoothWidth
HeldWidth
1s
SwapIcon

Components#

CrossfadeComponent#

Swaps content by key with a cross-fade: the previous node stays in the same grid cell for the exit (readExitMs()) playing its exit while the new one plays its enter; with motion off it is replaced at once. children === null is a valid state (empty slot).

TypeScript
function Crossfade(props: CrossfadeProps): Element
Parameters
NameTypeDescription
propsCrossfadeProps

Component props.

Element
Crossfade props
NameTypeDescription
activeKeystring | number

Identity of the current content; a change triggers the swap.

align?'start' | 'end'

text only: which edge both lines hold to. end for text set against something on its right (a trailing slot): when the outgoing line leaves and the cell narrows, the line on show stays where it is.

childrenReactNode

The current content. null is a valid empty slot.

className?string

Extra classes on the wrapping cell.

settle?boolean

For content inside something that is itself still appearing (a line fading in): a key change in its first moments replaces the content without a crossfade, since two lines fading over each other inside a line that is fading in reads as a flicker.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

variant?'text' | 'scale'

scale (default): the glyph swap, in/out through scale around the centre; right for spinners, checks and icons. text: for a line of words, anchored left; the old line blurs away, the new one sharpens into place, no scale.

ui/src/motion/swap.tsx:111

PresenceComponent#

Keeps children mounted for the exit (readExitMs()) after show flips false so the exit animation plays. Renders nothing once the exit is done.

TypeScript
function Presence(props: PresenceProps): Element | null
Parameters
NameTypeDescription
propsPresenceProps

Component props.

Element | null
Presence props
NameTypeDescription
childrenReactNode

The content to show and animate out.

className?string

Extra classes on the wrapper (sizing, spacing).

display?'inline' | 'block'

Inline wrapper by default; block for full-width rows.

showboolean

Whether the content is shown. When it turns false, the content stays mounted for its exit.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

variant?'text' | 'scale'

scale (default) for glyphs; text blurs a line of words in and out, anchored left.

ui/src/motion/swap.tsx:47

Functions#

useCadencedValueFunction#

Hold a fast-changing value to a readable cadence: at most one change every ms, the newest value always wins, and the last one always lands (a trailing update fires when the source goes quiet). The first value shows at once.

TypeScript
function useCadencedValue<T>(value: T, ms: number): T
Type parameters
NameDescription
T
Parameters
NameTypeDescription
valueT

The source value, which may change faster than it should show.

msnumber

The minimum time between shown changes, in ms.

T

The value to show.

ui/src/motion/swap.tsx:188

Interfaces#

CrossfadePropsInterface#

Props for Crossfade.

TypeScript
interface CrossfadeProps
CrossfadeProps properties
NameTypeDescription
activeKeystring | number

Identity of the current content; a change triggers the swap.

align?'start' | 'end'

text only: which edge both lines hold to. end for text set against something on its right (a trailing slot): when the outgoing line leaves and the cell narrows, the line on show stays where it is.

childrenReactNode

The current content. null is a valid empty slot.

className?string

Extra classes on the wrapping cell.

settle?boolean

For content inside something that is itself still appearing (a line fading in): a key change in its first moments replaces the content without a crossfade, since two lines fading over each other inside a line that is fading in reads as a flicker.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

variant?'text' | 'scale'

scale (default): the glyph swap, in/out through scale around the centre; right for spinners, checks and icons. text: for a line of words, anchored left; the old line blurs away, the new one sharpens into place, no scale.

ui/src/motion/swap.tsx:72

PresencePropsInterface#

Props for Presence.

TypeScript
interface PresenceProps
PresenceProps properties
NameTypeDescription
childrenReactNode

The content to show and animate out.

className?string

Extra classes on the wrapper (sizing, spacing).

display?'inline' | 'block'

Inline wrapper by default; block for full-width rows.

showboolean

Whether the content is shown. When it turns false, the content stays mounted for its exit.

style?CSSProperties

Inline styles on the root element, merged after the component's own.

variant?'text' | 'scale'

scale (default) for glyphs; text blurs a line of words in and out, anchored left.

ui/src/motion/swap.tsx:26