CommandMenu

CommandMenu represents a command menu component.

Usage#

import { CommandMenu } from 'primereact/commandmenu';
<CommandMenu>
    <CommandMenu.Input />
    <CommandMenu.Empty> </CommandMenu.Empty>
    <CommandMenu.List>
        <CommandMenu.Group>
            <CommandMenu.GroupHeading></CommandMenu.GroupHeading>
            <CommandMenu.Item></CommandMenu.Item>
        </CommandMenu.Group>
    </CommandMenu.List>
</CommandMenu>

Examples#

Basic#

No results found for ""
Test
basic-demo.tsx
'use client';
import { CommandMenu } from 'primereact/commandmenu';
import * as React from 'react';
import { cmds } from './cmds';

export default function BasicDemo() {
    const [search, setSearch] = React.useState('');

    return (
        <CommandMenu>
            <div className="border-b border-surface-200 dark:border-surface-700/50 px-4 py-2">
                <CommandMenu.Input value={search} onValueChange={(val: string) => setSearch(val)} placeholder="Search for commands..." />
            </div>
            <CommandMenu.List>
                <CommandMenu.Empty>
                    No results found for <span className="text-surface-900 dark:text-surface-0">&quot;{search}&quot;</span>
                </CommandMenu.Empty>
                {commands.map((group) => (
                    <CommandMenu.Group key={group.group} value={group.group}>
                        <CommandMenu.GroupHeading>{group.group}</CommandMenu.GroupHeading>
                        {group.items.map((item, index) => (
                            <CommandMenu.Item key={index} value={item.value}>
                                <div className={`w-5 h-5 rounded-md ${item.color} flex items-center justify-center text-white`}>
                                    <i className={`pi ${item.icon} text-xs font-bold`}></i>
                                </div>
                                <span>{item.label}</span>
                                <span className="opacity-50 ml-auto">{item.category}</span>
                            </CommandMenu.Item>
                        ))}
                    </CommandMenu.Group>
                ))}
                <CommandMenu.Item value="test">Test</CommandMenu.Item>
            </CommandMenu.List>
        </CommandMenu>
    );
}

const commands = [
    {
        group: 'recents',
        items: [
            {
                icon: 'pi-refresh',
                label: 'Check For Updates',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(245,83,84),rgb(235,70,70))]',
                value: 'check for updates',
                keywords: ['check', 'updates']
            },
            {
                icon: 'pi-cog',
                label: 'Open Settings',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(96,165,250),rgb(59,130,246))]',
                value: 'open settings'
            },
            {
                icon: 'pi-search',
                label: 'Search Files',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(167,139,250),rgb(139,92,246))]',
                value: 'search files'
            },
            {
                icon: 'pi-terminal',
                label: 'Open Terminal',
                category: 'View',
                color: 'bg-[linear-gradient(rgb(148,163,184),rgb(100,116,139))]',
                value: 'open terminal'
            },
            {
                icon: 'pi-history',
                label: 'View History',
                category: 'View',
                color: 'bg-[linear-gradient(rgb(192,132,252),rgb(168,85,247))]',
                value: 'view history',
                keywords: ['history', 'recent']
            },
            {
                icon: 'pi-comments',
                label: 'Open Chat',
                category: 'Communication',
                color: 'bg-[linear-gradient(rgb(34,211,238),rgb(6,182,212))]',
                value: 'open chat'
            }
        ]
    },
    ...cmds
];

Filter#

Use the filter prop to customize the filtering of the items.

No results found.
filter-demo.tsx
'use client';
import { CommandMenu } from 'primereact/commandmenu';
import { cmds } from './cmds';

const commands = [
    {
        group: 'recents',
        items: [
            {
                icon: 'pi-refresh',
                label: 'Check For Updates',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(245,83,84),rgb(235,70,70))]',
                value: 'check for updates',
                keywords: ['check', 'updates']
            },
            {
                icon: 'pi-cog',
                label: 'Open Settings',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(96,165,250),rgb(59,130,246))]',
                value: 'open settings'
            },
            {
                icon: 'pi-search',
                label: 'Search Files',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(167,139,250),rgb(139,92,246))]',
                value: 'search files'
            },
            {
                icon: 'pi-terminal',
                label: 'Open Terminal',
                category: 'View',
                color: 'bg-[linear-gradient(rgb(148,163,184),rgb(100,116,139))]',
                value: 'open terminal'
            },
            {
                icon: 'pi-history',
                label: 'View History',
                category: 'View',
                color: 'bg-[linear-gradient(rgb(192,132,252),rgb(168,85,247))]',
                value: 'view history',
                keywords: ['history', 'recent']
            },
            {
                icon: 'pi-comments',
                label: 'Open Chat',
                category: 'Communication',
                color: 'bg-[linear-gradient(rgb(34,211,238),rgb(6,182,212))]',
                value: 'open chat'
            }
        ]
    },
    ...cmds
];

export default function FuzeDemo() {
    return (
        <CommandMenu
            filter={(value: string, search: string) => {
                if (!search) return 1;

                value = value.toLowerCase();
                search = search.toLowerCase();

                let tIndex = 0;
                let sIndex = 0;
                let score = 0;

                while (tIndex < value.length && sIndex < search.length) {
                    if (value[tIndex] === search[sIndex]) {
                        score += 1; // match score
                        sIndex++;
                    }

                    tIndex++;
                }

                return sIndex === search.length ? score / value.length : 0;
            }}
        >
            <div className="border-b border-surface-200 dark:border-surface-700/50 px-4 py-2">
                <CommandMenu.Input placeholder="Search for commands..." />
            </div>
            <CommandMenu.List>
                <CommandMenu.Empty>No results found.</CommandMenu.Empty>
                {commands.map((group) => (
                    <CommandMenu.Group key={group.group} value={group.group}>
                        <CommandMenu.GroupHeading>{group.group}</CommandMenu.GroupHeading>
                        {group.items.map((item, index) => (
                            <CommandMenu.Item key={index} value={item.value}>
                                <div className={`w-5 h-5 rounded-md ${item.color} flex items-center justify-center text-white`}>
                                    <i className={`pi ${item.icon} text-xs font-bold`}></i>
                                </div>
                                <span>{item.label}</span>
                                <span className="opacity-50 ml-auto">{item.category}</span>
                            </CommandMenu.Item>
                        ))}
                    </CommandMenu.Group>
                ))}
            </CommandMenu.List>
        </CommandMenu>
    );
}

With Dialog#

Use the CommandPalette component inside a Dialog component to create a command palette that is displayed in a dialog. useHotKey hook is used to open the dialog with the meta+k shortcut.

Press CTRL/⌘ + K
with-dialog-demo.tsx
'use client';
import { useHotKey } from '@primereact/hooks';
import { DialogChangeEvent, DialogContentInstance } from '@primereact/types/shared/dialog';
import { CommandMenu } from 'primereact/commandmenu';
import { Dialog } from 'primereact/dialog';
import * as React from 'react';
import { cmds } from './cmds';

const commands = [
    {
        group: 'recents',
        items: [
            {
                icon: 'pi-refresh',
                label: 'Check For Updates',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(245,83,84),rgb(235,70,70))]',
                value: 'check for updates',
                keywords: ['check', 'updates']
            },
            {
                icon: 'pi-cog',
                label: 'Open Settings',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(96,165,250),rgb(59,130,246))]',
                value: 'open settings'
            },
            {
                icon: 'pi-search',
                label: 'Search Files',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(167,139,250),rgb(139,92,246))]',
                value: 'search files'
            },
            {
                icon: 'pi-terminal',
                label: 'Open Terminal',
                category: 'View',
                color: 'bg-[linear-gradient(rgb(148,163,184),rgb(100,116,139))]',
                value: 'open terminal'
            },
            {
                icon: 'pi-history',
                label: 'View History',
                category: 'View',
                color: 'bg-[linear-gradient(rgb(192,132,252),rgb(168,85,247))]',
                value: 'view history',
                keywords: ['history', 'recent']
            },
            {
                icon: 'pi-comments',
                label: 'Open Chat',
                category: 'Communication',
                color: 'bg-[linear-gradient(rgb(34,211,238),rgb(6,182,212))]',
                value: 'open chat'
            }
        ]
    },
    ...cmds
];

export default function BasicDemo() {
    const [search, setSearch] = React.useState('');
    const [open, setOpen] = React.useState(false);

    useHotKey('meta+k', () => setOpen(true));

    return (
        <div className="flex items-center justify-center py-8">
            <div className="flex items-center gap-2">
                Press{' '}
                <kbd className="bg-surface-100 dark:bg-surface-950 px-2 py-1 rounded-md border border-surface-200 dark:border-surface-700/50 text-sm">
                    CTRL/⌘ + K
                </kbd>
            </div>
            <Dialog open={open} onOpenChange={(e: DialogChangeEvent) => setOpen(e.value as boolean)} modal dismissableMask>
                <Dialog.Portal>
                    <Dialog.Content unstyled className="bg-none p-0 border-none sm:min-w-[520px] w-full">
                        {(instance: DialogContentInstance) => {
                            const { dialog } = instance;

                            return (
                                <CommandMenu className=" border-none">
                                    <div className="border-b border-surface-200 dark:border-surface-700/50 px-4 py-2 flex items-center gap-2">
                                        <CommandMenu.Input
                                            className="flex-1"
                                            value={search}
                                            onValueChange={(val: string) => setSearch(val)}
                                            placeholder="Search for commands..."
                                        />
                                        <kbd
                                            onClick={dialog?.close}
                                            className="cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-900 px-2 py-1 rounded-md border border-surface-200 dark:border-surface-700/50 text-xs"
                                        >
                                            ESC
                                        </kbd>
                                    </div>
                                    <CommandMenu.List>
                                        <CommandMenu.Empty>
                                            No results found for <span className="text-surface-900 dark:text-surface-0">&quot;{search}&quot;</span>
                                        </CommandMenu.Empty>
                                        {commands.map((group) => (
                                            <CommandMenu.Group key={group.group} value={group.group}>
                                                <CommandMenu.GroupHeading>{group.group}</CommandMenu.GroupHeading>
                                                {group.items.map((item, index) => (
                                                    <CommandMenu.Item key={index} value={item.value}>
                                                        <div
                                                            className={`w-5 h-5 rounded-md ${item.color} flex items-center justify-center text-white`}
                                                        >
                                                            <i className={`pi ${item.icon} text-xs font-bold`}></i>
                                                        </div>
                                                        <span>{item.label}</span>
                                                        <span className="opacity-50 ml-auto">{item.category}</span>
                                                    </CommandMenu.Item>
                                                ))}
                                            </CommandMenu.Group>
                                        ))}
                                    </CommandMenu.List>
                                </CommandMenu>
                            );
                        }}
                    </Dialog.Content>
                </Dialog.Portal>
            </Dialog>
        </div>
    );
}

Controlled#

No results found for ""
Test
controlled-demo.tsx
'use client';
import { CommandMenu } from 'primereact/commandmenu';
import * as React from 'react';
import { cmds } from './cmds';

export default function ControlledDemo() {
    const [search, setSearch] = React.useState('');
    const [selected, setSelected] = React.useState('open chat');

    return (
        <CommandMenu selected={selected} onSelectedChange={setSelected}>
            <div className="border-b border-surface-200 dark:border-surface-700/50 px-4 py-2">
                <CommandMenu.Input value={search} onValueChange={(val: string) => setSearch(val)} placeholder="Search for commands..." />
            </div>
            <CommandMenu.List>
                <CommandMenu.Empty>
                    No results found for <span className="text-surface-900 dark:text-surface-0">&quot;{search}&quot;</span>
                </CommandMenu.Empty>
                {commands.map((group) => (
                    <CommandMenu.Group key={group.group} value={group.group}>
                        <CommandMenu.GroupHeading>{group.group}</CommandMenu.GroupHeading>
                        {group.items.map((item, index) => (
                            <CommandMenu.Item key={index} value={item.value}>
                                <div className={`w-5 h-5 rounded-md ${item.color} flex items-center justify-center text-white`}>
                                    <i className={`pi ${item.icon} text-xs font-bold`}></i>
                                </div>
                                <span>{item.label}</span>
                                <span className="opacity-50 ml-auto">{item.category}</span>
                            </CommandMenu.Item>
                        ))}
                    </CommandMenu.Group>
                ))}
                <CommandMenu.Item value="test">Test</CommandMenu.Item>
            </CommandMenu.List>
        </CommandMenu>
    );
}

const commands = [
    {
        group: 'recents',
        items: [
            {
                icon: 'pi-refresh',
                label: 'Check For Updates',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(245,83,84),rgb(235,70,70))]',
                value: 'check for updates',
                keywords: ['check', 'updates']
            },
            {
                icon: 'pi-cog',
                label: 'Open Settings',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(96,165,250),rgb(59,130,246))]',
                value: 'open settings'
            },
            {
                icon: 'pi-search',
                label: 'Search Files',
                category: 'Command',
                color: 'bg-[linear-gradient(rgb(167,139,250),rgb(139,92,246))]',
                value: 'search files'
            },
            {
                icon: 'pi-terminal',
                label: 'Open Terminal',
                category: 'View',
                color: 'bg-[linear-gradient(rgb(148,163,184),rgb(100,116,139))]',
                value: 'open terminal'
            },
            {
                icon: 'pi-history',
                label: 'View History',
                category: 'View',
                color: 'bg-[linear-gradient(rgb(192,132,252),rgb(168,85,247))]',
                value: 'view history',
                keywords: ['history', 'recent']
            },
            {
                icon: 'pi-comments',
                label: 'Open Chat',
                category: 'Communication',
                color: 'bg-[linear-gradient(rgb(34,211,238),rgb(6,182,212))]',
                value: 'open chat'
            }
        ]
    },
    ...cmds
];

Accessibility#

Screen Reader#

CommandMenu renders a combobox with an input (role="combobox") that controls a list of options (role="listbox"). Items use aria-selected to reflect the current selection and aria-disabled="true" when an item cannot be chosen. You can override the accessible name with aria-label or aria-labelledby on the root component.

Keyboard Support#

Key / ComboFunction
ArrowDown / ArrowUpMove to next / previous item
Alt + ArrowDown/UpJump by the configured jump amount (default 5)
Meta + ArrowDown/UpJump to the next / previous group
Home / EndMove to first / last item
EnterSelects the active item (ignored when disabled)