Frontend Engineer

Lohith Mallikarjun

Frontend engineer with 5 years of experience building production React/Next.js applications, including a healthcare-insurance portal serving enterprise customers that cut claim turnaround by 72%. Specializes in scalable UI architecture, performance optimization, and end-to-end testing.

Technologies

What I work with

Languages
  • JavaScript
  • TypeScript
  • HTML5
  • CSS
Technologies
  • React
  • Redux
  • Jest
  • SASS
  • React Router
  • Next.js
  • Strapi
  • TanStack Query
  • Node.js
Testing / Tooling
  • Vitest
  • Playwright
  • MSW
  • Storybook
  • Vite

Projects

Things I've built in the open

Tactile

Context-aware keyboard shortcuts for the web

How hard can ⌘K be?

I was building a command palette. You know the pattern: press ⌘K anywhere in the app and a search box drops down. Every tool I admire has one. I figured it was an afternoon of work.

And it was. I wired it up with a shortcut library in maybe ten minutes, demoed it to a friend, felt smug, moved on.

A week later I pressed ⌘K while my cursor was sitting inside a text input, and Chrome focused the address bar instead.

The plugin that radicalized me

I assumed I’d broken something. I hadn’t. Mousetrap, like nearly every shortcut library, ignores keystrokes coming from an input, textarea, or select. On purpose. It’s a sensible default, you don’t want “g i” navigation firing while someone types “going home” into a form.

Except a command palette is precisely the thing that should open from anywhere. And because the library never saw the event, it never called preventDefault, so the browser’s own ⌘K won. My shortcut didn’t lose a fight. It never showed up to one.

The ecosystem’s answer turned out to be a plugin called mousetrap-global-bind. A plugin. For one keystroke.

While digging I found the Oxide console repo, where their team hit this exact bug (issue #724 reads like a transcript of my afternoon) and fixed it by wrapping the plugin in a custom hook, with the PR author openly worrying about what it might do to accessibility. These are people who build racks with their own hypervisor, and ⌘K inside an input made them nervous.

That was the moment this stopped being a bug and became a rabbit hole.

The part that actually scared me

Once I was reading library source instead of writing my app, I noticed what everything sits on: KeyboardEvent.keyCode. Mousetrap, hotkeys-js, keymaster. All of them matching against a property MDN has marked deprecated for years, whose values famously differ across browsers and keyboard layouts.

Here’s where that stops being spec pedantry. On a German QWERTZ keyboard, the letters Y and Z trade places. So which physical key should ⌘Z fire on? The key printed Z, or the key sitting where Z sits on my board in Bengaluru? There is a right answer. VS Code picks the physical position for letters, so muscle memory keeps working when layouts change. keyCode gives you neither, reliably, and the failure only shows up on keyboards you don’t own. Nobody files a bug report that says “undo felt wrong once.” They just quietly stop trusting your app.

The modern platform gives you two clean signals: event.key (the character produced) and event.code (the physical position). The right behavior needs both, chosen per key. Letters by position. Symbols by character, because ? means the glyph, wherever a layout hides it.

I kept waiting to find the npm package that worked this way, with the thing VS Code has had since forever: shortcuts as rules, gated by when clauses, conflicts resolved by priority, the whole keymap inspectable.

I didn’t find it.

So I wrote it.

What came out the other side

Tactile is a small TypeScript engine (about 5.5 kB) where every shortcut is a rule instead of a string glued to a callback:

kb.add({
  id: 'editor.bold',
  keys: 'mod+b',
  when: "scope == 'editor' && !readOnly",
  handler: toggleBold,
});

Matching uses event.key and event.code together, so ⌘Z stays on the physical Z keycap in Berlin and ? still means the question mark in New York. The input problem that started all this is one documented option, not a plugin. Two rules fighting over the same keystroke get detected at registration and resolved by priority, the way VS Code does it, instead of both silently firing. And because the engine talks to an injected event source rather than the DOM directly, it had 42 passing tests before it ever ran in a browser.

I want to be fair here. If you need three global shortcuts on an internal tool, you don’t need any of this. tinykeys is 700 bytes and excellent, and I wrote a comparison page saying exactly that, which my marketing brain considers a blunder and my engineering brain considers the whole point.

If you’re building anything with more than a handful of shortcuts, the playground is the fastest way to see whether it fits.