npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@liaskos/command-palette

v1.0.1

Published

A beautiful, accessible command palette component for React applications - inspired by VS Code and Linear

Readme

@liaskos/command-palette

A beautiful, accessible command palette component for React applications, inspired by VS Code and Linear. Built with TypeScript and designed to match the v1 prototype exactly.

Features

  • 🎨 Beautiful Design - Clean, modern interface with HSL-based theming
  • ⌨️ Keyboard Navigation - Full keyboard support with arrow keys and shortcuts
  • 🔍 Fuzzy Search - Intelligent search with keyword matching
  • 🎯 Accessibility - ARIA compliant with screen reader support
  • 📱 Responsive - Works on all screen sizes
  • 🎪 Zero Dependencies - Only requires React and Lucide React icons
  • 🏗️ TypeScript - Fully typed with comprehensive interfaces
  • 🎭 Customizable - Flexible theming and configuration options

Installation

npm install @liaskos/command-palette
# or
yarn add @liaskos/command-palette
# or
pnpm add @liaskos/command-palette

Quick Start

import React, { useState } from 'react';
import { CommandPalette, CommandPaletteTrigger, useGlobalShortcuts } from '@liaskos/command-palette';
import { Home, Folder, CheckSquare, Users } from 'lucide-react';

const actions = [
  {
    id: 'home',
    label: 'Go to Home',
    description: 'Navigate to the home page',
    icon: Home,
    keywords: ['home', 'dashboard'],
    group: 'Navigation',
  },
  {
    id: 'projects',
    label: 'View Projects',
    description: 'See all your projects',
    icon: Folder,
    keywords: ['projects', 'work'],
    group: 'Navigation',
  },
  // ... more actions
];

function App() {
  const [open, setOpen] = useState(false);

  // Enable global keyboard shortcut (⌘K / Ctrl+K)
  useGlobalShortcuts(() => setOpen(true));

  const handleSelect = (action) => {
    console.log('Selected:', action);
    // Handle action selection
  };

  return (
    <div>
      {/* Trigger Button */}
      <CommandPaletteTrigger onClick={() => setOpen(true)} />

      {/* Command Palette */}
      <CommandPalette
        open={open}
        actions={actions}
        onSelect={handleSelect}
        onClose={() => setOpen(false)}
      />
    </div>
  );
}

Advanced Usage

Custom Actions

import { Plus, Calendar, Settings } from 'lucide-react';

const customActions = [
  {
    id: 'create-project',
    label: 'Create New Project',
    description: 'Start a new project',
    icon: Plus,
    keywords: ['create', 'new', 'project'],
    group: 'Quick Actions',
    shortcut: '⌘N',
    data: { type: 'project' },
  },
  {
    id: 'schedule-meeting',
    label: 'Schedule Meeting',
    description: 'Create a new meeting',
    icon: Calendar,
    keywords: ['meeting', 'calendar'],
    group: 'Quick Actions',
    disabled: false,
  },
];

Custom Styling

const customStyle = {
  maxWidth: '600px',
  backgroundColor: 'hsl(0 0% 3%)',
  color: 'hsl(0 0% 98%)',
};

<CommandPalette
  open={open}
  actions={actions}
  style={customStyle}
  maxHeight={400}
  placeholder="Search anything..."
  emptyMessage="No commands found."
  onSelect={handleSelect}
  onClose={() => setOpen(false)}
/>

Dynamic Actions

function DynamicCommandPalette() {
  const [actions, setActions] = useState(defaultActions);

  const handleSelect = (action) => {
    switch (action.id) {
      case 'create-project':
        // Add new project action dynamically
        setActions(prev => [...prev, {
          id: 'new-project-' + Date.now(),
          label: 'New Project',
          description: 'Recently created project',
          icon: Folder,
          group: 'Recent',
        }]);
        break;
      // ... handle other actions
    }
  };

  return (
    <CommandPalette
      open={open}
      actions={actions}
      onSelect={handleSelect}
      onClose={() => setOpen(false)}
    />
  );
}

API Reference

CommandPalette Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | open | boolean | false | Whether the command palette is open | | actions | CommandAction[] | [] | Array of actions to display | | placeholder | string | "Search projects, tasks..." | Placeholder text for search input | | emptyMessage | string | "No results found." | Message when no results | | onSelect | (action: CommandAction) => void | undefined | Callback when action is selected | | onClose | () => void | undefined | Callback when palette is closed | | style | React.CSSProperties | undefined | Custom styles | | className | string | undefined | CSS class name | | maxHeight | number | 320 | Maximum height of results area | | fuzzySearch | boolean | true | Enable fuzzy search | | searchDelay | number | 150 | Search debounce delay in ms |

CommandAction Interface

interface CommandAction {
  readonly id: string;                    // Unique identifier
  readonly label: string;                 // Display name
  readonly description?: string;          // Optional description
  readonly icon?: LucideIcon;            // Optional Lucide icon
  readonly keywords?: readonly string[]; // Search keywords
  readonly group?: string;               // Group category
  readonly shortcut?: string;            // Keyboard shortcut
  readonly disabled?: boolean;           // Whether action is disabled
  readonly data?: Record<string, any>;   // Custom data
}

Hooks

useGlobalShortcuts

Enables global keyboard shortcuts (⌘K / Ctrl+K) to open the command palette.

import { useGlobalShortcuts } from '@liaskos/command-palette';

function App() {
  const [open, setOpen] = useState(false);
  
  useGlobalShortcuts(() => setOpen(true));
  
  return (/* ... */);
}

useCommandPalette

Provides state management for the command palette.

import { useCommandPalette } from '@liaskos/command-palette';

const {
  open,
  query,
  selectedIndex,
  setQuery,
  setSelectedIndex,
  openPalette,
  closePalette,
  selectAction,
} = useCommandPalette(actions, onSelect, onClose);

useSearch

Handles search functionality with debouncing and fuzzy matching.

import { useSearch } from '@liaskos/command-palette';

const results = useSearch(actions, query, fuzzySearch, delay);

Keyboard Shortcuts

  • ⌘K / Ctrl+K - Open command palette
  • Escape - Close command palette
  • ↑/↓ Arrow Keys - Navigate through results
  • Enter - Select highlighted action

Theming

The component uses an HSL-based color system for consistent theming:

const customTheme = {
  colors: {
    background: 'hsl(0 0% 100%)',
    foreground: 'hsl(222.2 84% 4.9%)',
    muted: 'hsl(210 40% 96%)',
    mutedForeground: 'hsl(215.4 16.3% 46.9%)',
    border: 'hsl(214.3 31.8% 91.4%)',
    accent: 'hsl(210 40% 96%)',
    accentForeground: 'hsl(222.2 84% 4.9%)',
    overlay: 'hsla(0, 0%, 0%, 0.5)',
  },
  // ... more theme options
};

Examples

With React Router

import { useNavigate } from 'react-router-dom';

function App() {
  const navigate = useNavigate();
  
  const actions = [
    {
      id: 'dashboard',
      label: 'Dashboard',
      icon: Home,
      data: { route: '/dashboard' },
    },
    {
      id: 'projects',
      label: 'Projects',
      icon: Folder,
      data: { route: '/projects' },
    },
  ];

  const handleSelect = (action) => {
    if (action.data?.route) {
      navigate(action.data.route);
    }
  };

  return (
    <CommandPalette
      actions={actions}
      onSelect={handleSelect}
    />
  );
}

With Next.js

import { useRouter } from 'next/router';

function App() {
  const router = useRouter();
  
  const handleSelect = (action) => {
    if (action.data?.route) {
      router.push(action.data.route);
    }
  };

  return (
    <CommandPalette
      actions={actions}
      onSelect={handleSelect}
    />
  );
}

Browser Support

  • Chrome/Edge 88+
  • Firefox 85+
  • Safari 14+
  • iOS Safari 14+
  • Android Chrome 88+

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome! Please read our contributing guidelines and code of conduct.


May the force be with you - Alexandros Liaskos