# react-simple-keyboard puts an on-screen keyboard in a React form

> react-simple-keyboard is a customizable, responsive and lightweight virtual keyboard component for React, distributed as four separate builds with an exports map, aimed at touch and kiosk interfaces where the native keyboard is not good enough.

**hodgef/react-simple-keyboard** — React Virtual Keyboard - Customizable, responsive and lightweight

- Repository: https://github.com/hodgef/react-simple-keyboard
- Website: https://virtual-keyboard.js.org/react
- Stars: 631 · Forks: 70
- Language: JavaScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/hodgef-react-simple-keyboard

## A keyboard you control, for interfaces the device keyboard does not suit

react-simple-keyboard is described as a virtual keyboard for React, customizable, responsive and lightweight, and the project tagline is the same three words. The homepage for the React version is at virtual-keyboard.js.org/react.

The use cases that need this are specific. A kiosk terminal with a touchscreen wants a fixed layout rather than whatever the operating system decides to show. A data entry form for a warehouse scanner wants a numeric pad. A shared tablet on a desk might want the keyboard to occupy a defined region of the screen rather than a floating panel. In each of those cases the argument for a virtual keyboard is not that the native one is bad, but that the interface needs to control the layout, the size and the behaviour of the input surface.

That is what the project is for, and it is worth being clear that it is a keyboard component rather than a text input system. The repository topics name kiosk, onscreen-keyboard, touchscreen and virtual-keyboard, and the fact that the same project ships vanilla JavaScript, Angular and Vue versions says the core is a framework-agnostic keyboard with a React binding on top.

The React package is published to npm as react-simple-keyboard, with the MIT licence and a live demo at simple-keyboard.com/demo. The repository carries a GitLab mirror, and there is a Discord channel for questions.

For the audience, the deciding question is simple: does the interface need to dictate the keys? If yes, this is a focused tool for it. If no, the device already has one.

## Legacy browser support is a first-class decision

The compatibility list is long and includes browsers that most projects have given up on, and that is a deliberate design choice rather than an accident.

The list names Internet Explorer 11, Edge (Spartan) 16+, Edge (Anaheim and Edge Chromium) 79+, Chrome 49+, Safari 9+, Firefox 57+ and iOS 9+.

The README explains the escape hatch. If you do not want to support old browsers, you can use the Modern Browsers bundle, index.modern.js in the build directory. So the project carries the cost of legacy support in the default artefact and gives you a way to opt out of it.

That trade-off shows up in the repository layout, which has four webpack configurations: webpack.config.js for the default build, webpack.config.demo.js for the demo server, webpack.config.modern.js for the modern bundle, and webpack.config.modern_esm.js for a modern ES module build. The sideEffects list in the package metadata names the files that are considered to have side effects, and it includes the CSS, the polyfills file and the two component files, which is what lets a bundler drop the rest of the library when your application imports only the parts it uses.

The IE11 support in particular is a statement about the audience. Kiosk and industrial deployments age slowly, and a hospital or a logistics system that has been running the same terminal for a decade is exactly the environment where a virtual keyboard with a fixed layout pays for itself.

## Four builds behind an exports map

The package metadata is more elaborate than most component packages, and the reason is that it has to serve several bundlers and several module systems without the application author having to think about it.

The top-level fields declare the classic entry points:

```json
  "main": "build/index.js",
  "module": "build/index.modern.esm.js",
  "types": "build/index.d.ts",
```

And then there is an exports map, which is the part that matters for anything modern. It declares separate import and require conditions, each with its own types entry, and a default fallback:

```json
    "exports": {
      ".": {
        "import": {
          "types": "./build/index.modern.d.ts",
          "default": "./build/index.modern.esm.js"
        },
        "require": {
          "types": "./build/index.d.ts",
          "default": "./build/index.js"
        },
        "default": "./build/index.js"
      },
      "./build/*": "./build/*",
      "./package.json": "./package.json"
    },
```

Note what the import condition resolves to. A bundler that honours the exports map and uses ES module semantics gets the modern ES module build, with its own type declarations, while a CommonJS require gets the default build. The subpath for the build directory is exposed as well, so consumers can reach individual files such as the stylesheets, and package.json itself is exported so that tooling can read it.

The net effect is that the legacy bundle is what you get by default in a CommonJS or unspecified context, and the modern one is what you get in a modern ES module context. An application that wants the legacy behaviour in a modern bundler has to ask for it explicitly, which is why the README points at index.modern.js and, presumably, at the default build for the other case.

## The demo, and the build pipeline behind the package

The README keeps its own instructions short, pointing you at the getting started and documentation pages, but it does document how to run the demo on your own machine. You clone the repository, run npm install, run npm start, and then visit http://localhost:3000/.

The npm scripts explain how that works and how the published package is produced:

```json
  "scripts": {
    "start": "webpack serve --config webpack.config.demo.js",
    "build": "npm run generate-types && webpack && npm run build-modern && npm run build-modern-esm && tsc",
    "build-modern": "webpack --config webpack.config.modern.js",
    "build-modern-esm": "webpack --config webpack.config.modern_esm.js",
    "test": "jest --silent",
```

The build is a chain: generate the keyboard types, run the default webpack build, run the modern build, run the modern ES module build, and finally run the TypeScript compiler to emit the declarations. The type generation step is its own script, node scripts/generateKeyboardTypes.js, which means the keyboard layouts are described in a data form that is turned into TypeScript types at build time rather than hand-written and drifting out of date.

Tests run under Jest with the silent flag, and a coverage script wraps the same runner with the coverage flag. The prepare script runs the build, so the package is built when it is installed from a git reference rather than from the registry.

The repository also carries a tsconfig.json, a babel.config.js, an eslintrc and eslintignore, a CODE_OF_CONDUCT.md and a CONTRIBUTING.md, and a build directory that is published with the package.

## The same keyboard in other frameworks

The project is not React-specific in its core, and the README points to the other versions: a vanilla JavaScript implementation and versions for Angular and Vue.js, each with its own demo.

That structure tells you something about the design. The keyboard behaviour, the layout model and the input handling live in a framework-agnostic core, and each framework binding is a thin adapter. The React package's TypeScript source sits under src with a components directory, and the sideEffects list names both a Keyboard.tsx and a KeyboardModern.tsx, which is the same split the build configurations make between the legacy and modern bundles.

The practical benefit for a React team is that a layout fixed for a kiosk in one framework behaves the same way if the product later has a second front end, and the layouts are not something you have to re-implement per stack.

The documentation itself is part of the product. There is a getting started page, a documentation site at simple-keyboard.com/react/documentation, a questions and answers page for common use cases, and a separate demo. The repository README is deliberately thin because that material lives on the site instead, which is the right call for a library whose API surface is mostly configuration options.

## Version state and the question of the legacy build

The licence is MIT, with the licence file in the repository and a badge in the readme pointing at it. The package metadata records version 3.8.284, which is a patch-level number that is much larger than the three-character release tags suggest, and the published release tags are 3.8.0 on 2024-09-12, 3.7.0 on 2023-08-21 and 3.6.0 on 2023-05-26, each marked as a stable release.

The last push to the repository was on 2026-10-22, and the repository is not archived, so the code is being worked on continuously even though the last tagged release is from 2024. The gap between 3.8.0 and 3.8.284 suggests a project that ships often, with the patch number carrying the real version information for anyone pinning.

The bigger question for an adopter is the direction of travel on the legacy bundle. A package that supports Internet Explorer 11 in its default artefact has to keep transpiling and polyfilling for a browser that no longer appears in anyone's usage statistics, and the README's advice is that you can switch to the modern bundle if you do not need the old ones. Whether to keep the legacy build is therefore a question with a deadline attached to it, and the answer will be different for a kiosk vendor with a long replacement cycle than for a consumer web product.

For the React version the maintenance has clearly continued, and the version numbering suggests a steady drip of fixes rather than a project that has stopped.

## Conclusion

react-simple-keyboard fits a team building a touch interface, a kiosk or a data entry screen where the operating system's own keyboard is in the way, and who wants a keyboard whose layout and behaviour they control rather than the device's. It is the wrong choice for an ordinary form on a phone, where the native keyboard is better, and it is the wrong choice if you need handwriting or a full input method, because the component is a keyboard, not an IME. Before adopting it, read the getting started and documentation pages, since the repository README defers almost all API detail to them, and check the exports map in the package metadata against your bundler, because the package ships several builds and a wrong entry point is the likely first integration problem.

## FAQ

### What is react-simple-keyboard?

It is a virtual keyboard component for React, described as customizable, responsive and lightweight. The project also publishes vanilla JavaScript, Angular and Vue.js versions of the same keyboard.

### How do I run the react-simple-keyboard demo locally?

Clone the repository, run npm install, run npm start, and then visit http://localhost:3000/. The start script runs webpack serve with the demo configuration.

### Which browsers does react-simple-keyboard support?

The compatibility list names Internet Explorer 11, Edge Spartan 16+, Edge Chromium 79+, Chrome 49+, Safari 9+, Firefox 57+ and iOS 9+. If you do not need old browsers, the README points to the Modern Browsers bundle in the build directory.

### Why does react-simple-keyboard ship several builds?

The package declares a classic main, module and types entry plus an exports map, so an ES module bundler receives the modern build with its own declarations while a CommonJS require receives the default build. There are separate webpack configurations for the default, modern and modern ES module builds.

### What licence is react-simple-keyboard released under?

MIT. The licence file is in the repository and the readme carries a matching badge, and the project is also mirrored on GitLab.

## Sources

- [hodgef/react-simple-keyboard on GitHub](https://github.com/hodgef/react-simple-keyboard)
- [License: MIT](https://github.com/hodgef/react-simple-keyboard/blob/master/LICENSE)
- [Project website](https://virtual-keyboard.js.org/react)
- [README](https://github.com/hodgef/react-simple-keyboard/blob/master/README.md)
- [Releases](https://github.com/hodgef/react-simple-keyboard/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hodgef-react-simple-keyboard
