JSFiddle - React, Tailwind, and code Playground

HTML

<div ng-app="yourApp" ng-controller="loginFormCtrl">
    <kbd-widget>
        <input type="text" ng-model="data.login" />
        <input type="password" ng-model="data.password" />
    </kbd-widget>
</div>

JavaScript

angular.module('yourApp', []).

controller('loginFormCtrl', ['$scope', function ($scope) {
    $scope.data = {
        login: 'hey',
        password: ''
    };
}]).

// Widget encompassing virtual-keyboard-enabled inputs
directive('kbdWidget', function () {
    return {
        restrict: 'E',
        transclude: true,
        template: '<div ng-transclude></div>' +
                  '<kbd ng-show="activeInput"></kbd>',
        controller: ['$scope', function ($scope) {   
            $scope.activeInput = null;
            
            var focusInput = function () {
                $scope.activeInput && $scope.activeInput.focus();
            };

            this.applyToActiveInput = function (func) {
                if ($scope.activeInput) {
                    setTimeout(focusInput, 5);
                    func($scope.activeInput);
                }
            };
            this.focusInput = focusInput;
        }],
        link: function (scope, element, attr) {
            element.find('input').bind('focus', function (evt) {
                scope.$apply(function () {
                    scope.activeInput = evt.target;
                });
            });
        }
    }
}).

// Virtual keyboard
directive('kbd', ['kbdButtons', function (buttons) {
    return {
        restrict: 'E',
        require: '^kbdWidget',
        link: function (scope, element, attr, widgetCtrl) {
            angular.forEach(buttons, function (btn) {
                var el = angular.element(
                    '<button>' + btn.label + '</button>');
                var repeatAction = function () {
                    widgetCtrl.applyToActiveInput(btn.action);
                    btn.timeout = setTimeout(repeatAction, 250);
                };

                el.bind('mousedown', function () {
                    repeatAction();
                });
                el.bind('mouseup', function () {
                    clearTimeout(btn.timeout);
                   ...