command.tsx raw

   1  import * as React from "react";
   2  import { Command as CommandPrimitive } from "cmdk";
   3  import { SearchIcon } from "lucide-react";
   4  
   5  import { cn } from "src/lib/utils";
   6  import {
   7    Dialog,
   8    DialogContent,
   9    DialogDescription,
  10    DialogHeader,
  11    DialogTitle,
  12  } from "src/components/ui/dialog";
  13  
  14  function Command({
  15    className,
  16    ...props
  17  }: React.ComponentProps<typeof CommandPrimitive>) {
  18    return (
  19      <CommandPrimitive
  20        data-slot="command"
  21        className={cn(
  22          "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
  23          className
  24        )}
  25        {...props}
  26      />
  27    );
  28  }
  29  
  30  function CommandDialog({
  31    title = "Command Palette",
  32    description = "Search for a command to run...",
  33    children,
  34    className,
  35    showCloseButton = true,
  36    ...props
  37  }: React.ComponentProps<typeof Dialog> & {
  38    title?: string;
  39    description?: string;
  40    className?: string;
  41    showCloseButton?: boolean;
  42  }) {
  43    return (
  44      <Dialog {...props}>
  45        <DialogHeader className="sr-only">
  46          <DialogTitle>{title}</DialogTitle>
  47          <DialogDescription>{description}</DialogDescription>
  48        </DialogHeader>
  49        <DialogContent
  50          className={cn("overflow-hidden p-0", className)}
  51          showCloseButton={showCloseButton}
  52        >
  53          <Command className="**:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[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">
  54            {children}
  55          </Command>
  56        </DialogContent>
  57      </Dialog>
  58    );
  59  }
  60  
  61  function CommandInput({
  62    className,
  63    ...props
  64  }: React.ComponentProps<typeof CommandPrimitive.Input>) {
  65    return (
  66      <div
  67        data-slot="command-input-wrapper"
  68        className="flex h-9 items-center gap-2 border-b px-3"
  69      >
  70        <SearchIcon className="size-4 shrink-0 opacity-50" />
  71        <CommandPrimitive.Input
  72          data-slot="command-input"
  73          className={cn(
  74            "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
  75            className
  76          )}
  77          {...props}
  78        />
  79      </div>
  80    );
  81  }
  82  
  83  function CommandList({
  84    className,
  85    ...props
  86  }: React.ComponentProps<typeof CommandPrimitive.List>) {
  87    return (
  88      <CommandPrimitive.List
  89        data-slot="command-list"
  90        className={cn(
  91          "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
  92          className
  93        )}
  94        {...props}
  95      />
  96    );
  97  }
  98  
  99  function CommandEmpty({
 100    ...props
 101  }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
 102    return (
 103      <CommandPrimitive.Empty
 104        data-slot="command-empty"
 105        className="py-6 text-center text-sm"
 106        {...props}
 107      />
 108    );
 109  }
 110  
 111  function CommandGroup({
 112    className,
 113    ...props
 114  }: React.ComponentProps<typeof CommandPrimitive.Group>) {
 115    return (
 116      <CommandPrimitive.Group
 117        data-slot="command-group"
 118        className={cn(
 119          "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",
 120          className
 121        )}
 122        {...props}
 123      />
 124    );
 125  }
 126  
 127  function CommandSeparator({
 128    className,
 129    ...props
 130  }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
 131    return (
 132      <CommandPrimitive.Separator
 133        data-slot="command-separator"
 134        className={cn("-mx-1 h-px bg-border", className)}
 135        {...props}
 136      />
 137    );
 138  }
 139  
 140  function CommandItem({
 141    className,
 142    ...props
 143  }: React.ComponentProps<typeof CommandPrimitive.Item>) {
 144    return (
 145      <CommandPrimitive.Item
 146        data-slot="command-item"
 147        className={cn(
 148          "relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
 149          className
 150        )}
 151        {...props}
 152      />
 153    );
 154  }
 155  
 156  function CommandShortcut({
 157    className,
 158    ...props
 159  }: React.ComponentProps<"span">) {
 160    return (
 161      <span
 162        data-slot="command-shortcut"
 163        className={cn(
 164          "ml-auto text-xs tracking-widest text-muted-foreground",
 165          className
 166        )}
 167        {...props}
 168      />
 169    );
 170  }
 171  
 172  export {
 173    Command,
 174    CommandDialog,
 175    CommandInput,
 176    CommandList,
 177    CommandEmpty,
 178    CommandGroup,
 179    CommandItem,
 180    CommandShortcut,
 181    CommandSeparator,
 182  };
 183