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-subtle">
<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 '@maas/mirror/vue'
import DefaultView from './components/DefaultView.vue'
</script>Overview
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>Installation
CLI
Add @maas/vue-equipment to your dependencies.
pnpm install @maas/vue-equipmentnpm install @maas/vue-equipmentyarn add @maas/vue-equipmentbun install @maas/vue-equipmentVue
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')
}TIP
If you have installed the command palette as a Nuxt module, the composable will be auto-imported and is automatically available in your Nuxt app.
Peer Dependencies
If you haven’t installed the required peer dependencies automatically, you’ll need to install the following packages manually.
Installation
pnpm install @nuxt/kit @maas/vue-primitive @vueuse/core defunpm install @nuxt/kit @maas/vue-primitive @vueuse/core defuyarn add @nuxt/kit @maas/vue-primitive @vueuse/core defubun install @nuxt/kit @maas/vue-primitive @vueuse/core defuAPI Reference
MagicCommandProvider
The MagicCommandProvider wraps the command palette and configures all child components according to the provided options.
Props
| Prop | Type | Required |
|---|---|---|
MaybeRef<string> | true | |
boolean | false | |
MagicMenuOptions | false |
Options
To customize the command palette, override the necessary options. Any custom options will be merged with the default options.
| Option | Type | Default |
|---|---|---|
boolean | false | |
string | magic-command-content | |
string[] | false | ['Cmd+k', 'Ctrl+k'] | |
string[] | false | ['Escape'] | |
string[] | false | ['ArrowDown'] | |
string[] | false | ['ArrowUp'] | |
string[] | false | ['Enter'] | |
boolean | false |
MagicCommandView
Props
| Prop | Type | Required |
|---|---|---|
MaybeRef<string> | false | |
boolean | false |
MagicCommandDrawer
Props
| Prop | Type | Required |
|---|---|---|
MagicCommandDrawerOptions | false |
MagicCommandModal
Props
| Prop | Type | Required |
|---|---|---|
MagicCommandModalOptions | false |
MagicCommandRenderer
CSS Variables
| Variable | Default |
|---|---|
--magic-command-renderer-width | 100% |
--magic-command-renderer-height | 100% |
MagicCommandItem
Props
| Prop | Type | Required |
|---|---|---|
string | false | |
boolean | false |
CSS Variables
| Variable | Default |
|---|---|
--magic-command-item-cursor | default |
MagicCommandTrigger
Props
| Prop | Type | Required |
|---|---|---|
string | false | |
boolean | false | |
false | ||
false | ||
boolean | false |
| Variable | Default |
|---|---|
--magic-command-trigger-cursor | pointer |
CSS Variables
| Variable | Default |
|---|---|
--magic-command-trigger-cursor | pointer |
Errors
| Source | Error Code | Message |
|---|---|---|
MagicCommandDrawer | missing_instance_id | MagicCommandDrawer must be nested inside MagicCommandProvider |
MagicCommandTrigger | missing_instance_id | MagicCommandTrigger must be nested inside MagicCommandProvider |
MagicCommandTrigger | missing_view_id | MagicCommandTrigger must be nested inside MagicCommandView or a viewId must be provided |
MagicCommandView | missing_instance_id | MagicCommandView must be nested inside MagicCommandProvider |
MagicCommandContent | missing_instance_id | MagicCommandContent must be nested inside MagicCommandProvider |
MagicCommandContent | missing_view_id | MagicCommandContent must be nested inside MagicCommandView |
useMagicCommand | view_id_required | viewId is required to select an item |
useMagicCommand | id_required | id is required to select an item |
useMenuItem | view_id_not_found | View {viewId} not found |
useMenuKeyListener | menu_not_active | MagicMenu {state.id} is not active |
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 '@maas/mirror/vue'
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 '@maas/mirror/vue'
import DefaultView from './components/DefaultView.vue'
</script>
<style>
[data-id='magic-command-drawer-demo'] {
--magic-drawer-width: 40rem;
--magic-drawer-height: 30rem;
}
</style>