An open API service indexing awesome lists of open source software.

https://github.com/jalez/react-shortcuts-provider


https://github.com/jalez/react-shortcuts-provider

accessibility eslint hotkeys javascript keybindings keyboard-events keyboard-shortcuts npm-package react react-component react-context react-hooks react-library tailwindcss typescript typescript-library ui-components vite vitest zustand

Last synced: 2 months ago
JSON representation

Awesome Lists containing this project

README

          

# @jalez/react-shortcuts-provider

[![codecov](https://codecov.io/gh/jalez/react-shortcuts-provider/branch/main/graph/badge.svg)](https://codecov.io/gh/jalez/react-shortcuts-provider)
[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-red.svg)](https://github.com/sponsors/jalez)

A React context/provider and utilities for managing keyboard shortcuts in your app. This library provides a decoupled, registry-based keyboard shortcuts system that allows components to register actions with specific key combinations without being tightly coupled to other components.

## Installation

```sh
npm install @jalez/react-shortcuts-provider
```

## Features

- **Registry-based**: Components can register/unregister shortcuts dynamically
- **Decoupled**: No dependencies on other contexts or systems
- **Categorized**: Shortcuts can be organized into categories
- **Automatic handling**: Global keyboard event handling
- **Type-safe**: Full TypeScript support
- **Flexible**: Support for complex key combinations
- **Cross-platform**: Works with Ctrl (Windows/Linux) and Cmd (macOS) automatically
- **Fast Refresh Compatible**: Optimized for React Fast Refresh development

## Quick Start

### 1. Wrap your app with ShortcutsProvider

```tsx
import { ShortcutsProvider } from '@jalez/react-shortcuts-provider';

function App() {
return (



);
}
```

### 2. Register shortcuts in any component

```tsx
import { useEffect } from 'react';
import { registerShortcut, unregisterShortcut, DEFAULT_SHORTCUT_CATEGORIES } from '@jalez/react-shortcuts-provider';

function MyComponent() {
useEffect(() => {
// Register a shortcut
registerShortcut(
DEFAULT_SHORTCUT_CATEGORIES.NAVIGATION,
'my-action',
'Ctrl+M',
() => console.log('My action triggered!'),
'My custom action'
);

// Cleanup
return () => {
unregisterShortcut(DEFAULT_SHORTCUT_CATEGORIES.NAVIGATION, 'my-action');
};
}, []);

return

My Component
;
}
```

### 3. Display shortcuts (optional)

```tsx
import { ShortcutsDisplay } from '@jalez/react-shortcuts-provider';

function MyApp() {
return (


My App


{/* Position the shortcuts display wherever you want */}



);
}
```

## API Reference

### Registry Functions

#### `registerShortcut(category, name, keyCombo, action, description, enabled?, order?)`

Register a new keyboard shortcut.

- `category`: Shortcut category (string)
- `name`: Unique name for the shortcut within its category
- `keyCombo`: Key combination (e.g., "Ctrl+F", "Shift+M", "Delete")
- `action`: Function to execute when triggered
- `description`: Human-readable description
- `enabled`: Whether the shortcut is enabled (default: true)
- `order`: Display order (lower numbers appear first)

#### `unregisterShortcut(category, name)`

Remove a registered shortcut.

#### `getAllShortcuts()`

Get all registered shortcuts across all categories.

### Key Combination Format

The system supports various key combination formats:

- `"Ctrl+F"` - Control + F (or Cmd+F on macOS)
- `"Shift+Delete"` - Shift + Delete
- `"Alt+Tab"` - Alt + Tab
- `"Ctrl+Shift+Z"` - Control + Shift + Z
- `"F11"` - Function key F11
- `"Esc"` - Escape key

### Default Categories

```tsx
DEFAULT_SHORTCUT_CATEGORIES = {
NAVIGATION: "navigation",
VIEW_SETTINGS: "viewSettings",
TOOLS: "tools",
EDITING: "editing",
CUSTOM: "custom",
}
```

### Hooks

#### `useShortcutsRegistry()`

Access the shortcuts registry state:

```tsx
const { shortcuts, getShortcuts, getAllShortcuts } = useShortcutsRegistry();
```

#### `useShortcuts()`

Access shortcuts display state (requires ShortcutsProvider):

```tsx
const { showShortcuts, toggleShortcuts } = useShortcuts();
```

#### `useKeyboardShortcutHandler()`

Enable automatic keyboard event handling (used internally by ShortcutsManager).

## Components

### `ShortcutsProvider`

Main component that provides the complete shortcuts system:

```tsx

```

### `ShortcutsDisplay`

Component that displays registered shortcuts. Position it wherever you want:

```tsx

```

Props:
- `showCategories`: Whether to group shortcuts by category (default: true)
- `maxShortcuts`: Maximum number of shortcuts to show initially (default: 20)
- `className`: Additional CSS classes for positioning and styling

## Examples

### Basic Usage

```tsx
import React, { useState, useEffect } from 'react';
import {
ShortcutsProvider,
ShortcutsDisplay,
registerShortcut,
unregisterShortcut
} from '@jalez/react-shortcuts-provider';

function App() {
const [showMessage, setShowMessage] = useState(false);

useEffect(() => {
registerShortcut(
'Examples',
'show-message',
'Ctrl+M',
() => setShowMessage(prev => !prev),
'Toggle a message',
true,
20
);

return () => {
unregisterShortcut('Examples', 'show-message');
};
}, []);

return (


React Shortcuts Provider Demo





{showMessage && (

Hello from keyboard shortcut!

)}


);
}
```

### Advanced Usage with Multiple Categories

```tsx
import { useEffect } from 'react';
import {
registerShortcut,
unregisterShortcut,
DEFAULT_SHORTCUT_CATEGORIES
} from '@jalez/react-shortcuts-provider';

function MyComponent() {
useEffect(() => {
// Navigation shortcuts
registerShortcut(
DEFAULT_SHORTCUT_CATEGORIES.NAVIGATION,
'next-item',
'ArrowDown',
() => navigateNext(),
'Navigate to next item'
);

// Editing shortcuts
registerShortcut(
DEFAULT_SHORTCUT_CATEGORIES.EDITING,
'delete-item',
'Delete',
() => deleteCurrentItem(),
'Delete current item'
);

// Tools shortcuts
registerShortcut(
DEFAULT_SHORTCUT_CATEGORIES.TOOLS,
'toggle-panel',
'Ctrl+P',
() => togglePanel(),
'Toggle side panel'
);

return () => {
unregisterShortcut(DEFAULT_SHORTCUT_CATEGORIES.NAVIGATION, 'next-item');
unregisterShortcut(DEFAULT_SHORTCUT_CATEGORIES.EDITING, 'delete-item');
unregisterShortcut(DEFAULT_SHORTCUT_CATEGORIES.TOOLS, 'toggle-panel');
};
}, []);

return

My Component
;
}
```

## Best Practices

1. **Always clean up**: Use the return function in useEffect to unregister shortcuts
2. **Use meaningful names**: Give shortcuts descriptive names and descriptions
3. **Organize by category**: Use appropriate categories for different types of actions
4. **Check for conflicts**: Be aware that multiple shortcuts with the same key combination may conflict
5. **Consider order**: Use the order parameter to control display order in the shortcuts panel
6. **Position ShortcutsDisplay**: The ShortcutsDisplay component is not positioned by default - you control where it appears
7. **Cross-platform compatibility**: Use "Ctrl" in key combinations - it automatically works as "Cmd" on macOS

## TypeScript Support

The library is fully typed with TypeScript. All functions and components include proper type definitions:

```tsx
import type {
ShortcutEntry,
ShortcutCategory,
KeyCombination
} from '@jalez/react-shortcuts-provider';
```

## Development

This project uses:

- **React** with TypeScript
- **Vite** for build tooling
- **Tailwind CSS** for styling
- **Zustand** for state management
- **Vitest** for testing
- **ESLint** for linting

### Available Scripts

```bash
# Development
npm run dev # Start development server
npm run build # Build the library
npm run preview # Preview the build

# Testing
npm run test # Run tests in watch mode
npm run test:run # Run tests once
npm run test:ui # Run tests with UI
npm run test:coverage # Run tests with coverage

# Linting
npm run lint # Run ESLint
```

### Project Structure

```
src/
├── ShortCuts/
│ ├── components/ # React components
│ │ └── ShortcutsDisplay.tsx
│ │
│ ├── context/ # React context and hooks
│ │ ├── ShortcutsContext.tsx
│ │ ├── ShortcutsContextDef.ts
│ │ └── useShortcuts.ts
│ │
│ ├── registry/ # Core registry system
│ │ └── shortcutsRegistry.ts
│ │
│ ├── index.tsx # Component exports
│ └── shortcuts-exports.ts # Function and type exports
└── index.ts # Main library entry point
```

## Contributing

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## Sponsorship

If you find this library helpful, please consider sponsoring me on GitHub! Your support helps me maintain and improve this project.

[![Sponsor](https://img.shields.io/badge/Sponsor-%E2%9D%A4-red.svg)](https://github.com/sponsors/jalez)

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.