Skip to content

Commit d6ca909

Browse files
authored
fix: better search command (#36)
1 parent effc66e commit d6ca909

File tree

5 files changed

+57
-8
lines changed

5 files changed

+57
-8
lines changed

www/src/components/search-command.tsx

+33-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@ import React from "react";
44
import { useRouter } from "next/navigation";
55
import { useDocsSearch } from "fumadocs-core/search/client";
66
import { SortedResult } from "fumadocs-core/server";
7-
import { FileTextIcon, HashIcon, TextIcon } from "lucide-react";
7+
import {
8+
ChevronsUpDownIcon,
9+
CornerDownLeftIcon,
10+
FileTextIcon,
11+
HashIcon,
12+
Loader2Icon,
13+
SearchIcon,
14+
TextIcon,
15+
Undo2Icon,
16+
} from "lucide-react";
817
import { kekabCaseToTitle } from "@/lib/string";
918
import { useCommandMenuInputRef } from "@/hooks/use-focus-command-menu";
1019
import {
@@ -85,7 +94,17 @@ export const SearchCommand = ({
8594
onValueChange={setSearch}
8695
autoFocus
8796
placeholder="Search a component, a block, a hook..."
88-
wrapperClassName={cn(animated && "border-b-0")}
97+
icon={
98+
query.isLoading && search !== "" ? (
99+
<Loader2Icon className="animate-spin" />
100+
) : (
101+
<SearchIcon />
102+
)
103+
}
104+
wrapperClassName={cn(
105+
"[&_svg]:text-fg-muted [&_svg]:size-4",
106+
animated && "border-b-0"
107+
)}
89108
/>
90109
{animated && (
91110
<CommandSeparator className="before:opacity-1 before:animate-loading before:delay-900 relative h-[2px] overflow-hidden before:absolute before:left-0 before:top-0 before:h-full before:w-1/2 before:bg-[linear-gradient(90deg,rgba(0,0,0,0)_0,#707070_50%,rgba(0,0,0,0)_100%)] before:opacity-0 before:content-['']" />
@@ -118,6 +137,18 @@ export const SearchCommand = ({
118137
</CommandGroup>
119138
))}
120139
</CommandList>
140+
{!animated && (
141+
<div className="text-fg-muted flex items-center justify-end gap-4 rounded-b-[inherit] border-t p-3 text-xs [&_svg]:size-4">
142+
<div className="flex items-center gap-1">
143+
<ChevronsUpDownIcon />
144+
<span>Navigate</span>
145+
</div>
146+
<div className="flex items-center gap-1">
147+
<CornerDownLeftIcon />
148+
<span>Go</span>
149+
</div>
150+
</div>
151+
)}
121152
</CommandRoot>
122153
);
123154
};

www/src/components/sidebar.tsx

+14-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
} from "@/registry/ui/default/core/collapsible";
2424
import { Dialog, DialogRoot } from "@/registry/ui/default/core/dialog";
2525
import { Kbd } from "@/registry/ui/default/core/kbd";
26+
import { DismissButton } from "@/registry/ui/default/core/overlay";
2627
import { ScrollArea } from "@/registry/ui/default/core/scroll-area";
2728
import { Tooltip, TooltipProps } from "@/registry/ui/default/core/tooltip";
2829
import { cn } from "@/registry/ui/default/lib/cn";
@@ -286,8 +287,19 @@ const SearchCommandDialog = ({ isCollapsed }: { isCollapsed: boolean }) => {
286287
</span>
287288
</SidebarButton>
288289
</StyledTooltip>
289-
<Dialog>
290-
<SearchCommand onRunCommand={() => setIsOpen(false)} />
290+
<Dialog className="!p-0" showDismissButton={false}>
291+
<SearchCommand
292+
onRunCommand={() => setIsOpen(false)}
293+
className="h-72 max-h-full"
294+
/>
295+
<DismissButton
296+
variant="outline"
297+
shape="rectangle"
298+
size="sm"
299+
className="h-7 px-2 text-xs font-normal"
300+
>
301+
Esc
302+
</DismissButton>
291303
</Dialog>
292304
</DialogRoot>
293305
);

www/src/registry/ui/default/core/command/command.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@ type CommandInputProps = React.ComponentPropsWithoutRef<
2525
typeof CommandPrimitive.Input
2626
> & {
2727
wrapperClassName?: string;
28+
icon?: React.ReactNode;
2829
};
2930
const CommandInput = React.forwardRef<
3031
React.ElementRef<typeof CommandPrimitive.Input>,
3132
CommandInputProps
32-
>(({ className, wrapperClassName, ...props }, ref) => (
33+
>(({ className, wrapperClassName, icon, ...props }, ref) => (
3334
<div
34-
className={cn("flex items-center border-b px-3", wrapperClassName)}
35+
className={cn("flex items-center gap-2 border-b px-3", wrapperClassName)}
3536
cmdk-input-wrapper=""
3637
>
37-
<SearchIcon className="mr-2 h-4 w-4 shrink-0 opacity-50" />
38+
{icon || <SearchIcon className="size-4 shrink-0" />}
3839
<CommandPrimitive.Input
3940
ref={ref}
4041
className={cn(
@@ -56,7 +57,7 @@ const CommandList = React.forwardRef<
5657
>(({ className, ...props }, ref) => (
5758
<CommandPrimitive.List
5859
ref={ref}
59-
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
60+
className={cn("flex-1 overflow-y-auto overflow-x-hidden", className)}
6061
{...props}
6162
/>
6263
));

www/src/registry/ui/default/core/overlay/overlay.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ export {
309309
PopoverOverlay,
310310
DrawerOverlay,
311311
ModalOverlay,
312+
DismissButton,
312313
drawerVariants,
313314
modalVariants,
314315
popoverOverlayVariants,

www/src/styles/globals.css

+4
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@
265265
@apply absolute left-0 top-3 h-3 w-[1px] bg-border content-[''];
266266
}
267267

268+
.focus-ring {
269+
@apply ring-team-current ring-offset-4 ring-offset-white transition duration-300 focus-within:outline-none focus-within:ring-2 focus-within:ring-team-current hover:ring-2 hover:ring-team-current focus:outline-none focus:ring-2 focus:ring-team-current disabled:ring-0 group-hover:ring-2 group-hover:ring-team-current group-focus:ring-2 group-focus:ring-team-current dark:ring-offset-gray-900;
270+
}
271+
268272
@media (max-width: 640px) {
269273
.container {
270274
@apply px-4;

0 commit comments

Comments
 (0)