cmd-plt
v0.0.2
Published
A command palette web component.
Downloads
217
Maintainers
Readme
cmd-plt
A lightweight, flexible command palette web component with nested navigation support.
Features
- Native web component (no framework)
- Keyboard navigation with arrow keys
- Built-in fuzzy filtering
- Nested item support with breadcrumb navigation
- Customizable filter function
- Lightweight and zero dependencies
Installation
npm install cmd-pltBasic Usage
<!DOCTYPE html>
<html>
<head>
<script type="module">
import { CmdPlt } from 'cmd-plt';
// Register the custom element
CmdPlt.define();
const cmdplt = document.querySelector('cmd-plt');
// Set up items
cmdplt.items = [
{ label: 'Profile', description: 'View your profile' },
{ label: 'Settings', description: 'Manage settings' },
{ label: 'Logout', description: 'Sign out of your account' }
];
// Handle selection
cmdplt.onSelect = (item, stack) => {
console.log('Selected:', item.label);
};
</script>
</head>
<body>
<cmd-plt></cmd-plt>
</body>
</html>Examples
Opening the Palette
By default, the command palette opens with Cmd+K:
You can also open it programmatically:
const cmdplt = document.querySelector('cmd-plt');
// Open with attribute
cmdplt.setAttribute('open', '');
// Or use the method
cmdplt.openDialog();
// Close it
cmdplt.closeDialog();Custom Keyboard Shortcut
Change the keyboard shortcut by setting the key attribute:
<cmd-plt key="p"></cmd-plt>Nested Items
Create hierarchical menus with nested children:
const cmdplt = document.querySelector('cmd-plt');
const sizes = [
{ label: 'small' },
{ label: 'medium' },
{ label: 'large' }
];
const colors = [
{ label: 'red', children: sizes },
{ label: 'blue', children: sizes },
{ label: 'green', children: sizes }
];
const items = [
{
label: 'T-shirt',
description: 'Classic cotton t-shirt',
children: colors
},
{
label: 'Hoodie',
description: 'Warm and comfortable',
children: colors
}
];
cmdplt.items = items;
cmdplt.onSelect = (item, stack) => {
// stack contains the full navigation path
const path = stack.map(s => s.item.label).join(' > ');
console.log('Selected:', path);
// "T-shirt > red > medium"
};Custom Filter Function
Provide your own filtering logic:
cmdplt.filter = (query, item, items) => {
const q = query.toLowerCase();
const label = item.label.toLowerCase();
// Prioritize items that start with the query
if (label.startsWith(q)) return true;
// Then check if it contains the query
return label.includes(q);
};Item-Specific Selection Handlers
Handle selection at the item level:
cmdplt.items = [
{
label: 'Delete',
description: 'Remove this item',
onSelect: (item, stack) => {
if (confirm('Are you sure?')) {
console.log('Item deleted');
}
}
},
{
label: 'Edit',
description: 'Modify this item',
onSelect: (item, stack) => {
console.log('Opening editor...');
}
}
];Complete Example
import { CmdPlt } from 'cmd-plt';
CmdPlt.define();
const cmdplt = document.querySelector('cmd-plt');
// Build a file browser-like structure
const files = [
{ label: 'document.txt', description: '2.3 KB' },
{ label: 'image.png', description: '1.5 MB' },
];
const folders = [
{
label: 'Documents',
description: '24 items',
children: files
},
{
label: 'Projects',
description: '12 items',
children: files
},
];
cmdplt.items = folders;
// Custom filter for better search
cmdplt.filter = (query, item) => {
const searchText = `${item.label} ${item.description || ''}`.toLowerCase();
return searchText.includes(query.toLowerCase());
};
// Handle final selection
cmdplt.onSelect = (item, stack) => {
const fullPath = stack.map(s => s.item.label).join('/');
console.log('Opening:', fullPath);
// Display the selection
document.getElementById('result').textContent = fullPath;
};Svelte Example
<script lang="ts">
import { CmdPlt, type Item, type StackItem } from "cmd-plt";
import { onMount } from "svelte";
CmdPlt.define();
let cmdplt: CmdPlt;
let selectedText = "No item selected";
const key = "k";
const animals: Item[] = [
{ label: "Cow", description: "A large herbivore." },
{ label: "Dog", description: "Your best friend." },
{ label: "Bird", description: "Feathered friend." },
];
onMount(() => {
cmdplt.items = animals;
cmdplt.onSelect = (item: Item) => {
console.log(item)
};
});
</script>
<div>
<cmd-plt bind:this={cmdplt} key={key}></cmd-plt>
</div>
<style>
cmd-plt {
--dialog-background: lightgreen;
}
</style>API Reference
Properties
| Property | Type | Description |
|----------|------|-------------|
| items | Item[] | Array of items to display in the palette |
| key | string | Keyboard key to open palette (default: 'k') |
| filter | Function | Custom filter function (query, item, items) => boolean |
| onSelect | Function | Callback when item is selected (item, stack) => void |
Methods
| Method | Description |
|--------|-------------|
| openDialog() | Opens the command palette |
| closeDialog() | Closes the command palette |
Styles
The component uses Shadow DOM with adopted stylesheets. You can customize the appearance by targeting the component's parts or using CSS custom properties in your own implementation.
cmd-plt {
--dialog-background: lightgreen;
--dialog-max-height: 800px;
}Full list of css variables.
--backdrop: rgba(0 0 0 / 0.4);
--dialog-background: #fff;
--dialog-width: 300px;
--dialog-max-height: calc(100vh - 200px);
--dialog-margin: 100px auto 0 auto;
--dialog-border: 0;
--dialog-box-shadow: 2px 2px 6px rgba(0 0 0 / 0.3);
--input-font-size: 22px;
--input-padding: 30px 10px;
--item-padding: 10px;