MagicCommand
MagicCommand is a flexible collection of components intended to build command palette style menus, such as Spotlight, Raycast and the like.
<template>
<magic-command-provider id="magic-command-demo" class="flex flex-col gap-6">
<magic-command-trigger view-id="initial-default-view" as-child>
<m-button>Open Menu</m-button>
</magic-command-trigger>
<div class="type-surface-body-sm text-surface-muted">
<span>or press ⌘+K / ⌃+K</span>
</div>
<magic-command-modal :options="{ focusTrap: false }">
<m-menu-box class="h-[30rem] w-[40rem]">
<magic-command-renderer />
</m-menu-box>
</magic-command-modal>
<default-view id="initial-default-view" />
</magic-command-provider>
</template>
<script lang="ts" setup>
import { MButton, MMenuBox } from 'mirror-compat'
import DefaultView from './components/DefaultView.vue'
</script>Anatomy
<template>
<magic-command-provider id="your-command-id">
<!-- modal -->
<magic-command-modal>
<magic-command-renderer />
</magic-command-modal>
<!-- drawer -->
<magic-command-drawer>
<magic-command-renderer />
</magic-command-drawer>
<!-- initial view -->
<magic-command-view :initial="true" id="your-view-id">
<magic-command-trigger>Open Menu</magic-command-trigger>
<magic-command-content>
<magic-command-item>
<!-- your content -->
</magic-command-item>
<!-- nested view -->
<magic-command-item>
<magic-command-view>
<magic-command-trigger>Open View</magic-command-trigger>
<magic-command-content>
<!-- your content -->
</magic-command-content>
</magic-command-view>
</magic-command-item>
</magic-command-content>
</magic-command-view>
<!-- optional -->
<magic-command-trigger view-id="your-view-id">
Open Menu
</magic-command-trigger>
</magic-command-provider>
</template>
<script setup>
const { open, close } = useMagicCommand('your-command-id')
</script>
Custom Layout
Both MagicCommandModal and MagicCommandDrawer render a default layout out of the box. Use the #layout slot to replace the entire inner structure when you need full control. For example to remove the backdrop or customise the teleport target.
<template>
<magic-command-modal>
<template #layout>
<magic-modal-teleport>
<magic-modal-content>
<magic-command-renderer />
</magic-modal-content>
</magic-modal-teleport>
</template>
</magic-command-modal>
</template>
See MagicModal and MagicDrawer for details.
Installation
CLI
Add @maas/vue-equipment to your dependencies.
pnpm add @maas/vue-equipment
Vue
If you are using Vue, import and add MagicCommandPlugin to your app.
import { createApp } from 'vue'
import { MagicCommandPlugin } from '@maas/vue-equipment/plugins/MagicCommand'
const app = createApp({})
app.use(MagicCommandPlugin)
Nuxt
The command palette is available as a Nuxt module. In your Nuxt config file add @maas/vue-equipment/nuxt to your modules and add MagicCommand to the plugins in your configuration.
export default defineNuxtConfig({
modules: ['@maas/vue-equipment/nuxt'],
vueEquipment: {
plugins: ['MagicCommand'],
},
})
Composable
In order to interact with the command palette from anywhere within your app, we provide a useMagicCommand composable. Import it directly when needed.
import { useMagicCommand } from '@maas/vue-equipment/plugins/MagicCommand'
const { selectView } = useMagicCommand('your-command-id')
function handleClick() {
selectView('your-view-id')
}
Peer Dependencies
MagicCommand relies on the following optional peer dependencies in addition to the core peer dependencies. Package managers don’t install optional peer dependencies automatically, so add them to your project.
Installation
pnpm add @vueuse/integrations focus-trap wheel-gestures
API Reference
MagicCommandProvider
The MagicCommandProvider wraps the command palette and configures all child components according to the provided options.
Props
Options
To customize the command palette, override the necessary options. Any custom options will be merged with the default options.
MagicCommandView
Groups command items into a single panel and tracks which item is currently selected.
Props
Slot Props
MagicCommandDrawer
Wraps the command palette in a MagicDrawerProvider and renders teleport, backdrop and content by default. Override the full inner structure using the #layout slot.
Props
MagicCommandModal
Wraps the command palette in a MagicModalProvider and renders teleport, backdrop and content by default. Override the full inner structure using the #layout slot.
Props
MagicCommandRenderer
Renders command items dynamically from registered commands.
CSS Variables
MagicCommandItem
A single interactive command entry.
Props
CSS Variables
Slot Props
MagicCommandTrigger
Opens or closes the command palette on click.
Props
CSS Variables
Slot Props
Errors
Examples
Modal
<template>
<magic-command-provider
id="magic-command-modal-demo"
:options="{ keyListener: { open: false } }"
>
<magic-command-trigger view-id="initial-modal-view" as-child>
<m-button>Open Menu</m-button>
</magic-command-trigger>
<magic-command-modal :options="{ focusTrap: false }">
<m-menu-box class="h-[30rem] w-[40rem]">
<magic-command-renderer />
</m-menu-box>
</magic-command-modal>
<default-view id="initial-modal-view" />
</magic-command-provider>
</template>
<script lang="ts" setup>
import { MButton, MMenuBox } from 'mirror-compat'
import DefaultView from './components/DefaultView.vue'
</script>Drawer
<template>
<magic-command-provider
id="magic-command-drawer-demo"
:options="{ keyListener: { open: false } }"
>
<magic-command-trigger view-id="initial-drawer-view" as-child>
<m-button>Open Menu</m-button>
</magic-command-trigger>
<magic-command-drawer :options="{ focusTrap: false }">
<div
class="h-full w-full p-2 pb-[calc(var(--magic-drawer-drag-overshoot)+0.5rem)]"
>
<m-menu-box class="h-full w-full">
<magic-command-renderer />
</m-menu-box>
</div>
</magic-command-drawer>
<default-view id="initial-drawer-view" />
</magic-command-provider>
</template>
<script lang="ts" setup>
import { MButton, MMenuBox } from 'mirror-compat'
import DefaultView from './components/DefaultView.vue'
</script>
<style>
[data-id='magic-command-drawer-demo'] {
--magic-drawer-width: 40rem;
--magic-drawer-height: 30rem;
}
</style>