React Command Palette Implementation
A command palette is a powerful UI element that allows users to quickly access various actions and features within an application using keyboard shortcuts. This challenge asks you to build a basic command palette component in React using TypeScript, enabling users to trigger actions by typing commands. This is a common feature in many modern applications, improving user efficiency and discoverability.
Problem Description
You are tasked with creating a React component that implements a simple command palette. The component should:
- Display a Search Input: A text input field where the user can type commands.
- Display Command Suggestions: As the user types, display a list of suggested commands based on the input. These suggestions should be rendered as clickable items.
- Execute Commands: When a user selects a command (either by clicking a suggestion or pressing Enter), execute the corresponding action.
- Toggle Visibility: The command palette should be initially hidden. A keyboard shortcut (e.g., Ctrl/Cmd + K) should toggle the visibility of the palette.
- Clear Input: After a command is executed or a suggestion is selected, the input field should be cleared.
Key Requirements:
- The component must be written in TypeScript.
- The component should be reusable and configurable (e.g., allow passing in a list of commands and their corresponding actions).
- The component should handle keyboard input gracefully.
- The component should be visually appealing and user-friendly.
Expected Behavior:
- When the keyboard shortcut is pressed, the command palette should appear, and the input field should receive focus.
- As the user types, the list of suggestions should update dynamically, filtering the available commands.
- Clicking a suggestion or pressing Enter should execute the associated action and close the palette.
- If no matching suggestions are found, an empty state should be displayed.
- The palette should disappear when the keyboard shortcut is pressed again or when the user clicks outside the palette.
Edge Cases to Consider:
- Empty command list.
- No matching commands for the input.
- Keyboard shortcut conflicts with other application shortcuts.
- Handling of special characters in the input.
- Performance with a large number of commands.
Examples
Example 1:
Input: commands = [{ label: "New File", action: () => alert("Creating new file") }, { label: "Open File", action: () => alert("Opening file") }], shortcut = "Ctrl+K"
Output: A command palette appears when "Ctrl+K" is pressed, displaying "New File" and "Open File" as suggestions. Selecting "New File" triggers the alert "Creating new file" and closes the palette.
Explanation: The component correctly displays the commands and executes the associated action upon selection.
Example 2:
Input: commands = [{ label: "Settings", action: () => alert("Opening settings") }], shortcut = "Cmd+K"
Output: A command palette appears when "Cmd+K" is pressed, displaying "Settings" as a suggestion. Typing "set" filters the suggestions to only show "Settings". Selecting "Settings" triggers the alert "Opening settings" and closes the palette.
Explanation: The component correctly filters the commands based on the input and executes the action.
Example 3:
Input: commands = [], shortcut = "Ctrl+K"
Output: A command palette appears when "Ctrl+K" is pressed, but the suggestion list is empty.
Explanation: The component handles the edge case of an empty command list gracefully.
Constraints
- The component should be implemented using functional components and React hooks.
- The component should be reasonably performant, even with a command list of up to 100 items.
- The keyboard shortcut should be configurable via a prop.
- The component should not rely on external libraries for core functionality (styling is acceptable).
- The component should be able to handle asynchronous actions (though not required for the basic implementation).
Notes
- Consider using a state management solution (e.g.,
useState) to manage the visibility of the palette and the input value. - You can use a simple filtering algorithm to find matching commands.
- Focus on creating a clean and well-structured component.
- Styling is not the primary focus of this challenge, but a basic visual presentation is expected.
- Think about how to make the component extensible and configurable for different use cases.
- Consider using
useRefto manage focus on the input field.