Command

Fast, composable, unstyled command menu for Vue.

Component Features

  • Fast & Responsive: Built on top of Radix Vue for ultimate interactive performance.
  • 🧩 Highly Composable: Composed of multiple small components, flexible for various business scenarios.
  • 🎨 Unstyled by Default: Provides a basic skeleton, easily customizable via Tailwind CSS.
  • ⌨️ Keyboard Navigation: Fully accessible via keyboard, offering a smooth keyboard operation experience.
  • 📋 Nested Support: Supports sub-commands and hierarchical navigation for complex command trees.

Basic Usage

<script setup lang="ts">
import {
  BrCommand,
  BrCommandEmpty,
  BrCommandGroup,
  BrCommandInput,
  BrCommandItem,
  BrCommandList,
  BrCommandSeparator,
  BrCommandShortcut,
} from '@breezeui/vue'
</script>

<template>
  <BrCommand class="rounded-lg border shadow-md max-w-[450px]">
    <BrCommandInput placeholder="Type a command or search..." />
    <BrCommandList>
      <BrCommandEmpty>No results found.</BrCommandEmpty>
      <BrCommandGroup heading="Suggestions">
        <BrCommandItem value="calendar">
          Calendar
        </BrCommandItem>
        <BrCommandItem value="search-emoji">
          Search Emoji
        </BrCommandItem>
        <BrCommandItem value="calculator">
          Calculator
        </BrCommandItem>
      </BrCommandGroup>
      <BrCommandSeparator />
      <BrCommandGroup heading="Settings">
        <BrCommandItem value="profile">
          Profile
          <BrCommandShortcut>⌘P</BrCommandShortcut>
        </BrCommandItem>
        <BrCommandItem value="billing">
          Billing
          <BrCommandShortcut>⌘B</BrCommandShortcut>
        </BrCommandItem>
        <BrCommandItem value="settings">
          Settings
          <BrCommandShortcut>⌘S</BrCommandShortcut>
        </BrCommandItem>
      </BrCommandGroup>
    </BrCommandList>
  </BrCommand>
</template>

Dialog

You can use the BrCommandDialog component to render the command menu in a dialog.

<script setup lang="ts">
import { ref } from 'vue'
import {
  BrButton,
  BrCommandDialog,
  BrCommandEmpty,
  BrCommandGroup,
  BrCommandInput,
  BrCommandItem,
  BrCommandList,
  BrCommandSeparator,
  BrCommandShortcut,
} from '@breezeui/vue'

const open = ref(false)

// Optional: Add keyboard shortcut to open the command dialog
// import { onMounted, onUnmounted } from 'vue'
// onMounted(() => {
//   const down = (e: KeyboardEvent) => {
//     if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
//       e.preventDefault()
//       open.value = !open.value
//     }
//   }
//   document.addEventListener('keydown', down)
//   onUnmounted(() => document.removeEventListener('keydown', down))
// })
</script>

<template>
  <div>
    <p class="text-sm text-muted-foreground mb-4">
      Press <kbd class="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100"><span class="text-xs">⌘</span>K</kbd> or click the button below.
    </p>
    
    <BrButton variant="outline" @click="open = true">
      Open Command Dialog
    </BrButton>

    <BrCommandDialog v-model:open="open">
      <BrCommandInput placeholder="Type a command or search..." />
      <BrCommandList>
        <BrCommandEmpty>No results found.</BrCommandEmpty>
        <BrCommandGroup heading="Suggestions">
          <BrCommandItem value="calendar">
            Calendar
          </BrCommandItem>
          <BrCommandItem value="search-emoji">
            Search Emoji
          </BrCommandItem>
          <BrCommandItem value="calculator">
            Calculator
          </BrCommandItem>
        </BrCommandGroup>
        <BrCommandSeparator />
        <BrCommandGroup heading="Settings">
          <BrCommandItem value="profile">
            Profile
            <BrCommandShortcut>⌘P</BrCommandShortcut>
          </BrCommandItem>
          <BrCommandItem value="billing">
            Billing
            <BrCommandShortcut>⌘B</BrCommandShortcut>
          </BrCommandItem>
          <BrCommandItem value="settings">
            Settings
            <BrCommandShortcut>⌘S</BrCommandShortcut>
          </BrCommandItem>
        </BrCommandGroup>
      </BrCommandList>
    </BrCommandDialog>
  </div>
</template>

Nested Commands

You can navigate between different command groups by changing the active page.

<script setup lang="ts">
import { ref } from 'vue'
import {
  BrCommand,
  BrCommandEmpty,
  BrCommandGroup,
  BrCommandInput,
  BrCommandItem,
  BrCommandList,
  BrCommandSeparator,
} from '@breezeui/vue'

const activePage = ref('home')
</script>

<template>
  <BrCommand class="rounded-lg border shadow-md max-w-[450px]">
    <BrCommandInput placeholder="Type a command or search..." />
    <BrCommandList>
      <BrCommandEmpty>No results found.</BrCommandEmpty>
      
      <template v-if="activePage === 'home'">
        <BrCommandGroup heading="Suggestions">
          <BrCommandItem value="search-projects" @select="activePage = 'projects'">
            Search Projects...
          </BrCommandItem>
          <BrCommandItem value="search-users" @select="activePage = 'users'">
            Search Users...
          </BrCommandItem>
        </BrCommandGroup>
        <BrCommandSeparator />
        <BrCommandGroup heading="Settings">
          <BrCommandItem value="profile">
            Profile
          </BrCommandItem>
        </BrCommandGroup>
      </template>

      <template v-else-if="activePage === 'projects'">
        <BrCommandItem value="back" @select="activePage = 'home'">
          ← Back
        </BrCommandItem>
        <BrCommandGroup heading="Projects">
          <BrCommandItem value="breeze-ui">
            Breeze UI
          </BrCommandItem>
          <BrCommandItem value="vue-app">
            Vue App
          </BrCommandItem>
        </BrCommandGroup>
      </template>

      <template v-else-if="activePage === 'users'">
        <BrCommandItem value="back" @select="activePage = 'home'">
          ← Back
        </BrCommandItem>
        <BrCommandGroup heading="Users">
          <BrCommandItem value="admin">
            Admin
          </BrCommandItem>
          <BrCommandItem value="guest">
            Guest
          </BrCommandItem>
        </BrCommandGroup>
      </template>
    </BrCommandList>
  </BrCommand>
</template>

Global Shortcut

You can bind a global keyboard shortcut to open the command dialog.

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import {
  BrCommandDialog,
  BrCommandEmpty,
  BrCommandGroup,
  BrCommandInput,
  BrCommandItem,
  BrCommandList,
  BrCommandSeparator,
  BrCommandShortcut,
} from '@breezeui/vue'

const open = ref(false)

const handleKeyDown = (e: KeyboardEvent) => {
  if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
    e.preventDefault()
    open.value = !open.value
  }
}

onMounted(() => {
  document.addEventListener('keydown', handleKeyDown)
})

onUnmounted(() => {
  document.removeEventListener('keydown', handleKeyDown)
})
</script>

<template>
  <div>
    <p class="text-sm text-muted-foreground mb-4">
      Press <kbd class="pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[10px] font-medium text-muted-foreground opacity-100"><span class="text-xs">⌘</span>K</kbd> to open the command dialog.
    </p>

    <BrCommandDialog v-model:open="open">
      <BrCommandInput placeholder="Type a command or search..." />
      <BrCommandList>
        <BrCommandEmpty>No results found.</BrCommandEmpty>
        <BrCommandGroup heading="Suggestions">
          <BrCommandItem value="calendar">
            Calendar
          </BrCommandItem>
          <BrCommandItem value="search-emoji">
            Search Emoji
          </BrCommandItem>
          <BrCommandItem value="calculator">
            Calculator
          </BrCommandItem>
        </BrCommandGroup>
        <BrCommandSeparator />
        <BrCommandGroup heading="Settings">
          <BrCommandItem value="profile">
            Profile
            <BrCommandShortcut>⌘P</BrCommandShortcut>
          </BrCommandItem>
          <BrCommandItem value="billing">
            Billing
            <BrCommandShortcut>⌘B</BrCommandShortcut>
          </BrCommandItem>
          <BrCommandItem value="settings">
            Settings
            <BrCommandShortcut>⌘S</BrCommandShortcut>
          </BrCommandItem>
        </BrCommandGroup>
      </BrCommandList>
    </BrCommandDialog>
  </div>
</template>

API

Command Props

NameTypeDefaultDescription
openbooleantrueThe open state of the command menu.
modelValuestring''The value of the selected item.
filterFunction(val: any[], search: string) => any[]-Custom filter function.

CommandInput Props

NameTypeDefaultDescription
valuestring''The search value.

CommandItem Props

NameTypeDefaultDescription
valuestring-The value of the item.
disabledbooleanfalseWhether the item is disabled.

CommandGroup Props

NameTypeDefaultDescription
headingstring-The heading of the group.

CommandDialog Props

NameTypeDefaultDescription
openbooleanfalseThe open state of the dialog.