Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<script setup lang="ts">
const groups = [
{
id: 'actions',
items: [
{
label: 'Add new file',
suffix: 'Create a new file in the current directory',
icon: 'i-lucide-file-plus',
kbds: ['meta', 'N']
},
{
label: 'Add new folder',
suffix: 'Create a new folder in the current directory',
icon: 'i-lucide-folder-plus',
kbds: ['meta', 'F']
},
{
label: 'Search files',
suffix: 'Search across all files in the project',
icon: 'i-lucide-search',
kbds: ['meta', 'P']
},
{
label: 'Settings',
suffix: 'Open application settings',
icon: 'i-lucide-settings',
kbds: ['meta', ',']
}
]
},
{
id: 'recent',
label: 'Recent',
items: [
{
label: 'project.vue',
suffix: 'components/',
icon: 'i-vscode-icons-file-type-vue'
},
{
label: 'readme.md',
suffix: 'docs/',
icon: 'i-vscode-icons-file-type-markdown'
},
{
label: 'package.json',
suffix: 'root/',
icon: 'i-vscode-icons-file-type-node'
}
]
}
]
</script>

<template>
<UCommandPalette :groups="groups" class="flex-1 h-80">
<template #footer>
<div class="flex items-center justify-between gap-2">
<UIcon name="i-simple-icons-nuxtdotjs" class="size-5 text-dimmed ml-1" />
<div class="flex items-center gap-1">
<UButton color="neutral" variant="ghost" label="Open Command" class="text-dimmed" size="xs">
<template #trailing>
<UKbd value="enter" />
</template>
</UButton>
<USeparator orientation="vertical" class="h-4" />
<UButton color="neutral" variant="ghost" label="Actions" class="text-dimmed" size="xs">
<template #trailing>
<UKbd value="meta" />
<UKbd value="k" />
</template>
</UButton>
</div>
</div>
</template>
</UCommandPalette>
</template>
14 changes: 14 additions & 0 deletions docs/content/3.components/command-palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,20 @@ props:
This can be useful when using the CommandPalette inside a [`Modal`](/components/modal) for example.
::

### With footer slot :badge{label="Soon" class="align-text-top"}

Use the `#footer` slot to add custom content at the bottom of the CommandPalette, such as keyboard shortcuts help or additional actions.

::component-example
---
collapse: true
name: 'command-palette-footer-slot-example'
class: '!p-0'
props:
autofocus: false
---
::

### With custom slot

Use the `slot` property to customize a specific item or group.
Expand Down
22 changes: 21 additions & 1 deletion playground/app/pages/components/command-palette.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,27 @@ defineShortcuts({
multiple
class="sm:max-h-80"
@update:model-value="onSelect"
/>
>
<template #footer>
<div class="flex items-center justify-between gap-2">
<UIcon name="i-simple-icons-nuxtdotjs" class="size-5 text-dimmed ml-1" />
<div class="flex items-center gap-1">
<UButton color="neutral" variant="ghost" label="Open Command" class="text-dimmed" size="xs">
<template #trailing>
<UKbd value="enter" />
</template>
</UButton>
<USeparator orientation="vertical" class="h-4" />
<UButton color="neutral" variant="ghost" label="Actions" class="text-dimmed" size="xs">
<template #trailing>
<UKbd value="meta" />
<UKbd value="k" />
</template>
</UButton>
</div>
</div>
</template>
</UCommandPalette>
</DefineTemplate>

<div class="flex-1 flex flex-col gap-12 w-full max-w-lg">
Expand Down
5 changes: 5 additions & 0 deletions src/runtime/components/CommandPalette.vue
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ type SlotProps<T> = (props: { item: T, index: number }) => any

export type CommandPaletteSlots<G extends CommandPaletteGroup<T> = CommandPaletteGroup<any>, T extends CommandPaletteItem = CommandPaletteItem> = {
'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
'close'(props: { ui: { [K in keyof Required<CommandPalette['slots']>]: (props?: Record<string, any>) => string } }): any
'item': SlotProps<T>
Expand Down Expand Up @@ -444,5 +445,9 @@ function onSelect(e: Event, item: T) {
</slot>
</div>
</ListboxContent>

<div v-if="!!slots.footer" :class="ui.footer({ class: props.ui?.footer })">
<slot name="footer" :ui="ui" />
</div>
</ListboxRoot>
</template>
1 change: 1 addition & 0 deletions src/theme/command-palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default (options: Required<ModuleOptions>) => ({
close: '',
back: 'p-0',
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',
group: 'p-1 isolate',
empty: 'py-6 text-center text-sm text-muted',
Expand Down
3 changes: 2 additions & 1 deletion test/components/CommandPalette.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ 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 close slot', { props: { ...props, close: true }, slots: { close: () => 'Close 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> }) => {
const html = await ComponentRender(nameOrHtml, options, CommandPalette)
expect(html).toMatchSnapshot()
Expand Down
Loading