Skip to content

feat: keyboard shortcuts switcher in Settings#1684

Open
alex-key wants to merge 6 commits intonpmx-dev:mainfrom
alex-key:feat/kbd-shortcuts-switcher
Open

feat: keyboard shortcuts switcher in Settings#1684
alex-key wants to merge 6 commits intonpmx-dev:mainfrom
alex-key:feat/kbd-shortcuts-switcher

Conversation

@alex-key
Copy link
Contributor

🔗 Linked issue

Resolves #1537

🧭 Context

In order to meet a11y requirements we should allow to disable custom keyboard shortcuts, which might conflict with other browser/OS shortcuts.

From Issue:

If we want to keep shortcuts, the easiest way to meet this requirement is to add a mechanism to turn them off. This should also hide the keyboard hints on the page.

  • Add a setting to disable keyboard shortcuts to the settings page.
  • Add a note to the keyboard shortcuts modals that links directly to the setting.
  • Conditionally render the keyboard hints based on the setting.

📚 Description

Basically checklist above describes changes. Added e2e to check for correct behavior on disabled shortcuts (last screenshot below).

Also see ss below for reference.

@knowler Since <kbd> rendering became <ClientOnly> it might cause layout shift (buttons in header). Please comment if this is an issue.

image image image

disable-kbd-shrtct-header-shift

@vercel
Copy link

vercel bot commented Feb 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
npmx.dev Ready Ready Preview, Comment Feb 27, 2026 7:19am
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs.npmx.dev Ignored Ignored Preview Feb 27, 2026 7:19am
npmx-lunaria Ignored Ignored Feb 27, 2026 7:19am

Request Review

@alex-key alex-key changed the title Feat/kbd shortcuts switcher Keyboard shortcuts switcher in Settings Feb 27, 2026
@github-actions
Copy link

github-actions bot commented Feb 27, 2026

Lunaria Status Overview

🌕 This pull request will trigger status changes.

Learn more

By default, every PR changing files present in the Lunaria configuration's files property will be considered and trigger status changes accordingly.

You can change this by adding one of the keywords present in the ignoreKeywords property in your Lunaria configuration file in the PR's title (ignoring all files) or by including a tracker directive in the merged commit's description.

Tracked Files

File Note
lunaria/files/en-GB.json Localization changed, will be marked as complete.
lunaria/files/en-US.json Source changed, localizations will be marked as outdated.
Warnings reference
Icon Description
🔄️ The source for this localization has been updated since the creation of this pull request, make sure all changes in the source have been applied.

@alex-key alex-key changed the title Keyboard shortcuts switcher in Settings feat: Keyboard shortcuts switcher in Settings Feb 27, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

📝 Walkthrough

Walkthrough

This PR adds a keyboardShortcuts setting and a new useKeyboardShortcuts() composable (default true), wires that state into multiple components, and gates existing single-key handlers behind it. Global and component-level key handlers (app.vue, AppHeader, package page, PackageSelector, etc.) now early-return when keyboardShortcuts is disabled. Keyboard hint UI and aria-keyshortcuts are rendered client-side and only when shortcuts are enabled. The settings page gains a toggle for keyboard shortcuts, translation/schema entries were added, and tests were updated to cover enabled/disabled behaviours.

Possibly related PRs

Suggested reviewers

  • danielroe
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The pull request description clearly relates to the changeset by explaining the implementation of keyboard shortcuts disabling feature, including context, objectives, and the specific changes made.
Linked Issues check ✅ Passed All coding requirements from issue #1537 are met: a settings toggle to disable keyboard shortcuts is added, a note in the keyboard shortcuts modal links to the setting, and keyboard hints are conditionally rendered based on the setting.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the objectives of disabling keyboard shortcuts and hiding hints. No out-of-scope modifications detected in the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
app/components/Link/Base.vue (1)

117-125: Consider reserving shortcut badge space to reduce hydration shift.

<ClientOnly> removes the <kbd> during SSR and inserts it on hydration, which can nudge neighbouring header controls. A fixed-size placeholder when ariaKeyshortcuts exists would keep layout stable.

app/components/Button/Base.vue (1)

30-30: Consider extracting the composable call to the top level of setup.

Invoking useKeyboardShortcuts() inside a computed getter is unconventional. Composables are typically called at the top level of <script setup> to ensure proper reactive context and lifecycle handling.

The current implementation works because import.meta.client guards the call on the server, but for clarity and adherence to Vue conventions, consider:

♻️ Suggested refactor
+const keyboardShortcuts = import.meta.client ? useKeyboardShortcuts() : shallowRef(false)
+const keyboardShortcutsEnabled = computed(() => keyboardShortcuts.value)
-const keyboardShortcutsEnabled = computed(() => import.meta.client && useKeyboardShortcuts().value)
test/e2e/interactions.spec.ts (1)

264-273: Consider adding a test for the 'c' shortcut when disabled.

For completeness, you might want to add a test verifying that the 'c' shortcut (compare) also does not navigate when shortcuts are disabled. This would mirror the enabled test at lines 155-165.

🧪 Optional test to add
test('"c" (package) does not navigate to compare when shortcuts are disabled', async ({
  page,
  goto,
}) => {
  await goto('/package/vue', { waitUntil: 'hydration' })

  await page.keyboard.press('c')

  await expect(page).toHaveURL(/\/package\/vue$/)
})

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ed4254 and 8506dd2.

📒 Files selected for processing (15)
  • app/app.vue
  • app/components/AppFooter.vue
  • app/components/AppHeader.vue
  • app/components/Button/Base.vue
  • app/components/Compare/PackageSelector.vue
  • app/components/Link/Base.vue
  • app/composables/useSettings.ts
  • app/pages/package/[[org]]/[name].vue
  • app/pages/settings.vue
  • i18n/locales/en.json
  • i18n/schema.json
  • lunaria/files/en-GB.json
  • lunaria/files/en-US.json
  • test/e2e/interactions.spec.ts
  • test/nuxt/composables/use-settings.spec.ts

@alex-key alex-key changed the title feat: Keyboard shortcuts switcher in Settings feat: keyboard shortcuts switcher in Settings Feb 27, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
app/components/Link/Base.vue (1)

118-126: Consider reserving space for the client-only <kbd> hint to reduce layout shift.

Because the key hint only appears after hydration, link/button content can shift horizontally. A small fallback placeholder in ClientOnly would minimise CLS in headers and dense layouts.

♻️ Suggested tweak
-    <ClientOnly>
+    <ClientOnly>
       <kbd
         v-if="keyboardShortcutsEnabled && ariaKeyshortcuts"
         class="ms-2 inline-flex items-center justify-center size-4 text-xs text-fg bg-bg-muted border border-border rounded no-underline"
         aria-hidden="true"
       >
         {{ ariaKeyshortcuts }}
       </kbd>
+      <template `#fallback`>
+        <span
+          v-if="ariaKeyshortcuts"
+          class="ms-2 inline-block size-4"
+          aria-hidden="true"
+        />
+      </template>
     </ClientOnly>

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8506dd2 and 89c89bc.

📒 Files selected for processing (8)
  • app/components/AppFooter.vue
  • app/components/Compare/PackageSelector.vue
  • app/components/Link/Base.vue
  • i18n/locales/en.json
  • i18n/schema.json
  • lunaria/files/en-GB.json
  • lunaria/files/en-US.json
  • test/nuxt/composables/use-settings.spec.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • i18n/locales/en.json
  • test/nuxt/composables/use-settings.spec.ts
  • app/components/Compare/PackageSelector.vue
  • i18n/schema.json
  • app/components/AppFooter.vue

@codecov
Copy link

codecov bot commented Feb 27, 2026

Codecov Report

❌ Patch coverage is 85.00000% with 3 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
app/app.vue 0.00% 2 Missing ⚠️
app/pages/package/[[org]]/[name].vue 0.00% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 89c89bc and 77bcb72.

📒 Files selected for processing (2)
  • app/components/AppFooter.vue
  • test/nuxt/composables/use-settings.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/nuxt/composables/use-settings.spec.ts

<i18n-t keypath="shortcuts.disable_shortcuts" tag="span" scope="global">
<template #settings>
<NuxtLink
:to="{ name: 'settings' }"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Link should target the keyboard-shortcuts section directly.

Line 103 currently routes to the settings page root only. To meet the “direct to setting” objective, point this link to the keyboard shortcuts section anchor instead of the page top.

Suggested change
-                    :to="{ name: 'settings' }"
+                    :to="{ name: 'settings', hash: '#keyboard-shortcuts' }"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:to="{ name: 'settings' }"
:to="{ name: 'settings', hash: '#keyboard-shortcuts' }"

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.

Add mechanism to turn off keyboard shortcuts (WCAG Level A requirement)

1 participant