Skip to content

Commit 998a4dd

Browse files
make syntax reference guide keyboard shortcut hint clickable (#229)
1 parent bf76cb9 commit 998a4dd

File tree

6 files changed

+75
-19
lines changed

6 files changed

+75
-19
lines changed

packages/web/src/app/components/searchBar/searchSuggestionsBox.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { VscFile, VscFilter, VscRepo, VscSymbolMisc } from "react-icons/vsc";
1717
import { Skeleton } from "@/components/ui/skeleton";
1818
import { Separator } from "@/components/ui/separator";
1919
import { KeyboardShortcutHint } from "../keyboardShortcutHint";
20+
import { useSyntaxGuide } from "@/app/syntaxGuideProvider";
2021

2122
export type Suggestion = {
2223
value: string;
@@ -79,6 +80,7 @@ const SearchSuggestionsBox = forwardRef(({
7980
searchHistorySuggestions,
8081
}: SearchSuggestionsBoxProps, ref: Ref<HTMLDivElement>) => {
8182
const [highlightedSuggestionIndex, setHighlightedSuggestionIndex] = useState(0);
83+
const { onOpenChanged } = useSyntaxGuide();
8284

8385
const { suggestions, isHighlightEnabled, descriptionPlacement, DefaultIcon, onSuggestionClicked } = useMemo(() => {
8486
if (!isEnabled) {
@@ -391,7 +393,10 @@ const SearchSuggestionsBox = forwardRef(({
391393
className="my-2"
392394
/>
393395
<div className="flex flex-row items-center justify-between mt-1">
394-
<div className="flex flex-row gap-1.5 items-center">
396+
<div
397+
className="flex flex-row gap-1.5 items-center cursor-pointer"
398+
onClick={() => onOpenChanged(true)}
399+
>
395400
<p className="text-muted-foreground text-sm">
396401
Syntax help:
397402
</p>

packages/web/src/app/components/syntaxReferenceGuide.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,31 @@ import {
1212
} from "@/components/ui/table";
1313
import clsx from "clsx";
1414
import Link from "next/link";
15-
import { useCallback, useRef, useState } from "react";
15+
import { useCallback, useRef } from "react";
1616
import { useHotkeys } from "react-hotkeys-hook";
17+
import { useSyntaxGuide } from "../syntaxGuideProvider";
1718

1819
const LINGUIST_LINK = "https://github.com/github-linguist/linguist/blob/main/lib/linguist/languages.yml";
1920
const CTAGS_LINK = "https://ctags.io/";
2021

2122
export const SyntaxReferenceGuide = () => {
22-
const [isOpen, setIsOpen] = useState(false);
23+
const { isOpen, onOpenChanged } = useSyntaxGuide();
2324
const previousFocusedElement = useRef<HTMLElement | null>(null);
2425

2526
const openDialog = useCallback(() => {
2627
previousFocusedElement.current = document.activeElement as HTMLElement;
27-
setIsOpen(true);
28-
}, []);
28+
onOpenChanged(true);
29+
}, [onOpenChanged]);
2930

3031
const closeDialog = useCallback(() => {
31-
setIsOpen(false);
32+
onOpenChanged(false);
3233

3334
// @note: Without requestAnimationFrame, focus was not being returned
3435
// to codemirror elements for some reason.
3536
requestAnimationFrame(() => {
3637
previousFocusedElement.current?.focus();
3738
});
38-
}, []);
39+
}, [onOpenChanged]);
3940

4041
const handleOpenChange = useCallback((isOpen: boolean) => {
4142
if (isOpen) {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'use client';
2+
3+
import { useSyntaxGuide } from "../syntaxGuideProvider";
4+
import { KeyboardShortcutHint } from "./keyboardShortcutHint";
5+
6+
export const SyntaxReferenceGuideHint = () => {
7+
const { isOpen, onOpenChanged } = useSyntaxGuide();
8+
9+
return (
10+
<div
11+
className="text-sm cursor-pointer"
12+
onClick={() => onOpenChanged(!isOpen)}
13+
>
14+
<span className="dark:text-gray-300">Reference guide: </span><KeyboardShortcutHint shortcut="⌘" /> <KeyboardShortcutHint shortcut="/" />
15+
</div>
16+
)
17+
}

packages/web/src/app/layout.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { PHProvider } from "./posthogProvider";
77
import { Toaster } from "@/components/ui/toaster";
88
import { TooltipProvider } from "@/components/ui/tooltip";
99
import { SyntaxReferenceGuide } from "./components/syntaxReferenceGuide";
10+
import { SyntaxGuideProvider } from "./syntaxGuideProvider";
1011

1112
export const metadata: Metadata = {
1213
title: "Sourcebot",
@@ -35,14 +36,16 @@ export default function RootLayout({
3536
>
3637
<QueryClientProvider>
3738
<TooltipProvider>
38-
{/*
39-
@todo : ideally we don't wrap everything in a suspense boundary.
40-
@see : https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
41-
*/}
42-
<Suspense>
43-
{children}
44-
</Suspense>
45-
<SyntaxReferenceGuide />
39+
<SyntaxGuideProvider>
40+
{/*
41+
@todo : ideally we don't wrap everything in a suspense boundary.
42+
@see : https://nextjs.org/docs/messages/missing-suspense-with-csr-bailout
43+
*/}
44+
<Suspense>
45+
{children}
46+
</Suspense>
47+
<SyntaxReferenceGuide />
48+
</SyntaxGuideProvider>
4649
</TooltipProvider>
4750
</QueryClientProvider>
4851
</ThemeProvider>

packages/web/src/app/page.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import { Separator } from "@/components/ui/separator";
1111
import { SymbolIcon } from "@radix-ui/react-icons";
1212
import { UpgradeToast } from "./components/upgradeToast";
1313
import Link from "next/link";
14-
import { KeyboardShortcutHint } from "./components/keyboardShortcutHint";
1514
import RegistrationCard from "./components/registrationCard";
1615
import { PUBLIC_SEARCH_DEMO } from "@/lib/environment";
16+
import { SyntaxReferenceGuideHint } from "./components/syntaxReferenceGuideHint";
1717

1818
export default async function Home() {
1919
return (
@@ -103,9 +103,7 @@ export default async function Home() {
103103
</QueryExample>
104104
</HowToSection>
105105
</div>
106-
<div className="text-sm">
107-
<span className="dark:text-gray-300">Reference guide: </span><KeyboardShortcutHint shortcut="⌘" /> <KeyboardShortcutHint shortcut="/" />
108-
</div>
106+
<SyntaxReferenceGuideHint />
109107
</div>
110108
</div>
111109

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use client';
2+
3+
import { createContext, useContext, useCallback, useState } from 'react';
4+
5+
interface SyntaxGuideContextType {
6+
isOpen: boolean;
7+
onOpenChanged: (isOpen: boolean) => void;
8+
}
9+
10+
const SyntaxGuideContext = createContext<SyntaxGuideContextType | null>(null);
11+
12+
export const useSyntaxGuide = () => {
13+
const context = useContext(SyntaxGuideContext);
14+
if (!context) {
15+
throw new Error('useSyntaxGuide must be used within a SyntaxGuideProvider');
16+
}
17+
return context;
18+
};
19+
20+
export const SyntaxGuideProvider = ({ children }: { children: React.ReactNode }) => {
21+
const [isOpen, setIsOpen] = useState(false);
22+
23+
const onOpenChanged = useCallback((isOpen: boolean) => {
24+
setIsOpen(isOpen);
25+
}, []);
26+
27+
return (
28+
<SyntaxGuideContext.Provider value={{ isOpen, onOpenChanged }}>
29+
{children}
30+
</SyntaxGuideContext.Provider>
31+
);
32+
};

0 commit comments

Comments
 (0)