Motion and accessibility
What animates, how reduce motion is honoured, and the accessibility contract each component keeps.
Motion
Every animation is a short timing, 90 to 150 ms, with an ease-out curve. There are no springs. A button press scales to 0.97 in 90 ms. A sheet fades and slides 24pt in 120 ms. A tab indicator slides in 150 ms. Anything longer starts to feel like the app is waiting for you.
Reanimated 4 defaults every withTiming and layout animation to ReduceMotion.System. When
the OS reduce motion setting is on, transitions jump to their end state and the Skeleton pulse
stops. Nothing in eoria overrides that default. To force animations on or off for the whole
app, mount Reanimated’s config once at the root.
import { ReducedMotionConfig, ReduceMotion } from 'react-native-reanimated'
<ReducedMotionConfig mode={ReduceMotion.Never} />Layout animations only move the views that carry them. An Accordion animates its own items;
a view below it jumps unless it also sets layout={LinearTransition}.
Accessibility
Each component ships with the role, state and label plumbing it needs. The rules the codebase follows:
- Interactive components set
accessibilityRoleandaccessibilityState. Checked, selected, expanded and disabled are always reported. accessibilityLabelledByworks on Android only, soFieldalso passes the label text asaccessibilityLabelon the control. Do the same if you wire labels by hand.- Live regions do nothing on iOS, so
ToastandFieldErrorcallAccessibilityInfo.announceForAccessibilitywhen they appear. - Decorative views such as
Separator,Skeletonand the initials inAvatarare hidden from assistive technology. Give theAvatarroot anaccessibilityLabelwith the person’s name. - Overlays mark the portal host
accessibilityViewIsModalwhile a dialog is open, so VoiceOver cannot wander behind it. Android has no equivalent, which is why the overlay stays in the tree as a “Close” button. Tooltipopens on long press and mirrors its text into the trigger’saccessibilityHint, since screen readers never long press.- Icon-only buttons need an
accessibilityLabel. The type does not force it; a reviewer should. - Text caps dynamic type at 1.5x by default through
maxFontSizeMultiplier. Raise it per component if your layout can take it.