DashboardSearch

A ready-to-use CommandPalette to add to your dashboard.

Usage

The DashboardSearch component extends the CommandPalette component, so you can pass any property such as icon, placeholder, etc.

Use it inside the default slot of the DashboardGroup component:

layouts/dashboard.vue
<template>
  <PDashboardGroup>
    <PDashboardSidebar>
      <PDashboardSearchButton />
    </PDashboardSidebar>

    <PDashboardSearch />

    <slot />
  </PDashboardGroup>
</template>
You can open the CommandPalette by pressing CtrlK, by using the DashboardSearchButton component or by using a v-model:open directive.

Shortcut

Use the shortcut prop to change the shortcut used in defineShortcuts to open the ContentSearch component. Defaults to meta_k (Ctrl K).

app.vue
<template>
  <PDashboardSearch
    v-model:search-term="searchTerm"
    shortcut="meta_k"
    :groups="groups"
    :fuse="{ resultLimit: 42 }"
  />
</template>

Color Mode

By default, a group of commands will be added to the command palette so you can switch between light and dark mode. This will only take effect if the colorMode is not forced in a specific page which can be achieved through definePageMeta:

pages/index.vue
<script setup lang="ts">
definePageMeta({
  colorMode: 'dark'
});
</script>

You can disable this behavior by setting the color-mode prop to false:

app.vue
<template>
  <PDashboardSearch
    v-model:search-term="searchTerm"
    :color-mode="false"
    :groups="groups"
    :fuse="{ resultLimit: 42 }"
  />
</template>

API

Props

Prop Default Type
size
'md'
"md" | "xs" | "sm" | "lg" | "xl"
close
true
boolean | Omit<ButtonProps, LinkPropsKeys>

Display a close button in the input (useful when inside a Modal for example). { size: 'md', color: 'neutral', variant: 'ghost' }

input
true
boolean | Omit<InputProps<AcceptableValue, ModelModifiers>, "modelValue" | "defaultValue">

Configure the input or hide it with false. { fixed: true }

shortcut
'meta_k'
string

Keyboard shortcut to open the search (used by defineShortcuts)

fuse
{ fuseOptions: { ignoreLocation: true, useTokenSearch: true, threshold: 0.1, keys: ['label', 'description', 'suffix'] }, resultLimit: 12, matchAllWhenSearchEmpty: true }
UseFuseOptions<CommandPaletteItem>

Options for useFuse passed to the CommandPalette.

searchDelay
100
number

Delay (in milliseconds) before the search term is passed to Fuse (debounced). Useful for large datasets where running fuzzy search on every keystroke is the bottleneck — the input stays responsive while Fuse only re-runs after typing settles. Set to 0 to disable.

colorMode
true
boolean

When true, the theme command will be added to the groups.

title
string
description
string
overlay
true
boolean

Render an overlay behind the modal.

transition
true
boolean

Animate the modal when opening or closing.

content
DialogContentProps & Partial<EmitsToProps<DialogContentImplEmits>>

The content of the modal.

dismissible
true
boolean

When false, the modal will not close when clicking outside or pressing escape.

fullscreen
false
boolean

When true, the modal will take up the full screen.

modal
boolean

The modality of the dialog When set to true,
interaction with outside elements will be disabled and only dialog content will be visible to screen readers.

portal
true
string | false | true | HTMLElement

Render the modal in a portal.

unmountOnHide
true
boolean

When set to false, the dialog content will not be unmounted when closed, but instead hidden with CSS.
Useful for SEO or when you want to improve performance by not remounting the component on every open.

icon
appConfig.ui.icons.search
any

The icon displayed in the input. Set to false to hide the icon.

trailingIcon
appConfig.ui.icons.search
any

The icon displayed on the right side of the input.

selectedIcon
appConfig.ui.icons.check
any

The icon displayed when an item is selected.

childrenIcon
appConfig.ui.icons.chevronRight
any

The icon displayed when an item has children.

placeholder
t('commandPalette.placeholder')
string

The placeholder text for the input.

autofocus
true
boolean

Automatically focus the input when component is mounted.

loading
boolean

When true, the loading icon will be displayed.

loadingIcon
appConfig.ui.icons.loading
any

The icon when the loading prop is true.

closeIcon
appConfig.ui.icons.close
any

The icon displayed in the close button.

back
true
boolean | Omit<ButtonProps, LinkPropsKeys>

Display a button to navigate back in history. { size: 'md', color: 'neutral', variant: 'link' }

backIcon
appConfig.ui.icons.arrowLeft
any

The icon displayed in the back button.

disabled
boolean

When true, prevents the user from interacting with listbox

highlightOnHover
boolean

When true, hover over item will trigger highlight

loop
boolean

When true, keyboard navigation will loop from last item to first, and vice versa.

labelKey
'label'
string

The key used to get the label from the item.

descriptionKey
'description'
string

The key used to get the description from the item.

preserveGroupOrder
false
boolean

Whether to preserve the order of groups as defined in the groups prop when filtering. When false, groups will appear based on item matches.

virtualize
false
boolean | { overscan?: number ; estimateSize?: number | ((index: number) => number) | undefined; } | undefined

Enable virtualization for large lists. Note: when enabled, all groups are flattened into a single list due to a limitation of Akar

groups
CommandPaletteGroup<CommandPaletteItem>[]
open
boolean
searchTerm
string
ui
{ modal?: SlotClass; input?: SlotClass; } & { root?: SlotClass; input?: SlotClass; close?: SlotClass; back?: SlotClass; content?: SlotClass; footer?: SlotClass; viewport?: SlotClass; group?: SlotClass; empty?: SlotClass; label?: SlotClass; item?: SlotClass; itemLeadingIcon?: SlotClass; itemLeadingAvatar?: SlotClass; itemLeadingAvatarSize?: SlotClass; itemLeadingChip?: SlotClass; itemLeadingChipSize?: SlotClass; itemTrailing?: SlotClass; itemTrailingIcon?: SlotClass; itemTrailingHighlightedIcon?: SlotClass; itemTrailingKbds?: SlotClass; itemTrailingKbdsSize?: SlotClass; itemWrapper?: SlotClass; itemLabel?: SlotClass; itemLabelBase?: SlotClass; itemLabelPrefix?: SlotClass; itemLabelSuffix?: SlotClass; itemDescription?: SlotClass; }

Slots

Slot Type
empty
{ searchTerm: string; }
footer
{ ui: object; }
back
{ ui: object; }
close
{ ui: object; }
item
{ item: CommandPaletteItem; index: number; ui: object; }
item-leading
{ item: CommandPaletteItem; index: number; ui: object; }
item-label
{ item: CommandPaletteItem; index: number; ui: object; }
item-description
{ item: CommandPaletteItem; index: number; ui: object; }
item-trailing
{ item: CommandPaletteItem; index: number; ui: object; }
group-label
{ group: CommandPaletteGroup<CommandPaletteItem>; label: string; ui: object; }
content
{ close: () => void; }

Emits

Event Type
update:open
[value: boolean]
update:searchTerm
[value: string]

Expose

When accessing the component via a template ref, you can use the following:

NameType
commandPaletteRefRef<InstanceType<typeof PCommandPalette> | null>

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    dashboardSearch: {
      slots: {
        modal: '',
        input: ''
      },
      variants: {
        fullscreen: {
          false: {
            modal: 'h-full sm:h-[28rem] sm:max-w-3xl'
          }
        },
        size: {
          xs: {},
          sm: {},
          md: {},
          lg: {},
          xl: {}
        }
      },
      defaultVariants: {
        size: 'md'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from 'pohon-ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        dashboardSearch: {
          slots: {
            modal: '',
            input: ''
          },
          variants: {
            fullscreen: {
              false: {
                modal: 'h-full sm:h-[28rem] sm:max-w-3xl'
              }
            },
            size: {
              xs: {},
              sm: {},
              md: {},
              lg: {},
              xl: {}
            }
          },
          defaultVariants: {
            size: 'md'
          }
        }
      }
    })
  ]
})

Changelog

No recent changes