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-hotkeys-selection

v1.1.0

Published

A React utility for selecting list elements with keyboard, like Windows or macOS

Readme

React Hotkeys Selection

A React library for handling multi-item selection with full keyboard shortcuts and mouse gestures support, similar to native OS experiences. Use it on:

  • ✅ Tables with checkboxes where you need to select rows, such as in GMail.
  • ✅ Image galleries
  • ✅ Lists of folders or files
  • ✅ In any list of items that need selection!

Demo

Storybook Demo

Features

  • Multi-selection: Support for selecting multiple items
  • ⌨️ Keyboard shortcuts: Ctrl/Cmd+Click for individual selection, Shift+Click for ranges
  • 🖱️ Selection strategy: Individual selection, toggle selection, or no selection
  • 🎯 TypeScript: Fully typed with generic support
  • 🔧 Flexible: Configurable selection behaviors and event handlers in your items
  • 🚀 Optimized: Uses memoized callbacks for better performance

Installation

Install with pnpm or your preferred package manager:

pnpm add react-hotkeys-selection

Quick Start

1. Setup Provider

import { SelectionProvider } from 'react-hotkeys-selection'

const items = [
  { id: 1, name: 'Item 1' },
  { id: 2, name: 'Item 2' },
  { id: 3, name: 'Item 3' }
]

function App() {
  return (
    <SelectionProvider initialState={items}>
      <ItemList />
    </SelectionProvider>
  )
}

2. Use in Components

import { useSelection, useSelectionItem } from 'react-hotkeys-selection'

function ItemList() {
  const { selected, clear } = useSelection()

  return (
    <div>
      <button onClick={clear}>Clear ({selected.length})</button>
      {items.map((item) => (
        <Item
          key={item.id}
          item={item}
        />
      ))}
    </div>
  )
}

function Item({ item }) {
  const { isSelected, handleSelection } = useSelectionItem(item)

  return (
    <div
      onClick={handleSelection}
      style={{
        backgroundColor: isSelected ? '#e3f2fd' : 'white',
        padding: '8px',
        cursor: 'pointer'
      }}
    >
      {item.name}
    </div>
  )
}

API Reference

SelectionProvider

Provides selection context to child components.

Props: HotkeysSelectionProps<T>

  • initialState: T[] - Array of selectable items
  • strategy?: HotkeysSelectionStrategy - Individual selection 'single', toggle selection 'toggle', or no selection 'none' (default: 'single')
  • useCtrlKey?: boolean - Enable Ctrl/Cmd+Event for individual selection (default: true)
  • useShiftKey?: boolean - Enable Shift+Event for range selection (default: true)

useSelection<T>()

Main hook providing selection functionality.

Returns: HotkeysSelectionReturn<T>

| Property | Type | Description | | ----------------- | ------------------------------------------ | --------------------------- | | selected | T[] | Currently selected items | | isSelected | (item: T) => boolean | Check if item is selected | | handleSelection | (event: SyntheticEvent, item: T) => void | Event handler for items | | clear | () => void | Clear all selection | | add | (items: T[]) => void | Add items to selection | | remove | (items: T[]) => void | Remove items from selection |

useSelectionItem<T>(item: T)

Convenience hook for individual item components.

Returns: HotkeysSelectionItemReturn<T> | Property | Type | Description | |----------|------|-------------| | isSelected | boolean | Whether this item is selected | | handleSelection | (event: SyntheticEvent) => void | Pre-configured event handler |

useSelectionCore<T>(props)

Low-level hook that can be used without the provider. Requires manual prop drilling to child components.

Props: HotkeysSelectionProps<T>

Returns: HotkeysSelectionReturn<T>

Note: When using useSelectionCore directly, you cannot use useSelectionItem as it requires the context provider. You'll need to pass the selection state manually to child components.

Selection Behaviors

| Interaction | Behavior | | -------------------- | -------------------------------------------- | | Event | Selection by predefined strategy | | Ctrl/Cmd + Event | Toggle clicked item without affecting others | | Shift + Event | Select range from last individual item |

Advanced Usage

Programmatic Selection

function Controls() {
  const { selected, add, remove, clear } = useSelection()

  const selectAll = () => add(items)
  const selectEvens = () => add(items.filter((_, i) => i % 2 === 0))

  return (
    <div>
      <button onClick={selectAll}>Select All</button>
      <button onClick={selectEvens}>Select Evens</button>
      <button onClick={clear}>Clear</button>
    </div>
  )
}

With TypeScript

interface User {
  id: number
  name: string
  email: string
}

function UserList() {
  const users: User[] = [
    /* ... */
  ]

  return (
    <SelectionProvider<User> initialState={users}>
      <UserTable />
    </SelectionProvider>
  )
}

function UserTable() {
  const { selected } = useSelection<User>()
  // selected is properly typed as User[]
}

Using useSelectionCore Directly

function DirectUsage() {
  const items = [
    /* ... */
  ]
  const selection = useSelectionCore({ initialState: items })

  return (
    <div>
      <button onClick={selection.clear}>Clear</button>
      {items.map((item) => (
        <Item
          key={item.id}
          item={item}
          selection={selection} // Manual prop drilling required
        />
      ))}
    </div>
  )
}

function Item({ item, selection }) {
  return (
    <div
      onClick={(e) => selection.handleSelection(e, item)}
      style={{
        backgroundColor: selection.isSelected(item) ? '#e3f2fd' : 'white'
      }}
    >
      {item.name}
    </div>
  )
}

Storybook Examples

This library includes comprehensive Storybook examples:

  • Basic: Simple list selection
  • Grid: Grid layout with selection
  • WithControls: Advanced controls and programmatic selection

Performance

  • Immutable state updates for React compatibility

Requirements

  • React 16.8+
  • TypeScript 4.5+

License

MIT © Benja Osuna