Skip to content

Commit dd24c21

Browse files
author
Dan Costello
committed
Add delegate google search
WIP
1 parent 6454b6a commit dd24c21

File tree

7 files changed

+139
-9
lines changed

7 files changed

+139
-9
lines changed

app/RootProvider.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"use client";
2+
3+
import { RootProvider } from "fumadocs-ui/provider";
4+
import type { ReactNode, ComponentType } from "react";
5+
import DefaultSearchDialog from "@/app/components/Search";
6+
import type { SharedProps } from "@/app/components/SearchDialog";
7+
8+
// Create a wrapper component that satisfies the ComponentType<SharedProps> requirement
9+
const SearchDialogWrapper: ComponentType<SharedProps> = (props) => {
10+
return <DefaultSearchDialog {...props} onSearchChange={() => {}} />;
11+
};
12+
13+
export default function Root({ children }: { children: ReactNode }) {
14+
return (
15+
<RootProvider
16+
search={{
17+
SearchDialog: SearchDialogWrapper,
18+
}}
19+
>
20+
{children}
21+
</RootProvider>
22+
);
23+
}

app/components/Search.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"use client";
2+
import type { ReactNode } from "react";
3+
import { SearchDialog, type SharedProps } from "./SearchDialog";
4+
5+
export interface DefaultSearchDialogProps extends SharedProps {
6+
/**
7+
* @defaultValue 'static'
8+
*/
9+
type?: "fetch" | "static";
10+
onSearchChange?: (value: string) => void;
11+
}
12+
13+
export default function DefaultSearchDialog({
14+
...props
15+
}: DefaultSearchDialogProps): ReactNode {
16+
return <SearchDialog {...props} />;
17+
}

app/components/SearchDialog.tsx

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"use client";
2+
3+
import { useCallback, useRef } from "react";
4+
import {
5+
Dialog,
6+
DialogContent,
7+
DialogOverlay,
8+
DialogTitle,
9+
} from "@radix-ui/react-dialog";
10+
11+
export interface SharedProps {
12+
open: boolean;
13+
onOpenChange: (open: boolean) => void;
14+
}
15+
16+
interface SearchDialogProps extends SharedProps {
17+
onSearchChange?: (v: string) => void;
18+
}
19+
20+
export function SearchDialog({
21+
open,
22+
onOpenChange,
23+
onSearchChange,
24+
}: SearchDialogProps) {
25+
const formRef = useRef<HTMLFormElement>(null);
26+
27+
const handleSearch = useCallback((query: string) => {
28+
// create a new tab and append the search query
29+
window.open(
30+
`https://www.google.com/search?q=site:userclouds.com${encodeURIComponent(` ${query}`)}`,
31+
"_blank",
32+
);
33+
}, []);
34+
35+
const handleClose = useCallback(() => {
36+
onOpenChange(false);
37+
if (formRef.current) {
38+
formRef.current.reset();
39+
}
40+
}, [onOpenChange]);
41+
42+
const handleSubmit = useCallback(
43+
(e: React.FormEvent) => {
44+
e.preventDefault();
45+
const formData = new FormData(e.target as HTMLFormElement);
46+
const query = formData.get("search") as string;
47+
if (query) {
48+
handleSearch(query);
49+
onSearchChange?.(query);
50+
}
51+
},
52+
[handleSearch, onSearchChange],
53+
);
54+
55+
return (
56+
<Dialog open={open} onOpenChange={onOpenChange}>
57+
<DialogOverlay className="fixed inset-0 z-50 bg-black/30 backdrop-blur-sm data-[state=closed]:animate-fd-fade-out data-[state=open]:animate-fd-fade-in" />
58+
<DialogContent
59+
aria-describedby={undefined}
60+
className="fixed left-1/2 top-[10vh] z-50 w-[98vw] max-w-screen-sm -translate-x-1/2 rounded-lg border bg-fd-popover text-fd-popover-foreground shadow-lg data-[state=closed]:animate-fd-dialog-out data-[state=open]:animate-fd-dialog-in"
61+
>
62+
<DialogTitle className="hidden">Search…</DialogTitle>
63+
<form
64+
ref={formRef}
65+
onSubmit={handleSubmit}
66+
className="flex flex-row items-center gap-2 px-3"
67+
>
68+
<input
69+
name="search"
70+
defaultValue=""
71+
placeholder="Search…"
72+
onChange={(e) => onSearchChange?.(e.target.value)}
73+
className="w-0 flex-1 bg-transparent py-3 text-base placeholder:text-fd-muted-foreground focus-visible:outline-none"
74+
/>
75+
<button
76+
type="button"
77+
aria-label="Close Search"
78+
onClick={handleClose}
79+
className="text-xs p-1.5 flex items-center gap-2 "
80+
>
81+
<kbd className="rounded-md border bg-fd-background p-1.5">Esc</kbd>
82+
</button>
83+
</form>
84+
</DialogContent>
85+
</Dialog>
86+
);
87+
}

app/layout.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import "./global.css";
2-
import { RootProvider } from "fumadocs-ui/provider";
32
import type { ReactNode } from "react";
43
import type { Metadata } from "next";
4+
import RootProvider from "./RootProvider";
55

66
export const metadata: Metadata = {
77
title: {
@@ -38,13 +38,7 @@ export default function Layout({ children }: { children: ReactNode }) {
3838
return (
3939
<html lang="en" suppressHydrationWarning>
4040
<body className="flex flex-col min-h-screen">
41-
<RootProvider
42-
search={{
43-
enabled: false,
44-
}}
45-
>
46-
{children}
47-
</RootProvider>
41+
<RootProvider>{children}</RootProvider>
4842
</body>
4943
</html>
5044
);

app/utils/cn.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { twMerge as cn } from "tailwind-merge";

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"postinstall": "fumadocs-mdx"
1414
},
1515
"dependencies": {
16+
"@radix-ui/react-dialog": "^1.1.14",
1617
"ajv": "^8.17.1",
1718
"fumadocs-core": "15.4.2",
1819
"fumadocs-mdx": "11.6.6",
@@ -24,7 +25,8 @@
2425
"react": "^19.1.0",
2526
"react-dom": "^19.1.0",
2627
"serve": "^14.2.4",
27-
"shiki": "^3.4.2"
28+
"shiki": "^3.4.2",
29+
"tailwind-merge": "^3.3.0"
2830
},
2931
"devDependencies": {
3032
"@tailwindcss/postcss": "^4.1.8",

pnpm-lock.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)