An animated number input component, inspired by the Family crypto wallet and Number Flow. Try typing a number below, when you’ll have some numbers typed in, select a single number and replace it with another number to see a barrel wheel effect like the one popularized by Number Flow.
autoAddLeadingZero prop is set to true.maxLength prop.The implementation of this component uses contentEditable in order to be able to animate the digits as they are typed. Relying on contentEditable allows to use markup, contrary to a regular input, but this comes with quite a few caveats.
Since the browser will insert content as the user types, the children of the content editable have to be managed outside of React. We are responsible for DOM manipulation, which can be a little tedious.
Content editable is designed to allow rich text formatting, and arbitrary markup to be inserted, for our input we need to prevent this. This is done via event.preventDefault(), simple yet effective.
In rich text, cursor positions move between nodes, this means that when you insert a span the cursor position can be inside, or outside of the span. This means that there more than on logical cursor position mapping to the same visual position. Which means the user would have to press the arrow keys twice to move the cursor to the next digit. This is definitely not ideal.
We need to handle cursor positioning ourselves. This also means we need to implement things such as alt+arrow or cmd+arrow in order to move the cursor to the beginning or end of the input (depending on which arrow the user pressed).
Because of this, we also need to implement a custom selection, too.
Since we manipulate the content ourselves and manipulate the DOM directly, we can’t rely on the native history for the content editable, we have to implement history on our own. The implementation here is pretty naive, but it works and restore cursor position as the user undoes/redoes.
Since we have rich text markup in our input, and we want to copy a raw number to the clipboard, we also need to handle copy operations ourselves in order to clean the markup.
I wanted an input that animates in a similar way to the Number Flowcomponent, and the Family crypto wallet inputs. Number Flow is great, but it doesn’t really have an input mode. What they do in their examples is that they basically overlay the number flow component on top of an input, but I wanted more animation options than that. In the end, using content editable is quite tricky, because you have to re-implement many things that are a given with a regular input if you want it to feel right and provide a decent UX.