Command

Command provides an accessible command surface for searching and running actions, with list/group/item primitives and optional dialog composition.

Use CommandDialog for modal command palettes, or render Command inline for embedded action pickers.

Preview

Open documentation
Copy install command
Toggle dark mode

Usage

import { Command, CommandInput, CommandItem, CommandList } from '@branditdev/ui';

export function CommandDemo() {
  return (
    <div className='max-w-md rounded-md border'>
      <Command>
        <CommandInput placeholder='Search docs...' />
        <CommandList>
          <CommandItem>Open documentation</CommandItem>
          <CommandItem>Copy install command</CommandItem>
          <CommandItem>Toggle dark mode</CommandItem>
        </CommandList>
      </Command>
    </div>
  );
}

API

Command(props): Element

Defined in: components/command/command.tsx:51

Command palette root surface built on cmdk.

Parameters

NameTypeOptionalDefaultDescription
propsChildren & Pick<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" \keyof HTMLAttributes<HTMLDivElement>> & object & object, "key" \"asChild" \keyof HTMLAttributes<HTMLDivElement>> & object & RefAttributes<HTMLDivElement>

Returns

Element

A styled command container.

Source

'use client';

import { Command as CommandPrimitive } from 'cmdk';
import { SearchIcon } from 'lucide-react';
import * as React from 'react';

import { cn } from '@branditdev/ui';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from '../dialog';

export type CommandProps = React.ComponentProps<typeof CommandPrimitive>;
export type CommandDialogProps = React.ComponentProps<typeof Dialog> & {
  title?: React.ReactNode;
  description?: string;
  className?: string;
  showCloseButton?: boolean;
  renderHeader?: boolean;
  children?: React.ReactNode;
};
export type CommandInputProps = React.ComponentProps<
  typeof CommandPrimitive.Input
>;
export type CommandListProps = React.ComponentProps<
  typeof CommandPrimitive.List
>;
export type CommandEmptyProps = React.ComponentProps<
  typeof CommandPrimitive.Empty
>;
export type CommandGroupProps = React.ComponentProps<
  typeof CommandPrimitive.Group
>;
export type CommandSeparatorProps = React.ComponentProps<
  typeof CommandPrimitive.Separator
>;
export type CommandItemProps = React.ComponentProps<
  typeof CommandPrimitive.Item
>;
export type CommandShortcutProps = React.ComponentProps<'span'>;

function Command({ className, ...props }: CommandProps) {
  return (
    <CommandPrimitive
      data-slot='command'
      className={cn(
        'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md',
        className
      )}
      {...props}
    />
  );
}

function CommandDialog({
  title = 'Command Palette',
  description = 'Search for a command to run...',
  children,
  className,
  showCloseButton = true,
  renderHeader = false,
  ...props
}: CommandDialogProps) {
  return (
    <Dialog {...props}>
      <DialogContent
        className={cn('overflow-hidden p-0', className)}
        showCloseButton={showCloseButton}
      >
        <DialogHeader className={cn(['p-6', { 'sr-only': !renderHeader }])}>
          <DialogTitle>{title}</DialogTitle>
          <DialogDescription>{description}</DialogDescription>
        </DialogHeader>
        <Command className='**:[[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:font-medium **:[[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'>
          {children}
        </Command>
      </DialogContent>
    </Dialog>
  );
}

function CommandInput({ className, ...props }: CommandInputProps) {
  return (
    <div
      data-slot='command-input-wrapper'
      className='flex h-9 items-center gap-2 border-b px-3'
    >
      <SearchIcon className='size-4 shrink-0 opacity-50' />
      <CommandPrimitive.Input
        data-slot='command-input'
        className={cn(
          'placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
          className
        )}
        {...props}
      />
    </div>
  );
}

function CommandList({ className, ...props }: CommandListProps) {
  return (
    <CommandPrimitive.List
      data-slot='command-list'
      className={cn(
        'max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto',
        className
      )}
      {...props}
    />
  );
}

function CommandEmpty({ ...props }: CommandEmptyProps) {
  return (
    <CommandPrimitive.Empty
      data-slot='command-empty'
      className='py-6 text-center text-sm'
      {...props}
    />
  );
}

function CommandGroup({ className, ...props }: CommandGroupProps) {
  return (
    <CommandPrimitive.Group
      data-slot='command-group'
      className={cn(
        'text-foreground **:[[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium',
        className
      )}
      {...props}
    />
  );
}

function CommandSeparator({ className, ...props }: CommandSeparatorProps) {
  return (
    <CommandPrimitive.Separator
      data-slot='command-separator'
      className={cn('bg-border -mx-1 h-px', className)}
      {...props}
    />
  );
}

function CommandItem({ className, ...props }: CommandItemProps) {
  return (
    <CommandPrimitive.Item
      data-slot='command-item'
      className={cn(
        "data-[selected=true]:bg-accent dark:data-[selected=true]:bg-accent/20 data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground 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 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
        className
      )}
      {...props}
    />
  );
}

function CommandShortcut({ className, ...props }: CommandShortcutProps) {
  return (
    <span
      data-slot='command-shortcut'
      className={cn(
        'text-muted-foreground ml-auto text-xs tracking-widest',
        className
      )}
      {...props}
    />
  );
}

export {
  Command,
  CommandDialog,
  CommandInput,
  CommandList,
  CommandEmpty,
  CommandGroup,
  CommandItem,
  CommandShortcut,
  CommandSeparator,
};