import { TooltipContentProps } from '@ui/components/shadcn/ui/tooltip'
import type { ReactNode } from 'react'
import { ShortcutTooltip } from './ShortcutTooltip'
import type { ShortcutId } from '@/state/shortcuts/registry'
import type { ShortcutOptions } from '@/state/shortcuts/types'
import { useShortcut } from '@/state/shortcuts/useShortcut'
interface ShortcutProps {
/** Registered shortcut id — drives both the hotkey binding and the tooltip. */
id: ShortcutId
/** Fires on the hotkey. Usually the same handler wired to the child's `onClick`. */
onTrigger: () => void
/** Element to bind the shortcut to and wrap in the tooltip. */
children: ReactNode
/** Per-mount overrides for the shortcut — see `ShortcutOptions`. */
options?: ShortcutOptions
side?: TooltipContentProps['side']
align?: TooltipContentProps['align']
sideOffset?: number
delayDuration?: number
/**
* Override the label from the registry. Use when the wrapped element's
* action is a narrower/contextual variant of the registered shortcut.
*/
label?: string
/**
* Controlled open state for the tooltip. Pass `false` to force the tooltip
* closed (e.g. while a popover or dialog opened by the wrapped element is
* visible). Leave `undefined` for default uncontrolled behavior.
*/
tooltipOpen?: boolean
}
/**
* Bind a registered shortcut to an element AND show its keybind on hover,
* Linear-style. Single source of truth: one `id` drives both the hotkey
* listener and the tooltip, so they can't drift.
*
* The wrapped child stays fully interactive — Radix `asChild` passes clicks,
* focus, and refs through untouched.
*
* @example
*
*
*
*
* @example
* // Gate the hotkey on local state; tooltip still renders:
*
*
*
*/
export const Shortcut = ({
id,
onTrigger,
children,
options,
side,
align,
sideOffset,
delayDuration,
label,
tooltipOpen,
}: ShortcutProps) => {
useShortcut(id, onTrigger, label !== undefined ? { ...options, label } : options)
return (
{children}
)
}