Skip to content

fix(react): make disabled a registration gate and warn on duplicate s… - #9

Merged
prassamin merged 1 commit into
mainfrom
release/v2.0.2
Sep 15, 2026
Merged

prassamin merged 1 commit into
mainfrom
release/v2.0.2

Conversation

@prassamin

Copy link
Copy Markdown
Contributor

…hortcuts

Copilot AI lite review requested due to automatic review settings September 15, 2026 09:41
@prassamin
prassamin merged commit 7bd125e into main Sep 15, 2026
2 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Multiple moderate issues remain in duplicate detection, warning behavior, lifecycle cleanup, hook tracking, and the sample gate.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This PR gates React shortcut registration when disabled and adds duplicate-binding warnings across React and core.

Changes:

  • Disabled hooks skip registration and scope management.
  • Added duplicate-registration tracking and warnings.
  • Updated tests, documentation, examples, changelogs, and package versions.
File summaries
File Summary
tests/sample-react/src/App.jsx Demonstrates duplicate-instance behavior.
packages/react/src/useShortcuts.ts Implements disabled gating and duplicate tracking.
packages/react/src/Keybindy.test.tsx Updates registration tests.
packages/react/src/disabled-gating.test.tsx Adds gating and warning coverage.
packages/react/README.md Documents registration gating.
packages/react/package.json Bumps the React package version.
packages/react/CHANGELOG.md Records React changes.
packages/core/src/ShortcutManager.ts Adds core duplicate warnings.
packages/core/src/ShortcutManager.test.ts Tests duplicate registration behavior.
packages/core/package.json Bumps the core package version.
packages/core/CHANGELOG.md Records core changes.
Review details

Suppressed comments (4)

packages/core/src/ShortcutManager.ts:544

  • This warning is inside the alias-expansion loop, so one logical duplicate such as Enter (which expands to Enter and Numpad Enter) emits multiple console warnings. Deduplicate at the logical registration level or emit once after collecting the replaced combinations.
          console.warn(

packages/core/src/ShortcutManager.ts:541

  • warnedDuplicates is only cleared in destroy(), while unregister() removes the shortcut without clearing this signature. After a duplicate is unmounted, a later registration of the same scope/key pair will overwrite again but never warn, so the warning does not re-arm with the active registrations; clear or recompute this state when no matching binding remains.
        const duplicateSignature = `${targetScope}::${JSON.stringify(normalized)}`;
        if (
          replaced.length > 0 &&
          !this.warnedDuplicates.has(duplicateSignature) &&
          !isProductionBuild

packages/react/README.md:172

  • This example calls onSelect below, but onSelect is not destructured from the component props, so the copied snippet fails to type-check (and is undefined at runtime). Include it in the parameter list.
function MediaPicker({ isOpen, onClose }) {

packages/react/src/useShortcuts.ts:43

  • This hook-level diagnostic runs immediately before manager.register, whose new core duplicate diagnostic also calls console.warn. A duplicate useShortcuts registration therefore emits both messages (and alias expansions can emit more), contradicting the sample's “one” warning; keep the diagnostic in one layer or coordinate suppression.
  if (count > 1 && !duplicateWarnings.has(signature) && !isProductionBuild) {
    duplicateWarnings.add(signature);
    console.warn(
      `[Keybindy] Duplicate shortcut detected: ${JSON.stringify(keys)} is registered by ${count} component instances in scope "${scope}". Only the most recent instance will fire. ` +
        `If these are parallel instances of the same component (dialogs, pickers), pass { disabled: !isOpen } so only the active instance registers.`
  • Files reviewed: 11/11 changed files
  • Comments generated: 5
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +25 to +29
const isProductionBuild = (() => {
try {
return process.env.NODE_ENV === 'production';
} catch {
return false;
Comment on lines +532 to +535
JSON.stringify(s.keys) === JSON.stringify(normalized) &&
(s.options?.scope || 'global') === targetScope &&
s.id !== id
);
Comment on lines +19 to +23
const isProductionBuild = (() => {
try {
return process.env.NODE_ENV === 'production';
} catch {
return false;
);
}

const stopTracking = stableShortcuts.map(({ keys }) => trackDuplicate(scope, keys));
},
],
{
// disabled: !isOpen,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants