Skip to content

Commit 80751c3

Browse files
Title for docs. Backlinks in docs. cmdk update.
1 parent 623520c commit 80751c3

21 files changed

+441
-191
lines changed

src/components/backlinks.tsx

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React from "react";
2+
3+
import { useBacklinkedDocs } from "@/queries/backlinks";
4+
import { Doc } from "@/lib/types";
5+
import { useOpenDocsStore } from "@/stores/docs";
6+
7+
export function Backlinks({ id }: { id: string }) {
8+
const { docs } = useBacklinkedDocs(id);
9+
const { openDoc } = useOpenDocsStore();
10+
11+
if (!docs || docs.length === 0) return null;
12+
13+
return (
14+
<div className="flex flex-col gap-4 mt-auto">
15+
<small className="font-medium text-secondary !text-xs">Backlinks</small>
16+
<ul className="flex items-center gap-2">
17+
{docs.map((doc: Doc) => (
18+
<li key={doc.id}>
19+
<button
20+
onMouseDown={() => openDoc(doc.id)}
21+
onKeyDown={(e) => {
22+
if (e.key === "Enter" || e.key === " ") {
23+
return openDoc(doc.id);
24+
}
25+
}}
26+
className="flex items-center gap-1.5 px-2 py-1 h-7 rounded-lg bg-gray-3 text-xs hover:bg-gray-4 outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
27+
>
28+
<span>{doc.emoji}</span>
29+
<span className="font-medium">{doc.title}</span>
30+
</button>
31+
</li>
32+
))}
33+
</ul>
34+
</div>
35+
);
36+
}

src/components/client-island.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ type IslandProps = {
55
fallback?: React.ReactNode;
66
lazy?: boolean;
77
delay?: number; // Optional delay before showing
8+
suspense?: boolean; // use suspense
89
onMount?: () => void; // Callback when mounted
910
};
1011

@@ -26,6 +27,7 @@ export function Island({
2627
delay = 0,
2728
onMount,
2829
fallback,
30+
suspense,
2931
}: IslandProps) {
3032
const [mounted, setMounted] = useState(false);
3133
const [shouldRender, setShouldRender] = useState(!delay);
@@ -48,6 +50,10 @@ export function Island({
4850
// Don't render yet if there's a delay
4951
if (!shouldRender) return fallback || null;
5052

53+
if (suspense) {
54+
return <Suspense fallback={fallback}>{children}</Suspense>;
55+
}
56+
5157
if (lazy) {
5258
return (
5359
<Suspense fallback={fallback}>

src/components/command-menu.tsx

-135
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { useCommandContext } from "@/components/command-menu";
2+
import { CommandGroup, CommandItem } from "@/primitives/command";
3+
import { useDocs } from "@/queries/docs";
4+
import { useOpenDocsStore } from "@/stores/docs";
5+
6+
export function CommandDocs() {
7+
const { setOpen } = useCommandContext();
8+
const { docs } = useDocs();
9+
const { openDoc } = useOpenDocsStore();
10+
11+
return (
12+
<CommandGroup heading="Documents">
13+
{docs?.map((doc) => (
14+
<CommandItem
15+
key={doc.id}
16+
keywords={[doc.id, doc.title!]}
17+
onSelect={() => {
18+
openDoc(doc.id);
19+
setOpen(false);
20+
}}
21+
>
22+
<p>{doc.emoji}</p>
23+
<small className="font-medium">{doc.title}</small>
24+
</CommandItem>
25+
))}
26+
</CommandGroup>
27+
);
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { useTheme } from "next-themes";
2+
import {
3+
ArchiveBoxXMarkIcon,
4+
ArrowRightEndOnRectangleIcon,
5+
BookOpenIcon,
6+
ComputerDesktopIcon,
7+
DocumentPlusIcon,
8+
MagnifyingGlassIcon,
9+
} from "@heroicons/react/16/solid";
10+
11+
import { CommandGroup, CommandItem } from "@/primitives/command";
12+
import { useDocs } from "@/queries/docs";
13+
import { useOpenDocsStore, useReadOnlyStore } from "@/stores/docs";
14+
import { useCommandContext } from "@/components/command-menu";
15+
16+
export function CommandHome() {
17+
const { setOpen, setCurrentPage } = useCommandContext();
18+
const { newDoc } = useDocs();
19+
const { docs: openDocs, closeDoc, closeAllDocs } = useOpenDocsStore();
20+
const { setReadOnlyMode, readOnlyMode } = useReadOnlyStore();
21+
const { theme, setTheme } = useTheme();
22+
23+
return (
24+
<>
25+
<CommandGroup>
26+
<CommandItem
27+
onSelect={() => {
28+
newDoc();
29+
setOpen(false);
30+
}}
31+
>
32+
<DocumentPlusIcon className="w-4 h-4 opacity-70" />
33+
<small className="font-medium">New document</small>
34+
</CommandItem>
35+
<CommandItem
36+
onSelect={() => {
37+
setCurrentPage("docs");
38+
}}
39+
>
40+
<MagnifyingGlassIcon className="w-4 h-4 opacity-70" />
41+
<small className="font-medium">Goto document...</small>
42+
</CommandItem>
43+
{openDocs.length > 0 && (
44+
<>
45+
<CommandItem
46+
onSelect={() => {
47+
closeDoc(openDocs.pop() as string);
48+
setOpen(false);
49+
}}
50+
>
51+
<ArrowRightEndOnRectangleIcon className="w-4 h-4 opacity-70" />
52+
<small className="font-medium">Close last document</small>
53+
</CommandItem>
54+
<CommandItem
55+
onSelect={() => {
56+
closeAllDocs();
57+
setOpen(false);
58+
}}
59+
>
60+
<ArchiveBoxXMarkIcon className="w-4 h-4 opacity-70" />
61+
<small className="font-medium">Close all documents</small>
62+
</CommandItem>
63+
</>
64+
)}
65+
</CommandGroup>
66+
<CommandGroup heading="Settings">
67+
<CommandItem
68+
onSelect={() => {
69+
setReadOnlyMode(!readOnlyMode);
70+
setOpen(false);
71+
}}
72+
>
73+
<BookOpenIcon className="w-4 h-4 opacity-70" />
74+
<small className="font-medium">Toggle read-only mode</small>
75+
</CommandItem>
76+
<CommandItem
77+
onSelect={() => {
78+
setTheme(theme === "dark" ? "light" : "dark");
79+
setOpen(false);
80+
}}
81+
>
82+
<ComputerDesktopIcon className="w-4 h-4 opacity-70" />
83+
<small className="font-medium">Toggle theme</small>
84+
</CommandItem>
85+
</CommandGroup>
86+
</>
87+
);
88+
}

0 commit comments

Comments
 (0)