Implement readingOrder(elements) — take a list of absolutely-positioned boxes scattered on a canvas and return them in the order a person would read them: left to right, top to bottom. This is the order a screen reader announces a layout, the order "Tab" walks a form, and the order a serializer emits when it flattens a 2D design back into a 1D stream. Each input is a plain data object with coordinates — not a real DOM node — so there is no layout engine to lean on; the ordering is yours to compute from the numbers.
type Box = {
id: string; // a label so you can identify each box in the output
top: number; // distance from the top edge of the canvas, in pixels
left: number; // distance from the left edge of the canvas, in pixels
};
// Returns a NEW array containing the same box objects, ordered for reading.
// Does not mutate the input array or any box.
function readingOrder(elements: Box[]): Box[];
A box is a plain object. There may be other fields on it (width, text, …); you only sort by top and left.
// A 2x2 grid. Reading order goes across the top row, then the bottom row.
readingOrder([
{ id: 'D', top: 100, left: 100 },
{ id: 'B', top: 0, left: 100 },
{ id: 'C', top: 100, left: 0 },
{ id: 'A', top: 0, left: 0 },
]);
// → ids in order: ['A', 'B', 'C', 'D']
// Two boxes on the SAME row (equal top): the smaller left comes first.
readingOrder([
{ id: 'right', top: 50, left: 300 },
{ id: 'left', top: 50, left: 20 },
]);
// → ids in order: ['left', 'right']
// Stacked in one column (equal left, different top): top-most first.
readingOrder([
{ id: 'bottom', top: 200, left: 0 },
{ id: 'top', top: 0, left: 0 },
]);
// → ids in order: ['top', 'bottom']
top, secondary key is left. Sort by top ascending first; when two boxes share the same top, break the tie by left ascending. A box higher on the canvas always reads before a box lower down, regardless of horizontal position.elements is part of the contract.top and the same left must always come out in the same relative order across runs — never randomly reordered.getBoundingClientRect, read the DOM, or use any browser API. The whole problem is sorting numbers.width/height), or "almost-aligned" rows where tops differ by a pixel or two — those land in the harder follow-up, Reading Order II. Here, same-row means exactly equal top.