Skip to content
Native Animation
QR Target Lock animation preview

This preview uses fictional demo content. See the props below for the customization options available in this component.

npx nativeanimation add qr-target-lock

QR Target Lock

A QR target-lock reveal with tracked corners and a result card, with configurable preview content, labels, palette, and fonts.

$9 for this animation

Add to your project

Copy the component and its assets into your app with the Native Animation CLI, or paste the agent prompt into Claude Code, Codex or Cursor once the MCP server is connected.

About this animation

Related guides

A QR target-lock reveal with tracked corners and a result card, with configurable preview content, labels, palette, and fonts. Your app supplies detection bounds and decoded results; this component does not open a camera or decode images.

How it works

  1. The host supplies bounds normalized to the centered square scan viewport and an optional status.
  2. A single lockState shared value drives the frame, target veil, and transfer choreography.
  3. locked tightens the corners and reveals the confirmation state.
  4. result reveals a card in a reserved area below the centered frame; lost and error keep the target context and offer retry.

Install

npx expo install expo-blur expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets

The component has no camera, barcode, or image-recognition dependency.

Usage

<QrTargetLock
  detectedBounds={{ x: 0.08, y: 0.08, width: 0.84, height: 0.84 }}
  status="tracking"
  labels={{ searching: 'Searching', tracking: 'Tracking', locked: 'Locked', lost: 'Lost', error: 'Error', retry: 'Retry' }}
/>

Use ref.reset() to request searching or ref.presentResult(result) to request a result in uncontrolled mode. For a controlled host, update status after receiving onStatusChange.

Props

PropTypeDefaultDescription
statusQrTargetStatus—Controlled state.
defaultStatusQrTargetStatussearchingInitial uncontrolled state.
detectedBounds{ x; y; width; height }centered targetHost bounds normalized to the centered square scan viewport.
resultQrTargetResult—Result card content.
renderPreview() => ReactNode—Content behind the frame.
cornerLengthnumber22Corner stroke length in points.
colorScheme / palettetheme propsauto / tokensComplete light/dark semantic palette controls.
motion{ durationScale; glowOpacity }1 / 0.25Motion and glow knobs.
labelsstate labels plus optional hints—All state, retry, and hint copy.
onResultPress(id: string) => void—Result action callback.

The Tidewell demo uses the teal droplet mark from the demo brand kit and a large, centered simulated preview. The preview is sized from the measured component bounds after reserving space for feedback and state copy. Short demo containers omit the editorial heading. Result and retry controls share a reserved area below it, so state changes keep the frame in place. Result text can wrap to two lines beside a 32-point badge and the action.

Compatibility

Expo SDK 58, React Native 0.88, Reanimated 4.7, Worklets 0.13, Gesture Handler 3.3, and expo-blur 58. Web compilation is supported by the implementation. No native camera permission is required. The embeddable component does not apply safe-area insets.

Accessibility

The current state is exposed as a polite live region, the viewport has a state label, QR content is identified as an image, and retry/result actions have 48-point targets. Reduced motion removes the frame flight and uses immediate state changes. All copy is supplied by props so hosts can localize it.

Why this one

It treats scanning as a stateful handoff: host-owned bounds remain authoritative, lost/error are first-class states, and the locked frame becomes the result surface instead of disappearing before the user understands what happened.