Scan viewfinder
Free · MITReact Native · ExpoAn overlay for a camera preview: brackets drift while searching, snap onto the subject with a cue, then a scan line sweeps while short findings fly out. It draws the overlay only; camera and detection are yours.
Installation
$ npx shadcn@latest add https://goodui.dev/native/r/scan-viewfinder.jsonThen run npx expo install --fix so react-native-reanimated match your Expo SDK. Files land in components/goodui-native/scan-viewfinder.
Usage
import { CameraView } from "expo-camera";
import { ScanViewfinder, type ScanState } from "@/components/goodui-native/scan-viewfinder/scan-viewfinder";
const TARGET = { x: 0.15, y: 0.25, width: 0.7, height: 0.45 };
<ScanViewfinder state={state} target={TARGET} chips={["Salmon", "Rice"]}>
<CameraView style={{ flex: 1 }} />
</ScanViewfinder>When to use
- Apps that photograph something to analyse it: food, plants, documents, coins.
- Giving feedback while an on-device detector looks for a subject.
- QR and barcode scanning: use the camera module's scanner with a plain frame.
- Plain photo capture: a shutter is enough.
API reference
| Prop | Type | Default |
|---|---|---|
| state* searching drifts the brackets, locked snaps them to `target`, analysing runs the scan line and chips. | "done" | "searching" | "locked" | "analysing" | — |
| target The subject, as fractions of the frame. | { x: number; y: number; width: number; height: number } | DEFAULT_TARGET |
| chips Short facts that fly out of the subject while analysing: "Salmon", "Rice". | string[] | [] |
| children* The camera preview. | ReactNode | — |
| labels | Partial<ScanViewfinderLabels> | — |
| style Style for the outer container. | StyleProp<ViewStyle> | — |
| testID Identifier for end-to-end tests. | string | — |
Motion and haptics
- Brackets drift on looping sine timings, then spring onto the target.
- On lock, the frame flashes and the brackets take the accent color.
- While analysing, a scan line loops and chips burst out in a staggered ring.
- Reduced motion: no drift or sweep. Chips fade in at their final place.
- Haptic: drop on lock, a tick for each chip.
- Brackets and the scan line run on the UI thread, over the camera preview.
Accessibility
- The status line is a polite live region, so state changes are announced.
- Brackets, the scan line and chips are hidden from screen readers. Say the result on the next screen.
Notes for AI
- It fills its parent with flex: 1, so the parent needs a height.
- `target` is in fractions of the frame, measured from the top left.
- State does not advance on its own: move through searching, locked, analysing and done yourself.
- `chips` are short facts from a real result, cut off at about 130 pt. Do not show invented findings as if they were detected.
- It stays left to right under RTL because it is measured from the physical camera frame.
Related
Cards for long AI jobs: each one shows its status, a fill and a light sweep while running, a rolling percentage, and cancel, retry and open actions.
Shows a result arriving: a scan line wipes down a blurred picture and leaves it sharp, then the frame settles with a spring and an unlock cue.
The logic layer behind the AI components, with no UI: a typed provider adapter with an offline mock, a credit ledger that keeps subscription and bought credits apart, and a generation queue that charges, refunds and retries.