npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

reactjs-virtual-keyboard

v2.0.1

Published

A customizable virtual keyboard component for React applications with support for multiple layouts, multi-language support, hardware keyboard sync, and touch devices

Readme

reactjs-virtual-keyboard

A lightweight, customizable virtual keyboard component for React applications. Features multiple layouts, multi-language support, hardware keyboard sync, extensive customization options, and full TypeScript support.

📚 Documentation & Live Demo

✨ Features

  • 🎹 Multiple Layouts: QWERTY letters, symbols, and numeric keypad
  • 🌍 Multi-Language Support: Built-in language switcher with custom language layouts
  • ⌨️ Hardware Keyboard Sync: Virtual keyboard syncs with physical keyboard (Caps Lock, key presses)
  • 📱 Touch Optimized: Continuous press support (hold backspace to delete)
  • 🎨 Highly Customizable: Custom layouts, key labels, disabled/hidden keys, render functions
  • 🪶 Lightweight: Only ~26 KB minified (~6.3 KB gzipped), no external dependencies
  • 📘 TypeScript: Full type definitions included
  • ♿ Accessible: Keyboard navigation and focus management

📦 Installation

npm install reactjs-virtual-keyboard
# or
yarn add reactjs-virtual-keyboard
# or
pnpm add reactjs-virtual-keyboard

🚀 Quick Start

Option 1: GlobalVirtualKeyboard (Recommended)

Add once at your app root - automatically shows keyboard for all inputs:

import { GlobalVirtualKeyboard } from 'reactjs-virtual-keyboard';
import 'reactjs-virtual-keyboard/styles.css';

function App() {
  return (
    <div>
      <input type="text" placeholder="Click any input!" />
      <input type="email" placeholder="Email" />
      <input type="number" placeholder="Numbers" />
      
      <GlobalVirtualKeyboard />
    </div>
  );
}

Option 2: VirtualKeyboard (Manual Control)

For more control over when and where the keyboard appears:

import { useRef, useState } from 'react';
import { VirtualKeyboard } from 'reactjs-virtual-keyboard';
import 'reactjs-virtual-keyboard/styles.css';

function App() {
  const inputRef = useRef<HTMLInputElement>(null);
  const [isInputFocused, setIsInputFocused] = useState(false);

  return (
    <div>
      <input
        ref={inputRef}
        type="text"
        onFocus={() => setIsInputFocused(true)}
        onBlur={() => setIsInputFocused(false)}
      />

      {isInputFocused && (
        <VirtualKeyboard
          focusedInputRef={inputRef}
          isInputFocused={isInputFocused}
        />
      )}
    </div>
  );
}

📖 API Reference

<GlobalVirtualKeyboard />

Automatically manages keyboard visibility for all inputs on the page.

interface GlobalVirtualKeyboardProps {
  enabled?: boolean;                              // Enable/disable keyboard (default: true)
  className?: string;                              // Custom CSS class
  onVisibilityChange?: (visible: boolean) => void; // Visibility change callback
  onEnterClick?: () => void;                       // Enter key callback
  onChange?: (value: string) => void;              // Value change callback
}

Example:

<GlobalVirtualKeyboard
  enabled={true}
  onEnterClick={() => console.log('Enter pressed!')}
  onChange={(value) => console.log('Value:', value)}
/>

<VirtualKeyboard />

Main keyboard component with extensive customization options.

interface VirtualKeyboardProps {
  // Required props
  focusedInputRef: RefObject<HTMLInputElement | HTMLTextAreaElement | null>;
  isInputFocused: boolean;
  
  // Layout & behavior
  inputType?: 'text' | 'email' | 'number' | etc;  // HTML input type
  defaultLayout?: 'letters' | 'symbols' | 'numbers';
  syncWithHardwareKeyboard?: boolean;             // Enable hardware sync (default: true)
  
  // Callbacks
  onEnterClick?: () => void;
  onChange?: (value: string) => void;
  validate?: (value: string) => boolean;          // Custom validation
  
  // Customization
  className?: string;
  theme?: VirtualKeyboardTheme;
  customLayouts?: {
    letters?: string[][];
    symbols?: string[][];
    numbers?: string[][];
  };
  
  // Key customization
  keyLabels?: Record<string, string>;             // Custom key labels
  hiddenKeys?: string[];                          // Keys to hide
  disabledKeys?: string[];                        // Keys to disable
  renderKey?: (key: string, defaultRender: ReactNode) => ReactNode;
  renderSpecialKey?: (type: string, defaultRender: ReactNode) => ReactNode;
  
  // Behavior configuration
  continuousPressConfig?: {
    initialDelay?: number;                        // Default: 500ms
    interval?: number;                            // Default: 50ms
  };
  scrollConfig?: {
    enabled?: boolean;
    offset?: number;
  };
}

Example with customization:

<VirtualKeyboard
  focusedInputRef={inputRef}
  isInputFocused={isInputFocused}
  
  // Custom key labels
  keyLabels={{
    enter: 'Submit',
    space: 'Space Bar',
    backspace: 'Del'
  }}
  
  // Hide specific keys
  hiddenKeys={['capslock']}
  
  // Disable certain keys
  disabledKeys={['@', '#']}
  
  // Custom layout
  customLayouts={{
    letters: [
      ['q', 'w', 'e', 'r', 't', 'y'],
      ['a', 's', 'd', 'f', 'g', 'h'],
      ['z', 'x', 'c', 'v', 'b', 'n']
    ]
  }}
  
  // Adjust continuous press behavior
  continuousPressConfig={{
    initialDelay: 300,
    interval: 40
  }}
  
  // Disable hardware keyboard sync
  syncWithHardwareKeyboard={false}
/>

🎨 Theming

Using CSS Variables

.vk-container {
  --vk-bg-color: #2c3e50;
  --vk-key-color: #34495e;
  --vk-key-text-color: #ecf0f1;
  --vk-key-active-color: #3498db;
  --vk-key-hover-color: #2c3e50;
  --vk-active-state-color: #e74c3c;
  --vk-key-border-radius: 8px;
  --vk-key-font-size: 18px;
  --vk-key-height: 50px;
}

Theme Object

const darkTheme = {
  backgroundColor: '#1a1a1a',
  keyColor: '#2d2d2d',
  keyTextColor: '#ffffff',
  keyActiveColor: '#0066cc',
  keyHoverColor: '#3d3d3d',
  activeStateColor: '#00cc66',
  keyBorderRadius: '6px',
  keyFontSize: '16px',
  keyHeight: '48px'
};

<VirtualKeyboard theme={darkTheme} {...props} />

🔧 Utility Functions & Hooks

For advanced use cases, you can import utilities directly:

import {
  // Caret management
  createCaretManager,
  
  // Hardware keyboard event handling
  setupHardwareKeyboard,
  
  // Validation utilities
  validateValueUtil,
  getInitialLayout,
  
  // Scroll utilities
  scrollInputIntoView,
  resetScrollPosition,
  
  // Input value sync
  setInputValueAndDispatchEvents,
  
  // Hooks (only for React state/effects)
  useContinuousPress,
  useKeyboardScroll
} from 'reactjs-virtual-keyboard';

createCaretManager

Pure function for managing caret position and text manipulation:

import { createCaretManager } from 'reactjs-virtual-keyboard';

const inputRef = useRef<HTMLInputElement>(null);
const { insertText, backspace } = createCaretManager(() => inputRef.current);

// Insert text at caret position
insertText('Hello');

// Delete character before caret
backspace();

setupHardwareKeyboard

Set up hardware keyboard event listeners:

import { setupHardwareKeyboard } from 'reactjs-virtual-keyboard';

useEffect(() => {
  const cleanup = setupHardwareKeyboard({
    onBackspace: () => console.log('Backspace'),
    onEnter: () => console.log('Enter'),
    onSpace: () => console.log('Space'),
    onCapsToggle: () => console.log('Caps'),
    onKeyClick: (key) => console.log('Key:', key)
  });
  
  return cleanup; // Clean up listeners
}, []);

📱 Input Type Behaviors

The keyboard automatically adapts to different input types:

| Input Type | Layout | Special Keys | Validation | |-----------|--------|--------------|------------| | text | QWERTY | All | None | | email | QWERTY + @ | Space, @ | Email chars only | | number | Numbers only | Backspace, Enter | Digits only | | tel | Numbers | Phone chars | Digits, +, - | | url | QWERTY | .com, www. | URL chars |


🎯 Custom Layouts Example

const customLayouts = {
  letters: [
    ['a', 'b', 'c', 'd', 'e'],
    ['f', 'g', 'h', 'i', 'j'],
    ['k', 'l', 'm', 'n', 'o'],
    ['p', 'q', 'r', 's', 't'],
    ['u', 'v', 'w', 'x', 'y', 'z']
  ],
  symbols: [
    ['!', '@', '#', '$', '%'],
    ['^', '&', '*', '(', ')'],
    ['-', '_', '=', '+', '['],
    [']', '{', '}', '|', '\\']
  ]
};

<VirtualKeyboard
  {...props}
  customLayouts={customLayouts}
/>

🎭 Custom Render Functions

<VirtualKeyboard
  {...props}
  renderKey={(key, defaultRender) => (
    <div className="my-custom-key">
      {key.toUpperCase()}
    </div>
  )}
  renderSpecialKey={(type, defaultRender) => {
    if (type === 'enter') {
      return <button className="submit-btn">Submit</button>;
    }
    return defaultRender;
  }}
/>

📦 Bundle Size

  • ESM: 26.14 kB minified (6.28 kB gzipped)
  • CJS: 12.56 kB minified (4.69 kB gzipped)
  • CSS: 6.03 kB (1.68 kB gzipped)

Tree-shaking enabled - import only what you need!


🌐 Browser Support

  • Modern Browsers: Chrome, Firefox, Safari, Edge (last 2 versions)
  • Mobile: iOS Safari, Chrome Mobile, Samsung Internet
  • Requires React 16.8+ (hooks support)

🛠️ Development

# Clone repository
git clone https://github.com/yourusername/reactjs-virtual-keyboard.git

# Install dependencies
npm install

# Build library
npm run build

# Run demo (if available)
cd demo && npm install && npm run dev

📄 License

MIT © Kalpesh Rane


🤝 Contributing

Contributions welcome! Please open an issue or submit a PR.


📝 Changelog

v2.0.0 (Latest)

  • New: Multi-language support with built-in language switcher
  • ✨ Added languages, currentLanguage, onLanguageChange, showLanguageSwitcher props
  • ✨ Enhanced customization API (24+ new props)
  • ⚡ Removed unnecessary hook wrappers for better performance
  • 📦 Optimized bundle size with better tree-shaking
  • 🏗️ Reorganized file structure for clarity
  • 🔧 Exported utility functions for advanced usage
  • 📘 Improved TypeScript types with ReadonlyArray support
  • 📚 Complete documentation website with interactive playground

v1.0.0

  • 🎉 Initial release