Circle Drawer
Click the canvas to draw a circle; right-click the gray one to adjust its diameter. The history is the State: a JSON list of changes in a data-changes attribute on this view's root, and the number of them applied in data-step. Undo and redo only move that number; the sheet derives the drawing from the changes up to it, so a new change simply drops the undone ones. Both frames are native modal <dialog>s, which hold the pointer still: the selected circle is their context. The only app JS is one pure function, the circle nearest to a point.
Task 6 of 7GUIs, a GUI programming benchmark.
The playground needs this site's service worker, which is still installing. Reload the page to start editing.