Scan flow

A React component in Beamline's Data & tables category.

A pick list that takes scans: each scan flies from the scan field into its row and fills that row's quantity ring, and the prompt moves to the next bin. A wrong item lands in the row it was taken for with Scanned against Expected and the words that differ marked (Oat milk 1 L against Oat milk 2 L), and the ring doesn't move until the right one is scanned; a scan past the count says one too many in its row; a code nobody knows says so under the field. Undo the last scan, set a count by hand, and finish early with the short lines kept in place.

Use it for

  • Picking an order, counting parts against a work order, receiving a delivery, checking a worklist: work done on a phone with a scanner or the camera, where a wrong item matters.
  • The host owns the lines and what happens on finish; codes come from a keyboard-wedge scanner typing into the field, or from a camera through scanRef.

Not for

Anatomy

  • prompt: the label, the scan field (Scan or type a code), the last scan's answer under it (a wrong item, one too many or an unknown code in its tone), Next · Bin with the item's name and n of qty, Undo last scan
  • list: lines in pick-path order; a line: its quantity ring (a segment per unit up to twelve, then one arc; a check when picked), name, bin and detail, n of qty (tap to set by hand), the +1 of the last scan
  • comparison (in a line): Wrong item, Scanned and Expected with names, codes and the differing words marked, Put it back; or n of n already: one too many, Put one back
  • finish: Finish pick (Finish with N lines short while lines are short); after: Pick complete · N items, or Finished with N lines short with Short n on each short line and Keep picking

States

  • picking
  • next line
  • counted
  • picked line
  • wrong item
  • one too many
  • unknown code
  • setting by hand
  • finished complete
  • finished short

Keyboard

  • The scan field keeps focus between scans: a scanner types the code and Enter; Escape clears a typed code
  • Each line is a list item named by its item, count and bin; its count is a button that opens a stepper (Escape or Done returns to the field)
  • Put it back and Put one back are reachable with Tab and return to the field; every scan result is said once (a polite status)

Motion

A scan's chip grows out of the scan field and lands on its row (the shared FLIP), the ring fills one step; a comparison opens with a short shake and the lines under it slide. Nothing runs at rest; reduced motion places everything and drops the shake.

Props

PropTypeDefaultDescription
label (required)string—What is being picked: "Order #4127".
lines (required)ScanLine[]—In pick-path order.
valueRecord<string, number>—Picked counts by line id.
defaultValueRecord<string, number>—Initial selection when uncontrolled; omitted by default.
onValueChange((picked: Record<string, number>) => void)—Reports the selected value after a change; no callback by default.
onScan((code: string, result: ScanResult) => void)—Every scan and what it was.
onFinish((picked: Record<string, number>, short: Record<string, number>) => void)—Finish pick: the counts, what is short by line id (empty when all is picked), and the serials by line id.
describe((code: string) => { name: string; } | null)—Name a code that is not on the list, so a wrong item shows what was scanned ("Oat milk 1 L"); null: unknown.
scanRefRef<ScanFlowHandle>—A camera or another reader feeds codes through `scanRef.current.scan(code)`.
classNamestring—Classes on the documented visual root; no override by default.
classNamesPartial<Record<"root" | "line" | "list" | "prompt" | "finish", string>>—Classes for the named visual parts; no overrides by default.
styleCSSProperties—Inline styles on the documented visual root; no overrides by default.
refRef<HTMLDivElement>—Receives the documented native target or imperative handle; omitted by default.
serialsRecord<string, string[]>—The serials captured on serial lines, by line id, in the order scanned.
defaultSerialsRecord<string, string[]>—
onSerialsChange((serials: Record<string, string[]>) => void)—
checkSerial((serial: string, line: ScanLine) => string | null)—Refuse a serial from outside this flow, saying why ("Shipped on order #4090"); null takes it. A serial already on this list is refused without asking.
groupsScanGroup[]—The orders or packages lines name in `group`.

Built from

Used in

Dependencies

lucide-react

Import

import { ScanFlow } from "@beamline/scan-flow";

Get it

Scan flow is part of Beamline UI. Install the parts you need in your React app as compiled packages or editable source. Get Beamline · Connect your agent

More in Data & tables

  • Living table: A table that shows as much as fits on both axes: width decides which columns show (the rest ride in the name line, moving there rather than vanishing)…
  • Availability layers: A week of bookable start times whose closed times explain themselves: every availability rule (hours, time off, bookings, buffers, rooms, lead time…
  • Capacity terrain: A schedule that stands on a terrain of capacity: under each station's lane of jobs, every day's load rises to its capacity line and an overload is a…
  • Domino move: A room board where one move shows its chain: drag a booking (or pick it and aim it with the keys) onto a taken room and the bookings it would push appear…
  • Match board: Month-end matching as one picture: bank lines and books entries side by side with threads between them — solid for matched, dashed with the host's reason…
  • Split anything: One splitter for money, quantities and time: a bar of the whole shows every target's part and what is not split yet; items are dragged onto targets…
  • Approval route: A policy you can read by trying it: an amount on a log scale with the thresholds as marks (the arrows stop just under, at and just over each), the…
  • Proposal twin: A proposal edited beside the client's exact page, the two linked both ways: a field in focus lights its twin on the page, scrolls it into view and joins…
  • Quantity river: The life of one order line's quantity: at rest a bar of its real split ("5 delivered · 1 back in stock · 1 damaged · 5 cancelled"), unfolding into a…
  • Stock horizon: Projected stock per item over the coming weeks: a strip of weeks with the safety line, weeks under safety in warn and short in danger, every dip said in…
  • Ageing queue: Tickets that visibly age: each ticket's ring fills toward its own service target and steps from on time to late to very late, the words say when it is…
  • Import lens: A messy import made fixable by kind: rows stream through the checks once with live counts; problems gather into groups that say what is wrong in words…
  • Duplicate guard: A new record that watches for the one that already exists: as you type, the likely duplicates slide in beside the form with the fields that match lit and…
  • Pack planner: The packing bench: the order's items sit in box outlines drawn to scale, each box filling to its padding line, weighing against its limit and naming the…
  • Provenance lens: Hold Alt (or press Lens) over any number on the page and see what makes it: hairline threads draw from the number to the rows, cards and documents on…
  • Record time machine: The record itself, rewound in place: a slim track of every change (a tick per change in its person's colour, hollow for automation, named moments as…
  • Tension timeline: A plan where slack is something you see: every dependency is a string from one task's end to the next one's start, sagging with the days it has to spare…
  • Replay bar: Rewind for anything live: pause a stream, scrub back to the moment you missed (markers for the ones that matter), step one update at a time, replay at a…
  • Event calendar: A schedule of events by day, week or month: events that overlap sit side by side, drag one to another time or day or pull its bottom edge to change its…
  • Kanban board: Work as cards in columns by stage: drag a card (or lift it with Space and walk it with the arrows) to another column or place, the cards around it make…
  • Data grid: Virtualised local or server-driven grid: stable row IDs, manual sort and filters, pages or infinite loading, retry without losing rows, inline editing…
  • Pivot table: Records summed up by the fields people choose: rows grouped by one or more fields that fold open level by level, columns split by another, one or more…
  • Query builder: Conditions people build by hand to pick out records: each rule is a field, an operator that fits the field (contains, between, in the last N days, is any…
  • Sort order: Several sort keys in order. Each key says its rank in words ("Sort by Plan, A to Z", "then by Size, largest first") with its order named for the field's…
  • Metric rules: Ordered rules that colour a dashboard number. Each rule has a name for what its colour means ("At risk", not just red) and a tone (good, watch, act…
  • Log viewer: Log lines as they stream: it follows the newest line until you scroll up, then counts what arrived and brings you back in one click; filter by level with…
  • JSON viewer: A JSON value as a tree you can read and walk: branches open and close (one level, or all at once), closed ones preview what they hold, every value reads…
  • JSON diff viewer: Two versions of a JSON value compared as one tree: added keys marked +, removed ones struck through with −, changed values read old → new, unchanged keys…
  • Import mapping: Map the columns of a file to the fields of one record type, see what every value becomes, then run the import and get an outcome for each row…
  • Diff table: Proposed edits to a table before they happen: new rows green, removals struck through, changed cells old → new; each change can be left out and Apply…
  • Filter toolbar: The filters on a list kept in view: chips that remove themselves, Add filter with fields and their values, Clear all, and room for search or view controls.
  • Table: A native HTML table for small datasets, composed with children or driven by records; shared server paging, sorting, filters, search, stable-ID selection…

Part of Beamline UI: polished, editable React components and complete screens for custom applications. Build your own style from any look; tokens, fonts, radii, motion; not only colours.