Skip to content

Commit 6947275

Browse files
committed
Creates a wrapper provider to block shortcuts while kapa modal is open (has bugs)
1 parent a58e9fc commit 6947275

File tree

5 files changed

+59
-6
lines changed

5 files changed

+59
-6
lines changed

apps/webapp/app/components/navigation/HelpAndFeedbackPopover.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import {
22
ArrowUpRightIcon,
33
BookOpenIcon,
44
CalendarDaysIcon,
5-
ChatBubbleLeftEllipsisIcon,
65
EnvelopeIcon,
76
LightBulbIcon,
87
QuestionMarkCircleIcon,
@@ -13,6 +12,7 @@ import { DiscordIcon, SlackIcon } from "@trigger.dev/companyicons";
1312
import { Fragment, useState } from "react";
1413
import { useCurrentPlan } from "~/routes/_app.orgs.$organizationSlug/route";
1514
import { Feedback } from "../Feedback";
15+
import { Shortcuts } from "../Shortcuts";
1616
import { StepContentContainer } from "../StepContentContainer";
1717
import { Button } from "../primitives/Buttons";
1818
import { ClipboardField } from "../primitives/ClipboardField";
@@ -22,7 +22,6 @@ import { Paragraph } from "../primitives/Paragraph";
2222
import { Popover, PopoverContent, PopoverSideMenuTrigger } from "../primitives/Popover";
2323
import { StepNumber } from "../primitives/StepNumber";
2424
import { MenuCount, SideMenuItem } from "./SideMenuItem";
25-
import { Shortcuts } from "../Shortcuts";
2625

2726
export function HelpAndFeedback({ disableShortcut = false }: { disableShortcut?: boolean }) {
2827
const [isHelpMenuOpen, setHelpMenuOpen] = useState(false);

apps/webapp/app/components/navigation/SideMenu.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ import { AISparkleIcon } from "~/assets/icons/AISparkleIcon";
8181
import { ShortcutKey } from "../primitives/ShortcutKey";
8282
import { useFeatures } from "~/hooks/useFeatures";
8383
import { useKapa } from "~/root";
84+
import { useShortcuts } from "~/components/primitives/ShortcutsProvider";
8485

8586
type SideMenuUser = Pick<User, "email" | "admin"> & { isImpersonating: boolean };
8687
export type SideMenuProject = Pick<
@@ -550,6 +551,7 @@ function HelpAndAI() {
550551
const [isKapaOpen, setIsKapaOpen] = useState(false);
551552
const features = useFeatures();
552553
const kapa = useKapa();
554+
const { disableShortcuts, enableShortcuts } = useShortcuts();
553555

554556
useEffect(() => {
555557
if (!features.isManagedCloud || !kapa?.websiteId) return;
@@ -559,13 +561,19 @@ function HelpAndAI() {
559561
// Define the handler function
560562
const handleModalClose = () => {
561563
setIsKapaOpen(false);
564+
enableShortcuts();
562565
};
563566

564567
const kapaInterval = setInterval(() => {
565568
if (typeof window.Kapa === "function") {
566569
clearInterval(kapaInterval);
567570
window.Kapa("render");
568571
window.Kapa("onModalClose", handleModalClose);
572+
// Register onModalOpen handler
573+
window.Kapa("onModalOpen", () => {
574+
setIsKapaOpen(true);
575+
disableShortcuts();
576+
});
569577
}
570578
}, 100);
571579

@@ -576,7 +584,7 @@ function HelpAndAI() {
576584
window.Kapa("unmount");
577585
}
578586
};
579-
}, [features.isManagedCloud, kapa?.websiteId]);
587+
}, [features.isManagedCloud, kapa?.websiteId, disableShortcuts, enableShortcuts]);
580588

581589
return (
582590
<>
@@ -595,6 +603,7 @@ function HelpAndAI() {
595603
if (typeof window.Kapa === "function") {
596604
window.Kapa("open");
597605
setIsKapaOpen(true);
606+
disableShortcuts();
598607
}
599608
}}
600609
>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { createContext, useContext, useState, type ReactNode } from "react";
2+
3+
type ShortcutsContextType = {
4+
areShortcutsEnabled: boolean;
5+
disableShortcuts: () => void;
6+
enableShortcuts: () => void;
7+
};
8+
9+
const ShortcutsContext = createContext<ShortcutsContextType | null>(null);
10+
11+
type ShortcutsProviderProps = {
12+
children: ReactNode;
13+
};
14+
15+
export function ShortcutsProvider({ children }: ShortcutsProviderProps) {
16+
const [areShortcutsEnabled, setAreShortcutsEnabled] = useState(true);
17+
18+
const disableShortcuts = () => setAreShortcutsEnabled(false);
19+
const enableShortcuts = () => setAreShortcutsEnabled(true);
20+
21+
return (
22+
<ShortcutsContext.Provider
23+
value={{
24+
areShortcutsEnabled,
25+
disableShortcuts,
26+
enableShortcuts,
27+
}}
28+
>
29+
{children}
30+
</ShortcutsContext.Provider>
31+
);
32+
}
33+
34+
const throwIfNoProvider = () => {
35+
throw new Error("useShortcuts must be used within a ShortcutsProvider");
36+
};
37+
38+
export const useShortcuts = () => {
39+
return useContext(ShortcutsContext) ?? throwIfNoProvider();
40+
};

apps/webapp/app/hooks/useShortcutKeys.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useHotkeys } from "react-hotkeys-hook";
22
import { useOperatingSystem } from "~/components/primitives/OperatingSystemProvider";
3+
import { useShortcuts } from "~/components/primitives/ShortcutsProvider";
34

45
export type Modifier = "alt" | "ctrl" | "meta" | "shift" | "mod";
56

@@ -30,6 +31,7 @@ export function useShortcutKeys({
3031
enabledOnInputElements,
3132
}: useShortcutKeysProps) {
3233
const { platform } = useOperatingSystem();
34+
const { areShortcutsEnabled } = useShortcuts();
3335
const isMac = platform === "mac";
3436
const relevantShortcut =
3537
shortcut && "mac" in shortcut ? (isMac ? shortcut.mac : shortcut.windows) : shortcut;
@@ -41,7 +43,7 @@ export function useShortcutKeys({
4143
action(event);
4244
},
4345
{
44-
enabled: !disabled,
46+
enabled: !disabled && areShortcutsEnabled,
4547
enableOnFormTags: enabledOnInputElements ?? relevantShortcut?.enabledOnInputElements,
4648
enableOnContentEditable: enabledOnInputElements ?? relevantShortcut?.enabledOnInputElements,
4749
}

apps/webapp/app/root.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { appEnvTitleTag } from "./utils";
2525
import { type Handle } from "./utils/handle";
2626
import { useEffect } from "react";
2727
import { useTypedMatchesData } from "./hooks/useTypedMatchData";
28+
import { ShortcutsProvider } from "./components/primitives/ShortcutsProvider";
2829

2930
declare global {
3031
interface Window {
@@ -129,8 +130,10 @@ export default function App() {
129130
<Links />
130131
</head>
131132
<body className="bg-darkBackground h-full overflow-hidden">
132-
<Outlet />
133-
<Toast />
133+
<ShortcutsProvider>
134+
<Outlet />
135+
<Toast />
136+
</ShortcutsProvider>
134137
<ScrollRestoration />
135138
<ExternalScripts />
136139
<Scripts />

0 commit comments

Comments
 (0)