ShortcutBadge.tsx45 lines · main
1import { Fragment } from 'react'
2import { cn, KeyboardShortcut } from 'ui'
3
4import { hotkeyToKeys } from '@/state/shortcuts/formatShortcut'
5import { SHORTCUT_DEFINITIONS, type ShortcutId } from '@/state/shortcuts/registry'
6
7interface ShortcutBadgeProps {
8 shortcutId: ShortcutId
9 className?: string
10 /** `'inline'` (default) is flat text; `'pill'` is a boxed badge. */
11 variant?: 'inline' | 'pill'
12}
13
14/**
15 * Inline display of the keybind for a registered shortcut. Useful inside
16 * menu items, buttons, or rows where the label already exists elsewhere and
17 * you just want to surface the keybind itself (no tooltip / hover).
18 *
19 * For multi-step sequences (e.g. `['G', 'T']`), each step is separated by the
20 * word "then".
21 *
22 * @example
23 * <DropdownMenuItem>
24 * <p>Copy as CSV</p>
25 * <ShortcutBadge shortcutId={SHORTCUT_IDS.RESULTS_COPY_CSV} className="ml-auto" />
26 * </DropdownMenuItem>
27 */
28export const ShortcutBadge = ({
29 shortcutId,
30 className,
31 variant = 'inline',
32}: ShortcutBadgeProps) => {
33 const def = SHORTCUT_DEFINITIONS[shortcutId]
34
35 return (
36 <span className={cn('flex items-center gap-1', className)}>
37 {def.sequence.map((step, i) => (
38 <Fragment key={i}>
39 {i > 0 && <span className="text-foreground-lighter text-[11px]">then</span>}
40 <KeyboardShortcut keys={hotkeyToKeys(step)} variant={variant} />
41 </Fragment>
42 ))}
43 </span>
44 )
45}