Skip to content

Commit 4218160

Browse files
committed
feat: add command component for enhanced UI interactions
1 parent 7a15dac commit 4218160

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

src/components/ui/command.tsx

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import { type DialogProps } from "@radix-ui/react-dialog"
5+
import { Command as CommandPrimitive } from "cmdk"
6+
import { Search } from "lucide-react"
7+
8+
import { cn } from "@/lib/utils"
9+
import { Dialog, DialogContent } from "@/components/ui/dialog"
10+
11+
const Command = React.forwardRef<
12+
React.ElementRef<typeof CommandPrimitive>,
13+
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
14+
>(({ className, ...props }, ref) => (
15+
<CommandPrimitive
16+
ref={ref}
17+
className={cn(
18+
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
19+
className
20+
)}
21+
{...props}
22+
/>
23+
))
24+
Command.displayName = CommandPrimitive.displayName
25+
26+
const CommandDialog = ({ children, ...props }: DialogProps) => {
27+
return (
28+
<Dialog {...props}>
29+
<DialogContent className="overflow-hidden p-0">
30+
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
31+
{children}
32+
</Command>
33+
</DialogContent>
34+
</Dialog>
35+
)
36+
}
37+
38+
const CommandInput = React.forwardRef<
39+
React.ElementRef<typeof CommandPrimitive.Input>,
40+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
41+
>(({ className, ...props }, ref) => (
42+
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
43+
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
44+
<CommandPrimitive.Input
45+
ref={ref}
46+
className={cn(
47+
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
48+
className
49+
)}
50+
{...props}
51+
/>
52+
</div>
53+
))
54+
55+
CommandInput.displayName = CommandPrimitive.Input.displayName
56+
57+
const CommandList = React.forwardRef<
58+
React.ElementRef<typeof CommandPrimitive.List>,
59+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
60+
>(({ className, ...props }, ref) => (
61+
<CommandPrimitive.List
62+
ref={ref}
63+
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
64+
{...props}
65+
/>
66+
))
67+
68+
CommandList.displayName = CommandPrimitive.List.displayName
69+
70+
const CommandEmpty = React.forwardRef<
71+
React.ElementRef<typeof CommandPrimitive.Empty>,
72+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
73+
>((props, ref) => (
74+
<CommandPrimitive.Empty
75+
ref={ref}
76+
className="py-6 text-center text-sm"
77+
{...props}
78+
/>
79+
))
80+
81+
CommandEmpty.displayName = CommandPrimitive.Empty.displayName
82+
83+
const CommandGroup = React.forwardRef<
84+
React.ElementRef<typeof CommandPrimitive.Group>,
85+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
86+
>(({ className, ...props }, ref) => (
87+
<CommandPrimitive.Group
88+
ref={ref}
89+
className={cn(
90+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
91+
className
92+
)}
93+
{...props}
94+
/>
95+
))
96+
97+
CommandGroup.displayName = CommandPrimitive.Group.displayName
98+
99+
const CommandSeparator = React.forwardRef<
100+
React.ElementRef<typeof CommandPrimitive.Separator>,
101+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
102+
>(({ className, ...props }, ref) => (
103+
<CommandPrimitive.Separator
104+
ref={ref}
105+
className={cn("-mx-1 h-px bg-border", className)}
106+
{...props}
107+
/>
108+
))
109+
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
110+
111+
const CommandItem = React.forwardRef<
112+
React.ElementRef<typeof CommandPrimitive.Item>,
113+
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
114+
>(({ className, ...props }, ref) => (
115+
<CommandPrimitive.Item
116+
ref={ref}
117+
className={cn(
118+
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
119+
className
120+
)}
121+
{...props}
122+
/>
123+
))
124+
125+
CommandItem.displayName = CommandPrimitive.Item.displayName
126+
127+
const CommandShortcut = ({
128+
className,
129+
...props
130+
}: React.HTMLAttributes<HTMLSpanElement>) => {
131+
return (
132+
<span
133+
className={cn(
134+
"ml-auto text-xs tracking-widest text-muted-foreground",
135+
className
136+
)}
137+
{...props}
138+
/>
139+
)
140+
}
141+
CommandShortcut.displayName = "CommandShortcut"
142+
143+
export {
144+
Command,
145+
CommandDialog,
146+
CommandInput,
147+
CommandList,
148+
CommandEmpty,
149+
CommandGroup,
150+
CommandItem,
151+
CommandShortcut,
152+
CommandSeparator,
153+
}

0 commit comments

Comments
 (0)