Skip to content
16 changes: 13 additions & 3 deletions src/runtime/components/CommandPalette.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export interface CommandPaletteProps<G extends CommandPaletteGroup<T> = CommandP
* @defaultValue appConfig.ui.icons.chevronRight
* @IconifyIcon
*/
trailingIcon?: string
itemTrailingIcon?: string
/**
* The placeholder text for the input.
* @defaultValue t('commandPalette.placeholder')
Expand All @@ -91,6 +91,12 @@ export interface CommandPaletteProps<G extends CommandPaletteGroup<T> = CommandP
* @defaultValue true
*/
autofocus?: boolean
/**
* The icon displayed in the input.
* @defaultValue appConfig.ui.icons.search
* @IconifyIcon
*/
trailingIcon?: string
/**
* Display a close button in the input (useful when inside a Modal for example).
* `{ size: 'md', color: 'neutral', variant: 'ghost' }`{lang="ts-type"}
Expand Down Expand Up @@ -149,6 +155,7 @@ export type CommandPaletteSlots<G extends CommandPaletteGroup<T> = CommandPalett
'empty'(props: { searchTerm?: string }): any
'footer'(props: { ui: { [K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string } }): any
'back'(props: { ui: { [K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string } }): any
'actions'(props: { ui: { [K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string } }): any
'close'(props: { ui: { [K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string } }): any
'item': SlotProps<T>
'item-leading': SlotProps<T>
Expand Down Expand Up @@ -337,6 +344,7 @@ function onSelect(e: Event, item: T) {
:autofocus="autofocus"
v-bind="inputProps"
:icon="icon || appConfig.ui.icons.search"
:trailing-icon="trailingIcon"
:class="ui.input({ class: props.ui?.input })"
@keydown.backspace="onBackspace"
>
Expand All @@ -354,7 +362,9 @@ function onSelect(e: Event, item: T) {
</slot>
</template>

<template v-if="close || !!slots.close" #trailing>
<template v-if="trailingIcon || close || !!slots.close || !!slots.actions" #trailing>
<UIcon v-if="trailingIcon" :name="trailingIcon" :class="ui.trailingIcon({ class: props.ui?.trailingIcon })" />
<slot name="actions" :ui="ui" />
<slot name="close" :ui="ui">
<UButton
v-if="close"
Expand Down Expand Up @@ -417,7 +427,7 @@ function onSelect(e: Event, item: T) {
<slot :name="((item.slot ? `${item.slot}-trailing` : group.slot ? `${group.slot}-trailing` : `item-trailing`) as keyof CommandPaletteSlots<G, T>)" :item="(item as any)" :index="index">
<UIcon
v-if="item.children && item.children.length > 0"
:name="trailingIcon || appConfig.ui.icons.chevronRight"
:name="itemTrailingIcon || appConfig.ui.icons.chevronRight"
:class="ui.itemTrailingIcon({ class: [props.ui?.itemTrailingIcon, item.ui?.itemTrailingIcon] })"
/>

Expand Down
1 change: 1 addition & 0 deletions src/theme/command-palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default (options: Required<ModuleOptions>) => ({
input: '[&>input]:h-12',
close: '',
back: 'p-0',
trailingIcon: 'shrink-0 size-5 text-dimmed',
content: 'relative overflow-hidden flex flex-col',
footer: 'p-1',
viewport: 'relative divide-y divide-default scroll-py-1 overflow-y-auto flex-1 focus:outline-none',
Expand Down
3 changes: 3 additions & 0 deletions test/components/CommandPalette.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ describe('CommandPalette', () => {
['with placeholder', { props: { ...props, placeholder: 'Search...' } }],
['with disabled', { props: { ...props, disabled: true } }],
['with icon', { props: { ...props, icon: 'i-lucide-terminal' } }],
['with trailingIcon', { props: { ...props, inputTrailingIcon: 'i-lucide-settings' } }],
['with itemTrailingIcon', { props: { ...props, itemTrailingIcon: 'i-lucide-arrow-right' } }],
['with loading', { props: { ...props, loading: true } }],
['with loadingIcon', { props: { ...props, loading: true, loadingIcon: 'i-lucide-loader' } }],
['with selectedIcon', { props: { ...props, selectedIcon: 'i-lucide-badge-check', modelValue: groups[2]?.items[0] } }],
Expand All @@ -89,6 +91,7 @@ describe('CommandPalette', () => {
['with item-label slot', { props, slots: { 'item-label': () => 'Item label slot' } }],
['with item-trailing slot', { props, slots: { 'item-trailing': () => 'Item trailing slot' } }],
['with custom slot', { props, slots: { custom: () => 'Custom slot' } }],
['with actions slot', { props, slots: { actions: () => 'Actions slot' } }],
['with close slot', { props: { ...props, close: true }, slots: { close: () => 'Close slot' } }],
['with footer slot', { props, slots: { footer: () => 'Footer slot' } }]
])('renders %s correctly', async (nameOrHtml: string, options: { props?: CommandPaletteProps, slots?: Partial<CommandPaletteSlots> }) => {
Expand Down
Loading