Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8dea461
feat(VCommandPalette): add new command palette component
MatthewAry Oct 17, 2025
743c68a
test(VCommandPalette): fix keyboard navigation edge cases
MatthewAry Oct 17, 2025
3806cdd
refactor(VCommandPalette): reorganize slot rendering
MatthewAry Oct 17, 2025
18f246b
test(VCommandPalette): add hotkey functionality tests for item selection
MatthewAry Oct 17, 2025
9bc8d73
refactor(VCommandPalette): Fix lint errors
MatthewAry Oct 17, 2025
cd4d141
Update packages/vuetify/src/labs/VCommandPalette/composables/useComma…
MatthewAry Nov 4, 2025
68460fc
Merge branch 'master' into matthewary/v-command-palette-r1
MatthewAry Nov 7, 2025
d7c80f8
Merge branch 'master' into matthewary/v-command-palette-r1
MatthewAry Nov 12, 2025
6f7a255
feat(VList): add navigationMode and navigationIndex props
MatthewAry Nov 13, 2025
7adc62b
Merge master into branch
MatthewAry Nov 13, 2025
0c3a67f
Merge branch 'temp' into matthewary/v-command-palette-r1
MatthewAry Nov 13, 2025
7624378
Initial Commit
MatthewAry Nov 13, 2025
ad41547
Merge master into branch
MatthewAry Nov 14, 2025
fe157e9
Made changes according to feedback from @johnleider
MatthewAry Nov 14, 2025
8e13563
Incorporate VList Changes
MatthewAry Nov 14, 2025
ee62c7a
Woops
MatthewAry Nov 14, 2025
def9e9c
Rough pass on docs - needs polish
MatthewAry Nov 14, 2025
537315d
Update packages/vuetify/src/components/VList/VList.tsx
MatthewAry Nov 14, 2025
c35d43a
Made changes according to feedback from @johnleider
MatthewAry Nov 14, 2025
5a17d7a
Merge branch 'master' into matthewary/feat-VList-navigation-modes
MatthewAry Nov 18, 2025
53e492a
Implement recommended changes from @J-Sek
MatthewAry Nov 18, 2025
1cacf0f
Add visual feedback as requested by @J-Sek
MatthewAry Nov 18, 2025
97e8682
fix scroll to active
J-Sek Nov 18, 2025
b0d5af7
Address concerns by @J-Sek
MatthewAry Nov 19, 2025
3fe829b
Merge 'matthewary/feat-VList-navigation-modes' into this one
MatthewAry Nov 19, 2025
6c63668
Update packages/vuetify/src/components/VList/VListItem.tsx
MatthewAry Nov 19, 2025
ca8453a
Merge 'matthewary/feat-VList-navigation-modes' into here
MatthewAry Nov 19, 2025
cb19f2d
Scroll Instant
MatthewAry Nov 19, 2025
a53eda2
sync
MatthewAry Nov 19, 2025
a36ea37
Delegate more responsibility to VList
MatthewAry Nov 19, 2025
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
26 changes: 26 additions & 0 deletions packages/api-generator/src/locale/en/VCommandPalette.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"props": {
"modelValue": "Controls the visibility state of the command palette dialog. When `true`, the palette is open; when `false`, it's closed.",
"search": "The current search query string. Can be used with `v-model:search` to control or monitor the search input value.",
"items": "Array of command palette items to display. Supports three item types via discriminated union: action items (with `type: 'item'` or no type), subheaders (with `type: 'subheader'`), and dividers (with `type: 'divider'`). Action items can include properties like `title`, `subtitle`, `prependIcon`, `appendIcon`, `hotkey`, `onClick`, `to`, and `href` for navigation and interaction.",
"filterKeys": "Array of item property keys to use when filtering items by the search query. By default filters on `['title', 'subtitle']`. Can be customized to search additional fields.",
"filterMode": "Controls the filtering algorithm used for search. Accepts standard filter modes for matching behavior.",
"placeholder": "Placeholder text displayed in the search input field. Defaults to the locale string for command search.",
"hotkey": "Global keyboard shortcut to toggle the command palette. Accepts hotkey strings like `'meta+k'` or `'ctrl+shift+p'`. The shortcut is automatically registered and unregistered based on component lifecycle.",
"noDataText": "Text displayed when no items match the current search query. Defaults to the standard `$vuetify.noDataText` locale string.",
"location": "Controls the position of the dialog on screen. Inherits from `v-dialog`'s location prop, supporting values like `'top'`, `'bottom'`, `'start'`, `'end'`, and combinations.",
"activator": "Designates a component to act as the activator for the command palette. Can be set to `'parent'` to use the parent element, or accepts other activator configurations from `v-dialog`.",
"dialogProps": "Object containing additional props to pass through to the underlying `v-dialog` component. Useful for customizing dialog behavior like `persistent`, `fullscreen`, `scrollable`, etc."
},
"events": {
"update:modelValue": "Emitted when the dialog visibility state changes. Event payload is a boolean indicating the new open/closed state.",
"update:search": "Emitted when the search query changes. Event payload is the new search string value.",
"click:item": "Emitted when a command palette item is clicked or activated via keyboard (Enter key). Event payload includes the clicked item object and the triggering event (MouseEvent or KeyboardEvent). The palette automatically closes after this event unless prevented."
},
"slots": {
"prepend": "Content to display above the search input, inside the command palette card. Useful for headers, instructions, or custom UI elements.",
"append": "Content to display below the items list, inside the command palette card. Useful for footers, help text, or additional actions.",
"no-data": "Custom content to display when no items match the search query. Replaces the default no-data message."
}
}

4 changes: 4 additions & 0 deletions packages/api-generator/src/locale/en/VList.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"lines": "Designates a **minimum-height** for all children `v-list-item` components. This prop uses [line-clamp](https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-line-clamp) and is not supported in all browsers.",
"link": "Applies `v-list-item` hover styles. Useful when using the item is an _activator_.",
"nav": "An alternative styling that reduces `v-list-item` width and rounds the corners. Typically used with **[v-navigation-drawer](/components/navigation-drawers)**.",
"navigationIndex": "Specifies the currently selected navigation index when using `navigationStrategy=\"track\"`. Can be used with `v-model:navigationIndex` for two-way binding. When set, overrides the internal navigation state.",
"navigationStrategy": "Determines keyboard navigation behavior. **focus** (default) moves DOM focus to items, suitable for traditional lists. **track** updates an index without moving focus, ideal for command palettes and autocomplete components where an external element retains focus.",
"subheader": "Removes the top padding from `v-list-subheader` components. When used as a **String**, renders a subheader for you.",
"slim": "Reduces horizontal spacing for badges, icons, tooltips, and avatars within slim list items to create a more compact visual representation.",
"collapseIcon": "Icon to display when the list item is expanded.",
Expand All @@ -20,6 +22,7 @@
"click:open": "Emitted when the list item is opened.",
"click:select": "Emitted when the list item is selected.",
"update:activated": "Emitted when the list item is activated.",
"update:navigationIndex": "Emitted when keyboard navigation occurs in `navigationStrategy=\"track\"`. The event payload is the new index of the selected item. Automatically skips non-selectable items like dividers and subheaders.",
"update:opened": "Emitted when the list item is opened.",
"update:selected": "Emitted when the list item is selected."
},
Expand All @@ -36,6 +39,7 @@
"children": "The nested list items within the component.",
"focus": "Focus the list item.",
"getPath": "Get the position of an item within the nested structure.",
"navigationIndex": "A computed ref that returns the current navigation index when using `navigationStrategy=\"track\"`. Returns -1 when no item is selected or when using `navigationStrategy=\"focus\"`.",
"open": "Open the list item.",
"parents": "The parent list items within the component."
}
Expand Down
3 changes: 2 additions & 1 deletion packages/api-generator/src/locale/en/VListItem.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"value": "The value used for selection. Obtained from [`v-list`](/api/v-list)'s `v-model:selected` when the item is selected.",
"lines": "The line declaration specifies the minimum height of the item and can also be controlled from v-list with the same prop.",
"nav": "Reduces the width v-list-item takes up as well as adding a border radius.",
"slim": "Reduces horizontal spacing for badges, icons, tooltips, and avatars to create a more compact visual representation."
"slim": "Reduces horizontal spacing for badges, icons, tooltips, and avatars to create a more compact visual representation.",
"tabindex": "Controls the tabindex of the list item. When set, overrides the default tabindex behavior. Automatically set to -1 by VList when using `navigationStrategy=\"track\"` to prevent Tab key navigation into items."
},
"exposed": {
"activate": "Activate the list item.",
Expand Down
4 changes: 4 additions & 0 deletions packages/docs/src/data/nav.json
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@
"title": "color-inputs",
"subfolder": "components"
},
{
"title": "command-palettes",
"subfolder": "components"
},
{
"title": "date-inputs",
"subfolder": "components"
Expand Down
206 changes: 206 additions & 0 deletions packages/docs/src/examples/v-command-palette/prop-dialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
<template>
<v-container fluid>
<v-row>
<v-col cols="12" md="4">
<v-card>
<v-card-title>Default (Center)</v-card-title>
<v-card-text>
<v-btn block @click="dialogs.default = true">
Open Default
</v-btn>
</v-card-text>
</v-card>

<v-command-palette
v-model="dialogs.default"
:items="items"
placeholder="Search..."
@click:item="handleClick"
></v-command-palette>
</v-col>

<v-col cols="12" md="4">
<v-card>
<v-card-title>Top Position</v-card-title>
<v-card-text>
<v-btn block @click="dialogs.top = true">
Open at Top
</v-btn>
</v-card-text>
</v-card>

<v-command-palette
v-model="dialogs.top"
:items="items"
location="top"
placeholder="Search..."
@click:item="handleClick"
></v-command-palette>
</v-col>

<v-col cols="12" md="4">
<v-card>
<v-card-title>Parent Activator</v-card-title>
<v-card-text>
<v-btn block>
Click to Open
<v-command-palette
v-model="dialogs.activator"
:items="items"
activator="parent"
placeholder="Search..."
@click:item="handleClick"
></v-command-palette>
</v-btn>
</v-card-text>
</v-card>
</v-col>
</v-row>

<v-row>
<v-col cols="12">
<v-card>
<v-card-title>Custom Dialog Props</v-card-title>
<v-card-text>
<v-btn block @click="dialogs.custom = true">
Open Persistent (No Close on Click Outside)
</v-btn>
</v-card-text>
</v-card>

<v-command-palette
v-model="dialogs.custom"
:dialog-props="{ persistent: true }"
:items="items"
placeholder="Search..."
@click:item="handleClick"
></v-command-palette>
</v-col>
</v-row>

<v-snackbar v-model="snackbar" :timeout="2000">
Selected: {{ selectedItem }}
</v-snackbar>
</v-container>
</template>

<script setup>
import { ref } from 'vue'

const dialogs = ref({
default: false,
top: false,
activator: false,
custom: false,
})

const snackbar = ref(false)
const selectedItem = ref('')

const items = [
{
title: 'New File',
subtitle: 'Create a new file',
prependIcon: 'mdi-file-plus',
value: 'new-file',
},
{
title: 'New Folder',
subtitle: 'Create a new folder',
prependIcon: 'mdi-folder-plus',
value: 'new-folder',
},
{
title: 'Open',
subtitle: 'Open a file or project',
prependIcon: 'mdi-folder-open',
value: 'open',
},
{
type: 'divider',
},
{
type: 'subheader',
title: 'Recent',
},
{
title: 'Project Alpha',
subtitle: 'Last opened 2 hours ago',
prependIcon: 'mdi-folder',
value: 'project-alpha',
},
{
title: 'Project Beta',
subtitle: 'Last opened yesterday',
prependIcon: 'mdi-folder',
value: 'project-beta',
},
]

function handleClick (item) {
selectedItem.value = item.title
snackbar.value = true
}
</script>

<script>
export default {
data () {
return {
dialogs: {
default: false,
top: false,
activator: false,
custom: false,
},
snackbar: false,
selectedItem: '',
items: [
{
title: 'New File',
subtitle: 'Create a new file',
prependIcon: 'mdi-file-plus',
value: 'new-file',
},
{
title: 'New Folder',
subtitle: 'Create a new folder',
prependIcon: 'mdi-folder-plus',
value: 'new-folder',
},
{
title: 'Open',
subtitle: 'Open a file or project',
prependIcon: 'mdi-folder-open',
value: 'open',
},
{
type: 'divider',
},
{
type: 'subheader',
title: 'Recent',
},
{
title: 'Project Alpha',
subtitle: 'Last opened 2 hours ago',
prependIcon: 'mdi-folder',
value: 'project-alpha',
},
{
title: 'Project Beta',
subtitle: 'Last opened yesterday',
prependIcon: 'mdi-folder',
value: 'project-beta',
},
],
}
},
methods: {
handleClick (item) {
this.selectedItem = item.title
this.snackbar = true
},
},
}
</script>
Loading
Loading