Skip to content
react-native-strx v1.0.0-beta.1

Tooling

Recipes

Copy-ready patterns for common UI motion.

Each recipe uses only public STRX APIs. Adjust tokens to taste.

Staggered list entrance

1<Strx.Timeline playback="stagger" interval={50}>2  {items.map(item => (3    <Strx.View key={item.id} animate="fade-in from:translate-y-12 duration-260">4      <Row item={item} />5    </Strx.View>6  ))}7</Strx.Timeline>

Keep the interval small (40–80ms) and the list short; for long lists, only stagger the first screenful.

Toast

1{toast && (2  <Strx.View3    animate="fade-in from:translate-y-24 spring damping-16, exit:opacity-0 exit:translate-y-24 duration-180 ease-in"4    style={styles.toast}5  >6    <Strx.Text>{toast.message}</Strx.Text>7  </Strx.View>8)}

The entrance springs in; the exit, in its own group, has its own short timing.

Bottom sheet

1<Strx.View2  animate="from:translate-y-600 to:translate-y-0 spring damping-20 stiffness-180, exit:translate-y-600 duration-220 ease-in"3  style={styles.sheet}4>5  <SheetContent />6</Strx.View>

Accordion

1<Strx.View animate="layout-spring" layoutClip style={styles.panel}>2  <Strx.Pressable onPress={() => setOpen(value => !value)}>3    <Strx.Text>{title}</Strx.Text>4  </Strx.Pressable>5  {open && <Strx.Text animate="fade-in exit:opacity-0 duration-150">{body}</Strx.Text>}6</Strx.View>

Selectable chip

1<Strx.Pressable2  animate="transition-all duration-160"3  onPress={() => setSelected(!selected)}4  style={({ pressed }) => ({5    backgroundColor: selected ? "#3552f0" : "#f2f4f7",6    transform: [{ scale: pressed ? 0.96 : 1 }],7  })}8>9  <Strx.Text style={{ color: selected ? "#fff" : "#0b1020" }}>Design</Strx.Text>10</Strx.Pressable>

Validation shake

Play a short keyframe animation from an event with useTimeline:

1const shake = Strx.useTimeline({2  playables: [{ target: "field", animate: "from:-translate-x-8 to:translate-x-0 spring damping-4 stiffness-400" }],3});45<Strx.TextInput strxId="field" onSubmitEditing={() => !valid && shake.play()} />;

Pulsing indicator

1<Strx.View2  animate="from:opacity-40 to:opacity-100 from:scale-90 to:scale-100 duration-700 ease-in-out play-infinite"3  style={styles.dot}4/>

Keep looping animations small. Under Reduce Motion they play once.

Skeleton to content

1{loading ? (2  <Strx.View animate="exit:opacity-0 duration-150" style={styles.skeleton} />3) : (4  <Strx.View animate="fade-in duration-250">5    <Content />6  </Strx.View>7)}

Success screen

1const celebrate = Strx.useTimeline({2  playback: "stagger",3  interval: 90,4  playables: [5    { target: "badge", animate: "bounce" },6    { target: "headline", animate: "fade-in from:translate-y-12" },7    { target: "cta", animate: "fade-in from:translate-y-12" },8  ],9});1011useEffect(() => {12  if (paid) celebrate.play();13}, [paid]);

Reorderable list

1<Strx.LayoutGroup transition="spring" damping={18}>2  {sorted.map(item => (3    <Strx.View key={item.id} animate="fade-in exit:opacity-0 exit:scale-95">4      <Row item={item} />5    </Strx.View>6  ))}7</Strx.LayoutGroup>

When sorted changes order, rows spring to their new positions; removed rows fade out first.

Esc