useHotkeys

ثبت میان‌برهای صفحه‌کلید با پشتیبانی cross-platform از کلید mod (Cmd/Ctrl) و مدیریت scope

معرفی

هوک useHotkeys یک میان‌بر صفحه‌کلید را ثبت می‌کند و هنگام unmount به‌صورت خودکار حذفش می‌کند. گرامر combo از mod پشتیبانی می‌کند (روی macOS تبدیل به ⌘ و در سایر سیستم‌ها Ctrl می‌شود)، و به‌صورت هوشمند وقتی کاربر در حال تایپ در input است، میان‌برهای بدون modifier را نادیده می‌گیرد.

چه زمانی استفاده کنیم

  • ثبت میان‌برهای سراسری در کامپوننت قاب برنامه، همان‌جا که ProductFrame رندر می‌شود (مثلاً Ctrl+K برای CommandPalette)
  • میان‌برهای محلی برای عملیات صفحه (مثل Escape برای بستن پنل، / برای focus در جستجو)
  • میان‌بر وظایف مشخص: Mod+S برای ذخیره، Mod+Shift+P برای پالت فرمان‌ها

چه زمانی استفاده نکنیم

  • برای event های فرم یا primitive های Radix که خودشان keyboard handling دارند
  • برای استفاده‌ی همزمان با Inputها بدون modifier — به‌صورت پیش‌فرض رد می‌شود (برای تجربه‌ی تایپ)

استفاده

پایه

import { useHotkeys } from '@partodata/ui'

// app/frame.tsx — کنار ProductFrame، یک بار برای کل برنامه
function GlobalShortcuts() {
  const [paletteOpen, setPaletteOpen] = React.useState(false)

  useHotkeys('mod+k', () => setPaletteOpen((v) => !v))

  return <CommandPalette open={paletteOpen} onOpenChange={setPaletteOpen} items={items} />
}

چند combo هم‌زمان

// Escape یا Mod+W هر دو پنل را می‌بندند
useHotkeys(['escape', 'mod+w'], close, { enabled: open })

محدود به شرط

با enabled می‌توانید میان‌بر را فقط در برخی شرایط زنده نگه دارید:

useHotkeys('enter', submitForm, { enabled: isFormValid })

هدف اختصاصی (ref)

const panelRef = React.useRef<HTMLDivElement>(null)
useHotkeys('escape', closePanel, { target: panelRef })
// فقط وقتی focus داخل panelRef باشد فعال است (چون keydown bubble می‌شود)

گرامر combo

<part>[+<part>]*
بخشتوضیح
mod⌘ روی macOS، Ctrl در بقیه — پیشنهاد رسمی
ctrlCtrl صریح (بدون fallback روی Mac)
cmd⌘ (روی Mac) / Win (در بقیه)
shiftShift
altAlt / Option
metaMeta (تقریباً معادل cmd)
کلیدk، enter، escape، space، فلش‌ها، ...
علامت/ یا slash، . یا period، , یا comma، ;، '، [، ]، \، -، =، `
علامت با Shift? (همان shift+slash)، <، >، :، "، {، }، |، _، ~

مثال‌ها:

  • 'mod+k' — ⌘K روی macOS، Ctrl+K در بقیه
  • 'mod+shift+p' — میان‌بر سه‌کلیده
  • 'escape' — فقط Escape
  • 'ctrl+k' — Ctrl صریح (روی Mac ⌘ کار نمی‌کند)

پارامترها

combo: HotkeyCombo

یک رشته یا آرایه‌ای از رشته‌ها. آرایه به‌صورت OR تفسیر می‌شود.

handler: (event: KeyboardEvent) => void

callback که با تطابق فراخوانی می‌شود. event.preventDefault() پیش‌فرض اعمال می‌شود.

options?: UseHotkeysOptions

پراپنوعپیش‌فرضتوضیح
preventDefaultbooleantrueفراخوانی event.preventDefault() هنگام تطابق
ignoreWhenTypingbooleantrueنادیده گرفتن combo هنگام focus در input/textarea بدون modifier
enabledbooleantrueفعال/غیرفعال کردن listener
targetRefObject<HTMLElement> | HTMLElement | Documentdocumentهدف listener. ref برای scope کردن میان‌بر به یک ناحیه‌ی خاص

صفحه‌کلید فارسی و چیدمان‌های غیرلاتین

میان‌بر حرفی، رقمی یا علامتی روی هر چیدمان کار می‌کند: useHotkeys('k', …)، useHotkeys('/', …) و useHotkeys('?', …) را همان‌طور که می‌نویسید بگذارید.

روی چیدمان فارسی (ISIRI 9147) کلید K حرف «ن»، کلید J حرف «ت» و کلید X حرف «ط» می‌دهد و Shift و / علامت «؟» را. مقایسهٔ event.key === 'k' هرگز برای کاربر فارسی اجرا نمی‌شود. useHotkeys دو کار می‌کند:

  1. اول کلیدی را که چیدمان چاپ کرده با ترکیب مقایسه می‌کند (event.key)؛ پس خواننده‌ای که چیدمان لاتین دیگری دارد (Dvorak، AZERTY، آلمانی) همان حرفی را می‌گیرد که روی کلید نوشته است.
  2. اگر چیدمان برای یک حرف یا رقم، حرف و رقم لاتین چاپ نکرده باشد (مثلاً «ن» به‌جای K، یا رقم فارسی به‌جای رقم لاتین)، کلید فیزیکی (event.code: KeyK، Digit1) تصمیم می‌گیرد. علامت (Slash، Comma، …) فقط وقتی با کلید فیزیکی تطبیق می‌خورد که چیدمان نویسهٔ غیر ASCII چاپ کرده باشد؛ چیدمان آلمانی که روی کلید / فیزیکی علامت - می‌دهد، / را اجرا نمی‌کند.

یکی از میان‌برها را روی صفحه‌کلید بزنید، یا یکی از نمونه‌های چیدمان فارسی را بفرستید. چیدمان فارسی روی کلید K حرف «ن» می‌دهد؛ میان‌بر باز هم کار می‌کند.

event.key
—
event.code
—
  • Kهنوز اجرا نشده
  • /هنوز اجرا نشده
  • ?هنوز اجرا نشده
  • Ctrl+Bهنوز اجرا نشده

قاعده: میان‌بر حرفی با useHotkeys نوشته می‌شود، نه e.key === 'k' در keydown دستی (قاعدهٔ lint parto/no-handmade-key-shortcut). اگر رویداد خام لازم است، event.code را مقایسه کنید ('KeyJ'، 'Slash')، مثل EntityDrawer برای J و K. کلیدهای نام‌دار (Enter، Escape، فلش‌ها و فاصله) روی همهٔ چیدمان‌ها یکی‌اند و با event.key درست‌اند.

میان‌بر تازه را قبل از «تمام» روی چیدمان فارسی امتحان کنید (Alt+Shift چیدمان را عوض می‌کند).


ابزار کمکی: formatHotkey

برای نمایش combo در UI، از formatHotkey استفاده کنید — روی macOS سمبل‌های ⌘⇧⌥ تولید می‌کند، در ویندوز/لینوکس متن Ctrl+Shift+Alt.

import { formatHotkey } from '@partodata/ui'

formatHotkey('mod+shift+p') // '⌘⇧P' (Mac) یا 'Ctrl+Shift+P' (بقیه)

راهنمای استفاده

  • میان‌بر سراسری را در یک نقطه متمرکز (کامپوننت قاب برنامه، کنار ProductFrame) ثبت کنید — نه درون کامپوننت‌های صفحه که ممکن است چند بار mount/unmount شوند
  • وقتی Input دارید و می‌خواهید Enter را کنترل کنید، از onKeyDown خود input استفاده کنید، نه useHotkeys — چون ignoreWhenTyping فعال است
  • برای نمایش میان‌بر در UI از formatHotkey استفاده کنید، نه حرف تایپ‌شده؛ formatHotkey('slash') همان / را می‌دهد
  • برای میان‌برهای متضاد بین صفحات (مثلاً / در یک صفحه focus می‌کند و در صفحه‌ی دیگر کنشی دیگر انجام می‌دهد)، از enabled برای context-scoping استفاده کنید

هوک‌ها و کامپوننت‌های مرتبط

  • CommandPalette — کامپوننت پالت که داخلاً از useHotkeys('mod+k') استفاده می‌کند