From dc760dd843e02dcaee50cee083fb2eadbf56f61a Mon Sep 17 00:00:00 2001 From: water <672684719@qq.com> Date: Thu, 6 Aug 2026 23:37:17 +0800 Subject: [PATCH] feat: add keyboard shortcut hint chip on ShareSheet (Closes #824) --- app/components/ShareSheet.tsx | 94 ++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 19 deletions(-) diff --git a/app/components/ShareSheet.tsx b/app/components/ShareSheet.tsx index 70eef07..3288ced 100644 --- a/app/components/ShareSheet.tsx +++ b/app/components/ShareSheet.tsx @@ -94,6 +94,41 @@ const SOCIAL_PLATFORMS: SharePlatform[] = [ }, ] +/** + * Detect whether the user is on macOS (for ⌘ vs Ctrl display). + */ +const isMac = + typeof navigator !== "undefined" && navigator.platform?.toLowerCase().includes("mac") + +/** + * Small keyboard shortcut chip used to hint at available keyboard actions. + * Renders as a compact kbd-style badge with the modifier key label. + */ +function KbdChip({ + keys, + className, +}: { + /** Array of key labels, e.g. ["⌘", "C"] or ["Esc"] */ + keys: string[] + className?: string +}) { + return ( + + ) +} + export function ShareSheet({ title, text, @@ -117,21 +152,6 @@ export function ShareSheet({ } }, []) - // Load QR code when sheet opens (desktop fallback) - React.useEffect(() => { - if (open && !hasNativeShare && generateQrCode && !qrCode && !isLoadingQr) { - setIsLoadingQr(true) - Promise.resolve(generateQrCode(url)) - .then((data) => { - setQrCode(data) - setIsLoadingQr(false) - }) - .catch(() => { - setIsLoadingQr(false) - }) - } - }, [open, generateQrCode, url, qrCode, isLoadingQr]) - const handleNativeShare = React.useCallback(async () => { if (typeof navigator !== "undefined" && navigator.share) { try { @@ -193,6 +213,26 @@ export function ShareSheet({ } }, [url, toast]) + // Register global keyboard shortcut for Copy Link (⌘C / Ctrl+C) when the + // sheet is open. This makes the footer hint chip functional, not decorative. + React.useEffect(() => { + function handleKeyDown(e: KeyboardEvent) { + if (!open) return + const mod = isMac ? e.metaKey : e.ctrlKey + if (mod && (e.key === "c" || e.key === "C")) { + // Don't intercept if the user is focused on an input/textarea + const tag = (e.target as HTMLElement)?.tagName?.toLowerCase() + if (tag === "input" || tag === "textarea" || (e.target as HTMLElement)?.isContentEditable) { + return + } + e.preventDefault() + handleCopyLink() + } + } + window.addEventListener("keydown", handleKeyDown) + return () => window.removeEventListener("keydown", handleKeyDown) + }, [open, handleCopyLink]) + const handlePlatformShare = React.useCallback( (platform: SharePlatform) => { try { @@ -217,6 +257,8 @@ export function ShareSheet({ const isDesktop = typeof window !== "undefined" && window.innerWidth >= 768 + const modKey = isMac ? "⌘" : "Ctrl" + return ( @@ -374,11 +416,25 @@ export function ShareSheet({ })} -

- Share via your preferred platform or copy the direct link. -

+ {/* Keyboard shortcut hints */} +
+ + + Copy link + + {hasNativeShare && ( + + + Native share + + )} + + + Close + +
) -} +} \ No newline at end of file