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

react-modifiers

v1.0.2

Published

Use modifiers to intercept event handling more concisely in React, like "stop", "prevent".

Readme

React Modifiers

npm GitHub License: MIT

Use modifiers to enhance event handling concisely in React.

This package brings Vue-style event modifiers to React, enabling concise and intuitive event handling interception. With React Modifiers, you can chain modifiers to restrict when event handlers execute, eliminating boilerplate code for event filtering, propagation control, and modifier key checks.

Installation

# npm
npm install react-modifiers

# yarn
yarn add react-modifiers

# pnpm
pnpm add react-modifiers

Basic Usage

Import the mod utility and chain modifiers to your event handlers:

Example 1: Keyboard Shortcut (Ctrl+L)

Trigger a handler only when the Ctrl+L shortcut is pressed:

import mod from "react-modifiers";

<button onKeyDown={mod.ctrl.l(e => {
    console.log("Ctrl+L pressed!");
})} />

Example 2: Stop Propagation + Prevent Default

Prevent event bubbling and browser default behavior before executing the handler:

import mod from "react-modifiers";

<button onClick={mod.stop.prevent(e => {
    console.log("Click handled without propagation/default behavior!");
})} />

// Or just

<button onClick={mod.handled(e => {
    console.log("Click handled without propagation/default behavior!");
})} />

Example 3: Modifiers Only Without Handler

The handler function can be ignored, it will only handled by modifiers.

import mod from "react-modifiers";

<form onSubmit={mod.prevent()} />

Key Concepts

Chaining Order Matters

Modifiers are executed in the order they are chained. This affects behavior:

  • mod.prevent.self: Prevents default behavior for all clicks (element + children)
  • mod.self.prevent: Prevents default behavior only for clicks on the element itself

Modifier Logic Rules

  • For keyboard modifier key modifiers (ctrl/shift/alt/meta): Chained modifiers mean AND (all must be pressed)

  • For other modifiers—keyboard character/function key modifiers, mouse button modifiers, pointer type modifiers—except universal modifiers (e.g., a/b/space/tab/enter/middle/right/touch): Chained modifiers mean OR (any one pressed or used)

Full Modifier Reference

1. Universal Modifiers (All Event Types)

Apply to any React synthetic event type:

|Modifier|Behavior| |---|---| |.stop|Calls event.stopPropagation()| |.prevent|Calls event.preventDefault()| |.handled|Shorthand for .stop.prevent (calls both methods)| |.self|Triggers handler only if the event originates from the element itself (not children)| |.once|Triggers handler a maximum of one time|

2. Modifier Key Modifiers (KeyboardEvent/MouseEvent/PointerEvent)

Apply to keyboard, mouse, or pointer events (case-insensitive):

|Modifier|Behavior| |---|---| |.ctrl|Triggers handler only when Ctrl/Control key is pressed| |.shift|Triggers handler only when Shift key is pressed| |.alt|Triggers handler only when Alt/Option key is pressed| |.meta|Triggers handler only when Win/Command key is pressed| |.capsLockOn|Triggers handler only when CapsLock is active| |.capsLockOff|Triggers handler only when CapsLock is inactive| |.numLockOn|Triggers handler only when NumLock is active| |.numLockOff|Triggers handler only when NumLock is inactive| |.scrollLockOn|Triggers handler only when ScrollLock is active| |.scrollLockOff|Triggers handler only when ScrollLock is inactive| |.exact|Enforces exact modifier key combination (no extra keys)|

[!NOTE]

  • .ctrl works for both left and right Ctrl/Control key (similar to other modifier keys).
  • Do not use both .capsLockOn and .capsLockOff (similar to other lock keys) simultaneously, this will never trigger the handler!

.exact Examples

// Triggers if Ctrl is pressed (even with Alt/Shift)
<button onClick={mod.ctrl(handleClick)} />

// Triggers ONLY if Ctrl is pressed (no other modifier keys)
<button onClick={mod.ctrl.exact(handleClick)} />

// Triggers ONLY if no modifier keys are pressed
<button onClick={mod.exact(handleClick)} />

[!NOTE]

You can put .exact anywhere. The following code has the same behavior.

<button onKeyDown={mod.ctrl.p.exact(handleClick)} />
<button onKeyDown={mod.exact.ctrl.p(handleClick)} />
<button onKeyDown={mod.ctrl.exact.p(handleClick)} />

3. Other Key Modifiers (KeyboardEvent)

Apply exclusively to keyboard events (onKeyDown/onKeyUp/onKeyPress):

Basic Key Modifiers

Common keys supported (case-insensitive):

  • .enter, .tab, .delete, .backspace, .space, .esc
  • .up, .down, .left, .right
  • .pageUp, .pageDown, .home, .end, .printScreen, .pause, .insert
  • All letter/number/symbol keys (.a, .b, ..., .z, [0], [1], ..., [9], ["`"], ["/"], ["\\"])
  • .application (also known as context menu key)

[!NOTE]

  • Number and special symbols (e.g., `, /, \) must be wrapped in brackets:
    • mod.ctrl["/"](handler)
    • mod.ctrl["\\"](handler)
    • mod.ctrl[0](handler)
  • Do not use shift-modified symbol keys (e.g. !, @, #, ?), just use primary symbol keys (e.g. -, =, ;, ').

For Numpad

  • It shares the same modifiers as the main. For example, [0] works for both 0/) key and numpad 0/Insert key. Same as other numbers, ["."], ["-"], ["/"], .enter.
  • ["+"] is an alias of ["="], and it works for both =/+ key and numpad + key.
  • ["*"] works for numpad * key only, it doesn't work for 8/* key.

Special Keyboard Modifiers

|Modifier|Behavior| |---|---| |.arrow|Shorthand for .up.down.left.right (any arrow key)| |.noRepeat|Triggers handler only once for held keys (ignores event.repeat = true)|

Keyboard Example Combinations

// Ctrl+Shift+L OR Ctrl+Shift+P (L/P = OR; Ctrl/Shift = AND)
<button onKeyDown={mod.ctrl.shift.l.p(handleKeyDown)} />

// Ctrl+Shift+L (stop propagation) OR Ctrl+Shift+P (no stop)
<button onKeyDown={mod.ctrl.shift.l.stop.p(handleKeyDown)} />

// Ctrl+/ (special symbol via bracket notation)
<button onKeyDown={mod.ctrl["/"](handleKeyDown)} />

// Arrow key (up/down/left/right) with no repeat
<button onKeyDown={mod.arrow.noRepeat(handleKeyDown)} />

4. Mouse Button Modifiers (MouseEvent/PointerEvent)

Apply to mouse or pointer events (onClick/onMouseDown/onPointerUp etc.):

|Modifier|Behavior| |---|---| |.left|Triggers handler only for left mouse button clicks| |.right|Triggers handler only for right mouse button clicks| |.middle|Triggers handler only for middle mouse button clicks|

Mouse Example Combinations

You can chain them together to indicate that any of them can trigger the handler.

// Triggers handler for both middle mouse button and right mouse button
// Left mouse button will not trigger the handler
<button onClick={mod.middle.right(handleClick)} />

5. Pointer Type Modifiers (PointerEvent)

Apply exclusively to pointer events (onPointerDown/onPointerEnter etc.):

|Modifier|Behavior| |---|---| |.mouse|Triggers handler only for mouse input| |.touch|Triggers handler only for touch input (mobile/tablet)| |.pen|Triggers handler only for stylus/pen input|

Pointer Example Combinations

You can chain them together to indicate that any of them can trigger the handler.

// Triggers handler for both touch and pen input
// Mouse will not trigger the handler
<button onPointerDown={mod.touch.pen(handleTouch)} />

Advanced Examples

Combine Modifier Keys + Mouse/Pointer Modifiers

// Ctrl + mouse left click (Not Ctrl+Left Arrow!)
<button onClick={mod.ctrl.left(handleCtrlClick)} />

// Shift + touch screen, with NumLock on
<button onClick={mod.shift.touch.numLockOn(handleShiftTouch)} />

Combine Mouse + Universal Modifiers

// Prevent default, trigger once, right click only (self)
<button onClick={mod.prevent.once.right.self(handleRightClick)} />

Combine Mouse + Pointer Modifiers

// Mouse or touch input, middle or right click only if mouse input
<button onPointerUp={mod.middle.right.mouse.touch(handleClick)} />

Complex Keyboard Shortcut

// Ctrl+Shift+Delete (prevent default) OR Ctrl+Shift+Backspace (stop propagation)
<button onKeyDown={mod.ctrl.shift.delete.prevent.backspace.stop(handleKeyDown)} />

Notes

  • TypeScript Support: Full TypeScript support. Due to technical limitations, the modifiers for non specific events will also be displayed in the suggestion list, but it can report errors normally after use.

  • Case-Insensitive: All modifiers are case-insensitive. However, TypeScript will suggest the most appropriate camel case.

  • Event Type Compatibility: Ensure modifiers match the event type (e.g., .touch only works with onPointerDown, not onKeyDown).

  • Chaining Order: Always test modifier order—execution is sequential (e.g., .self.prevent.prevent.self).

  • Do not Duplicate: Duplicate modifiers will not have any effect, they will only waste your traffic out of thin air.

  • Synthetic Events And Native Events: React Modifiers work with both React synthetic events and native DOM events.

  • Browser Support: Follows React's browser support matrix—modifiers like .touch require PointerEvent support (modern browsers); .noRepeat require Chromium 137 and above.

License

react-modifiers is available under the MIT License. See the LICENSE file for more info.