
Productive Robotics
Custom On-Screen Keyboard & BaseButton Migration
Built a custom on-screen keyboard to replace the unreliable Android native keyboard in the tablet WebView, then executed a 164-file migration converting 50+ components from a broken v-touch directive to a unified BaseButton component with @pointerdown — discovering 4 instances of a stopPropogation() typo silently failing across the codebase.
The Android native keyboard on the Samsung SM-X200 tablets was unreliable inside the Chromium 90 WebView — it would fail to appear, overlap UI elements, or dismiss unexpectedly during welding program editing. Built a complete custom on-screen keyboard in Vue.js: intercepts focusin events on input fields, sets inputmode='none' to suppress the native keyboard, and renders a fully styled keyboard overlay. Includes a connection guard (prevents the keyboard from blocking the UI during WebSocket cold-start), a modal guard (watches displayMessage/displayError to hide the keyboard when system modals appear), and v-model support via synthetic DOM input events so existing Vue two-way bindings work without modification.
Implemented scroll management — when the keyboard appears, it finds the nearest scrollable parent container, calculates the visible area above the keyboard, and injects a spacer element to push content into view. Without this, input fields near the bottom of the screen would be hidden behind the keyboard with no way to see what you're typing. Built a separate Vue 3 Composition API version for the Miller welding UI with the same feature set but using ref()/onMounted() patterns instead of Options API.
Discovered that 50+ components across the tablet UI used a broken v-touch.prevent.stop directive that failed silently on many Android devices. Created a `BaseButton` component using @pointerdown (which correctly prevents scroll detection issues on touch devices) and executed a 164-file migration replacing all instances. During the migration, found 4 instances of `stopPropogation()` — a typo (missing 'a') that called a nonexistent method, silently failing to stop event propagation. These had been in production for months without anyone noticing because the misspelled method call simply returned undefined instead of throwing an error.