diff --git a/.changeset/giant-drinks-love.md b/.changeset/giant-drinks-love.md
deleted file mode 100644
index 7a4ac767..00000000
--- a/.changeset/giant-drinks-love.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@cube-dev/ui-kit": patch
----
-
-Add `tooltip` prop to menu items. You can pass a `string` or a `TooltipProps` object with `title` prop there for advanced customization.
diff --git a/.changeset/serious-meals-work.md b/.changeset/serious-meals-work.md
new file mode 100644
index 00000000..166fb144
--- /dev/null
+++ b/.changeset/serious-meals-work.md
@@ -0,0 +1,5 @@
+---
+"@cube-dev/ui-kit": minor
+---
+
+Add CommandMenu component.
diff --git a/.cursor/rules/guidelines.mdc b/.cursor/rules/guidelines.mdc
new file mode 100644
index 00000000..2b7a43f3
--- /dev/null
+++ b/.cursor/rules/guidelines.mdc
@@ -0,0 +1,287 @@
+---
+alwaysApply: true
+---
+
+# Description
+
+Package name: `@cube-dev/ui-kit`
+
+# Project Structure
+
+## Component file structure (preferable)
+
+/src/components/{category}/{ComponentName}/
+- {ComponentName}.tsx – implementation of the component
+- {ComponentName}.docs.mdx - documentation
+- {ComponentName}.stories.tsx - Storybook stories
+- {ComponentName}.test.tsx - Unit tests
+- index.tsx - re-export of all instances
+
+## Icons
+
+/src/icons/
+
+# Commands
+
+## Test
+
+All tests: `$ pnpm test`
+Specific test: `$ pnpm test -- {TestFileName}`
+
+## Build
+
+`pnpm run build`
+
+## Lint + Fix
+
+`pnpm run fix`
+
+# Stack
+
+- `tasty` style helper.
+ - `src/tasty` - sources
+ - `src/stories/Tasty.docs.mdx` - documentation
+ - `src/stories/Styles.docs.mdx` - custom tasty styles documentation
+ - `src/stories/CreateComponent.docs.mdx` - create components using tasty helper.
+- Storybook v8.6
+- React and React DOM v18
+- `styled-components` v6
+- `react-aria` and `react-stately` with the latest versions.
+- `tabler/icons-react` - icons.
+
+# Recomendations
+
+- Use `DOCUMENTATION_GUIDELINES.md` for writing documentation for components.
+- Use icons from `/src/icons` if they have a required one. If not - use `tabler/icons-react`. If we need to customize the size or color of the icon, then wrap it with `` component and pass all required props there. Do not add any props to the tabler icons directly.
+
+## Form System
+
+- Form validation uses async rule-based system with built-in validators:
+ - `required` - field is required
+ - `type` - validates data type (email, url, number, etc.)
+ - `pattern` - regex pattern validation
+ - `min`/`max` - length/value constraints
+ - `enum` - allowed values
+ - `whitespace` - non-empty content
+ - `validator` - custom async function
+- Form fields support direct integration without Field wrapper
+- Use `useForm` hook for form instance management
+- Form state includes validation, touched state, and error handling
+
+## Testing
+
+- Testing setup: Jest + React Testing Library + `@testing-library/react-hooks`
+- Test configuration: `src/test/setup.ts` with custom configurations
+- Testing utilities: `src/test/render.tsx` provides `renderWithRoot` wrapper
+- QA attributes: Use `qa` prop for e2e testing selectors (`data-qa`)
+- Test environment: Uses `jsdom` with React 18 act() environment
+- Coverage: Run `pnpm test-cover` for coverage reports
+
+## Accessibility
+
+- All components use React Aria hooks for accessibility
+- Keyboard navigation patterns are consistent across components
+- ARIA attributes are automatically managed by React Aria
+- Screen reader support is built-in with proper announcements
+- Focus management is handled automatically
+- Components support all standard ARIA labeling props
+
+## TypeScript
+
+- Interface naming: Use descriptive names with `Props` suffix for component props
+- Base props: Extend from `BaseProps` or `AllBaseProps` for standard properties
+- Form types: Use `FieldTypes` interface for form field type definitions
+- Style props: Use specific style prop interfaces (e.g., `ContainerStyleProps`)
+- Generic constraints: Use `extends` for type safety in form and field components
+
+## Component Architecture
+
+- Use `filterBaseProps` to separate design system props from DOM props
+- Export pattern: Use barrel exports with compound components (e.g., `Button.Group`)
+- Style system: Use `extractStyles` for separating style props from other props
+- Modifiers: Use `mods` prop for state-based styling
+- Sub-elements: Use `data-element` attribute for targeting specific parts in styles
+
+## Style System (Tasty)
+
+- Use `tasty` documentation
+- Use `tasty` custom styles with tasty syntax when possible.
+- Use `style` property only for dynamic styles and tokens (css custom properties).
+- Style categories: BASE, POSITION, BLOCK, COLOR, TEXT, DIMENSION, FLOW, CONTAINER, OUTER
+- Responsive values: Use arrays for breakpoint-based styling
+- Modifiers: Use object syntax for conditional styles
+- Sub-elements: Target inner elements using capitalized keys in styles
+- Style props: Direct style application without `styles` prop
+- CSS custom properties: Use `@token-name` syntax for design tokens
+- To declare a CSS animation use `styled-components` and then pass the animation name to the tasty styles.
+
+## Export Patterns
+
+- Compound components: Use `Object.assign` pattern for sub-components
+- Barrel exports: Each category has index.ts for re-exports
+- Main export: All components exported from `src/index.ts`
+- Type exports: Export component prop types for external use
+
+## Development Workflow
+
+- Branch naming: `[type/(task-name | scope)]` (e.g., `feat/button-group`)
+- Commit convention: `category: message` format
+- Changesets: Use `pnpm changeset` for version management
+- Code snippets: Use `jsx live=false` for documentation snippets
+- Storybook: Two modes - `stories` and `docs` for different outputs
+
+## Performance
+
+- Icon optimization: Reuse icon components, wrap with `` for customization
+- Style caching: Tasty system includes built-in style caching
+- Bundle size: Monitor with `pnpm size` command
+- Lazy loading: Use dynamic imports for large components
+
+## Error Handling
+
+- Form validation: Async error handling with Promise-based validation
+- Console suppression: Test setup includes act() warning suppression
+- Error boundaries: Use proper error boundaries in complex components
+- Validation state: Use `validationState` prop for field error states
+
+# Description
+
+Package name: `@cube-dev/ui-kit`
+
+# Project Structure
+
+## Component file structure (preferable)
+
+/src/components/{category}/{ComponentName}/
+- {ComponentName}.tsx – implementation of the component
+- {ComponentName}.docs.mdx - documentation
+- {ComponentName}.stories.tsx - Storybook stories
+- {ComponentName}.test.tsx - Unit tests
+- index.tsx - re-export of all instances
+
+## Icons
+
+/src/icons/
+
+# Commands
+
+## Test
+
+All tests: `$ pnpm test`
+Specific test: `$ pnpm test -- {TestFileName}`
+
+## Build
+
+`pnpm run build`
+
+## Lint + Fix
+
+`pnpm run fix`
+
+# Stack
+
+- `tasty` style helper.
+ - `src/tasty` - sources
+ - `src/stories/Tasty.docs.mdx` - documentation
+ - `src/stories/Styles.docs.mdx` - custom tasty styles documentation
+ - `src/stories/CreateComponent.docs.mdx` - create components using tasty helper.
+- Storybook v8.6
+- React and React DOM v18
+- `styled-components` v6
+- `react-aria` and `react-stately` with the latest versions.
+- `tabler/icons-react` - icons.
+
+# Recomendations
+
+- Use `DOCUMENTATION_GUIDELINES.md` for writing documentation for components.
+- Use icons from `/src/icons` if they have a required one. If not - use `tabler/icons-react`. If we need to customize the size or color of the icon, then wrap it with `` component and pass all required props there. Do not add any props to the tabler icons directly.
+
+## Form System
+
+- Form validation uses async rule-based system with built-in validators:
+ - `required` - field is required
+ - `type` - validates data type (email, url, number, etc.)
+ - `pattern` - regex pattern validation
+ - `min`/`max` - length/value constraints
+ - `enum` - allowed values
+ - `whitespace` - non-empty content
+ - `validator` - custom async function
+- Form fields support direct integration without Field wrapper
+- Use `useForm` hook for form instance management
+- Form state includes validation, touched state, and error handling
+
+## Testing
+
+- Testing setup: Jest + React Testing Library + `@testing-library/react-hooks`
+- Test configuration: `src/test/setup.ts` with custom configurations
+- Testing utilities: `src/test/render.tsx` provides `renderWithRoot` wrapper
+- QA attributes: Use `qa` prop for e2e testing selectors (`data-qa`)
+- Test environment: Uses `jsdom` with React 18 act() environment
+- Coverage: Run `pnpm test-cover` for coverage reports
+
+## Accessibility
+
+- All components use React Aria hooks for accessibility
+- Keyboard navigation patterns are consistent across components
+- ARIA attributes are automatically managed by React Aria
+- Screen reader support is built-in with proper announcements
+- Focus management is handled automatically
+- Components support all standard ARIA labeling props
+
+## TypeScript
+
+- Interface naming: Use descriptive names with `Props` suffix for component props
+- Base props: Extend from `BaseProps` or `AllBaseProps` for standard properties
+- Form types: Use `FieldTypes` interface for form field type definitions
+- Style props: Use specific style prop interfaces (e.g., `ContainerStyleProps`)
+- Generic constraints: Use `extends` for type safety in form and field components
+
+## Component Architecture
+
+- Use `filterBaseProps` to separate design system props from DOM props
+- Export pattern: Use barrel exports with compound components (e.g., `Button.Group`)
+- Style system: Use `extractStyles` for separating style props from other props
+- Modifiers: Use `mods` prop for state-based styling
+- Sub-elements: Use `data-element` attribute for targeting specific parts in styles
+
+## Style System (Tasty)
+
+- Use `tasty` documentation
+- Use `tasty` custom styles with tasty syntax when possible.
+- Use `style` property only for dynamic styles and tokens (css custom properties).
+- Style categories: BASE, POSITION, BLOCK, COLOR, TEXT, DIMENSION, FLOW, CONTAINER, OUTER
+- Responsive values: Use arrays for breakpoint-based styling
+- Modifiers: Use object syntax for conditional styles
+- Sub-elements: Target inner elements using capitalized keys in styles
+- Style props: Direct style application without `styles` prop
+- CSS custom properties: Use `@token-name` syntax for design tokens
+- To declare a CSS animation use `styled-components` and then pass the animation name to the tasty styles.
+
+## Export Patterns
+
+- Compound components: Use `Object.assign` pattern for sub-components
+- Barrel exports: Each category has index.ts for re-exports
+- Main export: All components exported from `src/index.ts`
+- Type exports: Export component prop types for external use
+
+## Development Workflow
+
+- Branch naming: `[type/(task-name | scope)]` (e.g., `feat/button-group`)
+- Commit convention: `category: message` format
+- Changesets: Use `pnpm changeset` for version management
+- Code snippets: Use `jsx live=false` for documentation snippets
+- Storybook: Two modes - `stories` and `docs` for different outputs
+
+## Performance
+
+- Icon optimization: Reuse icon components, wrap with `` for customization
+- Style caching: Tasty system includes built-in style caching
+- Bundle size: Monitor with `pnpm size` command
+- Lazy loading: Use dynamic imports for large components
+
+## Error Handling
+
+- Form validation: Async error handling with Promise-based validation
+- Console suppression: Test setup includes act() warning suppression
+- Error boundaries: Use proper error boundaries in complex components
+- Validation state: Use `validationState` prop for field error states
diff --git a/.junie/guidelines.md b/.junie/guidelines.md
new file mode 100644
index 00000000..a4b71bfa
--- /dev/null
+++ b/.junie/guidelines.md
@@ -0,0 +1,141 @@
+# Description
+
+Package name: `@cube-dev/ui-kit`
+
+# Project Structure
+
+## Component file structure (preferable)
+
+/src/components/{category}/{ComponentName}/
+- {ComponentName}.tsx – implementation of the component
+- {ComponentName}.docs.mdx - documentation
+- {ComponentName}.stories.tsx - Storybook stories
+- {ComponentName}.test.tsx - Unit tests
+- index.tsx - re-export of all instances
+
+## Icons
+
+/src/icons/
+
+# Commands
+
+## Test
+
+All tests: `$ pnpm test`
+Specific test: `$ pnpm test -- {TestFileName}`
+
+## Build
+
+`pnpm run build`
+
+## Lint + Fix
+
+`pnpm run fix`
+
+# Stack
+
+- `tasty` style helper.
+ - `src/tasty` - sources
+ - `src/stories/Tasty.docs.mdx` - documentation
+ - `src/stories/Styles.docs.mdx` - custom tasty styles documentation
+ - `src/stories/CreateComponent.docs.mdx` - create components using tasty helper.
+- Storybook v8.6
+- React and React DOM v18
+- `styled-components` v6
+- `react-aria` and `react-stately` with the latest versions.
+- `tabler/icons-react` - icons.
+
+# Recomendations
+
+- Use `DOCUMENTATION_GUIDELINES.md` for writing documentation for components.
+- Use icons from `/src/icons` if they have a required one. If not - use `tabler/icons-react`. If we need to customize the size or color of the icon, then wrap it with `` component and pass all required props there. Do not add any props to the tabler icons directly.
+
+## Form System
+
+- Form validation uses async rule-based system with built-in validators:
+ - `required` - field is required
+ - `type` - validates data type (email, url, number, etc.)
+ - `pattern` - regex pattern validation
+ - `min`/`max` - length/value constraints
+ - `enum` - allowed values
+ - `whitespace` - non-empty content
+ - `validator` - custom async function
+- Form fields support direct integration without Field wrapper
+- Use `useForm` hook for form instance management
+- Form state includes validation, touched state, and error handling
+
+## Testing
+
+- Testing setup: Jest + React Testing Library + `@testing-library/react-hooks`
+- Test configuration: `src/test/setup.ts` with custom configurations
+- Testing utilities: `src/test/render.tsx` provides `renderWithRoot` wrapper
+- QA attributes: Use `qa` prop for e2e testing selectors (`data-qa`)
+- Test environment: Uses `jsdom` with React 18 act() environment
+- Coverage: Run `pnpm test-cover` for coverage reports
+
+## Accessibility
+
+- All components use React Aria hooks for accessibility
+- Keyboard navigation patterns are consistent across components
+- ARIA attributes are automatically managed by React Aria
+- Screen reader support is built-in with proper announcements
+- Focus management is handled automatically
+- Components support all standard ARIA labeling props
+
+## TypeScript
+
+- Interface naming: Use descriptive names with `Props` suffix for component props
+- Base props: Extend from `BaseProps` or `AllBaseProps` for standard properties
+- Form types: Use `FieldTypes` interface for form field type definitions
+- Style props: Use specific style prop interfaces (e.g., `ContainerStyleProps`)
+- Generic constraints: Use `extends` for type safety in form and field components
+
+## Component Architecture
+
+- Use `filterBaseProps` to separate design system props from DOM props
+- Export pattern: Use barrel exports with compound components (e.g., `Button.Group`)
+- Style system: Use `extractStyles` for separating style props from other props
+- Modifiers: Use `mods` prop for state-based styling
+- Sub-elements: Use `data-element` attribute for targeting specific parts in styles
+
+## Style System (Tasty)
+
+- Use `tasty` documentation
+- Use `tasty` custom styles with tasty syntax when possible.
+- Use `style` property only for dynamic styles and tokens (css custom properties).
+- Style categories: BASE, POSITION, BLOCK, COLOR, TEXT, DIMENSION, FLOW, CONTAINER, OUTER
+- Responsive values: Use arrays for breakpoint-based styling
+- Modifiers: Use object syntax for conditional styles
+- Sub-elements: Target inner elements using capitalized keys in styles
+- Style props: Direct style application without `styles` prop
+- CSS custom properties: Use `@token-name` syntax for design tokens
+- To declare a CSS animation use `styled-components` and then pass the animation name to the tasty styles.
+
+## Export Patterns
+
+- Compound components: Use `Object.assign` pattern for sub-components
+- Barrel exports: Each category has index.ts for re-exports
+- Main export: All components exported from `src/index.ts`
+- Type exports: Export component prop types for external use
+
+## Development Workflow
+
+- Branch naming: `[type/(task-name | scope)]` (e.g., `feat/button-group`)
+- Commit convention: `category: message` format
+- Changesets: Use `pnpm changeset` for version management
+- Code snippets: Use `jsx live=false` for documentation snippets
+- Storybook: Two modes - `stories` and `docs` for different outputs
+
+## Performance
+
+- Icon optimization: Reuse icon components, wrap with `` for customization
+- Style caching: Tasty system includes built-in style caching
+- Bundle size: Monitor with `pnpm size` command
+- Lazy loading: Use dynamic imports for large components
+
+## Error Handling
+
+- Form validation: Async error handling with Promise-based validation
+- Console suppression: Test setup includes act() warning suppression
+- Error boundaries: Use proper error boundaries in complex components
+- Validation state: Use `validationState` prop for field error states
diff --git a/src/components/actions/CommandMenu/CommandMenu.docs.mdx b/src/components/actions/CommandMenu/CommandMenu.docs.mdx
new file mode 100644
index 00000000..ceb6c5f3
--- /dev/null
+++ b/src/components/actions/CommandMenu/CommandMenu.docs.mdx
@@ -0,0 +1,357 @@
+import { Meta, Story, Controls } from '@storybook/blocks';
+import { CommandMenu } from './CommandMenu';
+import * as CommandMenuStories from './CommandMenu.stories';
+
+
+
+# CommandMenu
+
+A searchable menu interface that combines the functionality of Menu and ListBox components. It provides a command-line-like experience for users to quickly find and execute actions through a searchable interface.
+
+## When to use
+
+- **Quick action access**: Enable users to quickly find and execute commands or actions
+- **Large command sets**: When you have many available actions that benefit from search filtering
+- **Keyboard-first workflows**: For power users who prefer keyboard navigation
+- **Command-line interfaces**: When building developer tools or admin interfaces
+- **Global search**: As a global command palette accessible via keyboard shortcuts
+
+## Examples
+
+### Default Usage
+
+
+
+## Props
+
+
+
+## Styling
+
+### Style Props
+
+The CommandMenu component supports all standard style properties:
+
+- **Layout**: `width`, `height`, `padding`, `margin`
+- **Positioning**: `position`, `top`, `left`, `right`, `bottom`
+- **Flexbox**: `flex`, `alignSelf`, `justifySelf`
+- **Grid**: `gridArea`, `gridColumn`, `gridRow`
+- **Spacing**: `gap`, `rowGap`, `columnGap`
+- **Sizing**: `minWidth`, `maxWidth`, `minHeight`, `maxHeight`
+
+### Sub-elements
+
+The CommandMenu component has several sub-elements that can be styled:
+
+- `SearchWrapper` - Container for the search input area
+- `SearchInput` - The search input field specifically
+- `SearchIcon` - The search/loading icon
+- `LoadingWrapper` - Container for loading state
+- `EmptyState` - Container for empty state message
+- `MenuWrapper` - Container for the menu content
+
+#### searchInputStyles
+
+Customizes the search input field specifically.
+
+### Modifiers
+
+The CommandMenu component supports the following modifiers:
+
+| Modifier | Type | Description |
+|----------|------|-------------|
+| loading | `boolean` | Whether the command palette is in loading state |
+
+## Accessibility
+
+### Keyboard Navigation
+
+The CommandMenu component provides comprehensive keyboard support:
+
+- **Search Input Focus**: The search input is automatically focused when the palette opens
+- **Arrow Keys**: Navigate through filtered options while keeping search input focused
+- **Enter**: Select the currently highlighted option
+- **Escape**: Clear search term or close the palette
+- **Tab**: Navigate between focusable elements
+
+### Screen Reader Support
+
+- Proper ARIA roles and labels for search and menu functionality
+- Live region announcements for state changes
+- Support for `aria-activedescendant` for virtual focus
+- Descriptive labels for loading and empty states
+
+### Focus Management
+
+- Search input maintains focus during keyboard navigation
+- Virtual focus pattern for menu items
+- Proper focus restoration when closing
+
+## Usage Patterns
+
+### Basic Usage
+
+```jsx
+
+ Copy
+ Paste
+ Cut
+
+```
+
+### With MenuTrigger
+
+```jsx
+
+
+
+ Copy
+ Paste
+
+
+```
+
+### With Sections and Keywords
+
+```jsx
+
+
+
+ Copy
+
+
+ Paste
+
+
+
+
+ Zoom In
+
+
+
+```
+
+### Controlled Search
+
+```jsx
+const [searchValue, setSearchValue] = useState('');
+
+
+ Action 1
+ Action 2
+
+```
+
+### With Loading State
+
+```jsx
+
+ {commands.map(command => (
+
+ {command.name}
+
+ ))}
+
+```
+
+### Custom Filtering
+
+```jsx
+ {
+ // Custom fuzzy search logic
+ return textValue.toLowerCase().includes(inputValue.toLowerCase());
+ }}
+ searchPlaceholder="Fuzzy search..."
+>
+ Action 1
+ Action 2
+
+```
+
+### Force Mount Items
+
+```jsx
+
+
+ Help (always visible)
+
+ Copy
+ Paste
+
+```
+
+### With Selection
+
+```jsx
+const [selectedKeys, setSelectedKeys] = useState(['copy']);
+
+
+ Copy
+ Paste
+ Cut
+
+```
+
+### Multiple Selection
+
+```jsx
+const [selectedKeys, setSelectedKeys] = useState(['copy', 'paste']);
+
+
+ Copy
+ Paste
+ Cut
+
+```
+
+### With DialogTrigger
+
+Use CommandMenu inside a Dialog with DialogTrigger for modal command palette functionality:
+
+```jsx
+
+
+
+
+```
+
+### With useDialogContainer Hook
+
+For programmatic control over the command menu dialog:
+
+```jsx
+import { useDialogContainer } from '@cube-dev/ui-kit';
+
+function CommandMenuDialogContent({ onClose, ...args }) {
+ const handleAction = (key) => {
+ console.log('Action selected:', key);
+ onClose();
+ };
+
+ return (
+
+ );
+}
+
+function App() {
+ const dialog = useDialogContainer(CommandMenuDialogContent);
+
+ const handleOpenDialog = () => {
+ dialog.open({
+ searchPlaceholder: 'Search commands...',
+ autoFocus: true,
+ onClose: dialog.close,
+ });
+ };
+
+ return (
+
+
+ {dialog.rendered}
+
+ );
+}
+```
+
+## Advanced Features
+
+### Enhanced Search
+
+The CommandMenu supports enhanced search capabilities:
+
+- **Keywords**: Items can include additional keywords for better discoverability
+- **Custom values**: Items can have custom search values separate from display text
+- **Force mount**: Certain items can always be visible regardless of search filter
+- **Custom filtering**: Override the default search algorithm with custom logic
+
+## Best Practices
+
+### Do's
+
+- **Provide clear placeholders**: Use descriptive placeholder text that indicates what users can search for
+- **Use keywords**: Add relevant keywords to items for better discoverability
+- **Group related commands**: Use sections to organize commands logically
+- **Handle loading states**: Show loading indicators for async operations
+- **Provide keyboard shortcuts**: Include hotkey hints in menu items when applicable
+
+### Don'ts
+
+- **Don't overload with options**: Too many commands can overwhelm users even with search
+- **Don't use for simple menus**: Use regular Menu component for small, static option sets
+- **Don't ignore empty states**: Always provide helpful empty state messages
+- **Don't disable search**: The search functionality is core to the component's purpose
+
+## Related Components
+
+- [Menu](/docs/actions-menu--docs) - For static menu options without search
+- [ListBox](/docs/forms-listbox--docs) - For searchable selection lists
+- [Dialog](/docs/overlays-dialog--docs) - For modal command palette usage
+- [MenuTrigger](/docs/actions-menu--docs) - For trigger-based command palette usage
+
+## Technical Notes
+
+### Performance
+
+- The component uses efficient filtering with React Stately's collection system
+- Search filtering is debounced to prevent excessive re-renders
+- Virtual focus is used to maintain performance with large option sets
+
+### Accessibility Compliance
+
+- Meets WCAG 2.1 AA standards for keyboard navigation
+- Supports screen readers with proper ARIA attributes
+- Implements virtual focus pattern for optimal accessibility
+
+### Browser Support
+
+- Modern browsers with ES2018+ support
+- Requires React 18+ for concurrent features
+- Uses React Aria for cross-browser accessibility
diff --git a/src/components/actions/CommandMenu/CommandMenu.spec.md b/src/components/actions/CommandMenu/CommandMenu.spec.md
new file mode 100644
index 00000000..9f91bace
--- /dev/null
+++ b/src/components/actions/CommandMenu/CommandMenu.spec.md
@@ -0,0 +1,278 @@
+# CommandMenu Component Specification
+
+## Overview
+
+The CommandMenu component is a searchable menu interface that combines the functionality of Menu and ListBox components. It provides a command-line-like experience for users to quickly find and execute actions through a searchable interface.
+
+## Component Features
+
+### Core Functionality
+- **Search-first interface**: Always includes a search input at the top for filtering options
+- **Flexible usage**: Can be used standalone or within a popover/modal
+- **Multiple trigger methods**: Can be opened via MenuTrigger or programmatically like a Dialog
+- **Virtual focus**: Uses virtual focus for keyboard navigation while keeping search input focused
+- **Header/Footer support**: Configurable header and footer sections
+- **Accessibility**: Full keyboard navigation and screen reader support
+- **Loading states**: Built-in loading indicator and state management
+- **Force mount items**: Always render certain items regardless of search filter
+- **Enhanced search**: Keywords-based matching and custom value support
+
+### Key Behaviors
+- When CommandMenu gains focus, the search input is automatically focused
+- Arrow keys navigate through filtered options while search input retains focus
+- Enter key selects the currently highlighted option
+- Escape key clears search or closes the palette
+- Supports both single and multiple selection modes
+- Real-time filtering as user types
+
+- **Loading state**: Shows loading indicator while async operations are in progress
+- **Force mount**: Certain items always visible regardless of search filter
+- **Keywords matching**: Items can be found by additional keywords beyond display text
+
+## Required Files
+
+### Core Component Files
+1. **CommandMenu.tsx** - Main component implementation
+2. **styled.tsx** - Styled components using tasty
+3. **index.ts** - Export barrel (includes CommandMenu.Trigger alias)
+
+### Documentation & Testing
+4. **CommandMenu.docs.mdx** - Component documentation
+5. **CommandMenu.stories.tsx** - Storybook stories
+6. **CommandMenu.test.tsx** - Unit tests (10-15 comprehensive tests)
+
+### Integration Files
+7. **Update src/components/actions/index.ts** - Export new components
+8. **Update src/index.ts** - Export new components
+
+## Implementation Approach
+
+The CommandMenu will **reuse the existing Menu component** and add search functionality on top. This approach ensures we inherit all Menu features (sections, descriptions, tooltips, hotkeys) while adding search-specific capabilities. The implementation will follow the React Aria command palette example pattern, wrapping Menu with search input and filtering logic.
+
+### Key Technical Insights
+
+1. **Reuse Menu component**: CommandMenu will wrap the existing Menu component to inherit all features (sections, descriptions, tooltips, hotkeys)
+2. **Filter-based search**: Use React Stately's `filter` prop (like ListBox) to implement search functionality
+3. **Virtual focus pattern**: Follow ListBox's search pattern - search input stays focused while arrow keys navigate menu items
+4. **Reuse existing patterns**: Use `useDialogContainer(CommandMenu)` for programmatic usage - no need for a separate hook
+
+## Implementation Plan
+
+### Phase 1: Core Component Structure (CommandMenu.tsx)
+1. **Setup component interface**
+ - Extend Menu props with search-specific additions
+ - Add `searchPlaceholder`, `emptyLabel`, `filter` props
+ - Add `searchInputStyles` for search input styling
+ - Add advanced features: `isLoading`, `shouldFilter`
+ - Support enhanced item structure with `keywords`, `value`, `forceMount`
+ - Reuse all existing Menu props (header, footer, itemStyles, etc.)
+
+2. **Implement search wrapper around Menu**
+ - Create search input similar to ListBox's searchable mode
+ - Implement filtering logic using React Stately's filter capability
+ - Add keywords-based search matching for enhanced findability
+ - Support force mount items that always appear regardless of filter
+ - Handle manual filtering mode (`shouldFilter={false}`)
+ - Pass filtered collection to Menu component
+ - Handle search state management
+
+3. **Setup keyboard navigation**
+ - Follow ListBox pattern for virtual focus
+ - Keep search input focused while navigating options
+ - Handle Enter/Space for selection, Escape for clearing/closing
+
+ - Use `shouldUseVirtualFocus` for proper accessibility
+
+4. **Render structure**
+ - Header section (optional, from Menu)
+ - Search input (always present)
+ - Loading indicator (when `isLoading={true}`)
+ - Menu component with filtered items
+ - Footer section (optional, from Menu)
+ - Empty state when no results
+
+### Phase 2: MenuTrigger Integration and Alias
+1. **Create CommandMenu.Trigger alias**
+ - Export MenuTrigger as CommandMenu.Trigger in index.ts
+ - Ensure CommandMenu works seamlessly with MenuTrigger
+ - Test compatibility with existing MenuTrigger features
+
+2. **Update documentation**
+ - Show usage with MenuTrigger
+ - Demonstrate the alias usage pattern
+ - Provide examples of both approaches
+
+### Phase 3: Styling (styled.tsx)
+1. **Create styled components using tasty**
+ - CommandMenuWrapper: Main container
+ - SearchSection: Search input area
+ - LoadingSection: Loading indicator area
+ - ContentSection: Options list area
+ - HeaderSection: Optional header
+ - FooterSection: Optional footer
+ - EmptyState: No results message
+
+2. **Implement responsive design**
+ - Mobile-friendly layout
+ - Proper spacing and typography
+ - Theme integration
+
+### Phase 4: Documentation (CommandMenu.docs.mdx)
+1. **Follow documentation guidelines**
+ - Component overview and when to use
+ - Complete props documentation
+ - Accessibility section with keyboard shortcuts
+ - Best practices and examples
+ - Integration patterns
+
+2. **Include comprehensive examples**
+ - Basic usage
+ - With header/footer
+ - Programmatic usage with `useDialogContainer(CommandMenu)`
+ - With MenuTrigger (using CommandMenu.Trigger alias)
+ - Custom filtering and keywords
+ - Multiple selection
+ - Loading states
+ - Force mount items
+
+### Phase 5: Stories (CommandMenu.stories.tsx)
+1. **Create comprehensive stories**
+ - Default usage
+ - With header and footer
+ - Programmatic usage with `useDialogContainer(CommandMenu)`
+ - With MenuTrigger (CommandMenu.Trigger)
+ - Custom filtering and keywords
+ - Loading states
+ - Empty states
+ - Force mount items
+ - Complex example with multiple sections
+
+2. **Add play functions**
+ - Auto-open for trigger-based stories
+ - Demonstrate keyboard navigation
+ - Show filtering behavior
+
+### Phase 6: Testing (CommandMenu.test.tsx)
+1. **Functional tests (10-15 tests)**
+ - Basic rendering and props
+ - Search functionality and filtering
+ - Keywords-based search matching
+ - Keyboard navigation (arrow keys, enter, escape)
+ - Selection handling (single/multiple)
+ - Header/footer rendering
+ - Empty state display
+ - Loading state display
+ - Force mount items behavior
+ - Accessibility attributes
+ - Focus management
+ - MenuTrigger integration
+ - Programmatic usage with `useDialogContainer`
+ - Custom filtering (`shouldFilter={false}`)
+ - Disabled states
+ - Event handlers
+
+2. **Accessibility tests**
+ - ARIA attributes
+ - Keyboard navigation
+ - Screen reader compatibility
+ - Focus management
+
+## Technical Specifications
+
+### Props Interface
+```typescript
+interface CommandMenuProps extends CubeMenuProps {
+ // Search-specific props
+ searchPlaceholder?: string;
+ searchValue?: string;
+ onSearchChange?: (value: string) => void;
+ filter?: (textValue: string, inputValue: string) => boolean;
+ emptyLabel?: ReactNode;
+ searchInputStyles?: Styles;
+
+ // Advanced search features
+ isLoading?: boolean;
+ shouldFilter?: boolean;
+
+ // Inherited from Menu: all Menu props are supported
+ // - header, footer (content props)
+ // - styles, itemStyles, sectionStyles, sectionHeadingStyles (styling)
+ // - selectionIcon, shouldFocusWrap, autoFocus (behavior)
+ // - onAction, onSelectionChange (handlers)
+ // - All React Aria menu props (isDisabled, disabledKeys, etc.)
+}
+
+interface CommandMenuItem {
+ // Standard item props
+ id: string;
+ textValue: string;
+
+ // Enhanced search features
+ keywords?: string[];
+ value?: string;
+ forceMount?: boolean;
+
+ // Standard Menu item props
+ // ... (all existing Menu item props)
+}
+```
+
+### React Aria Hooks Usage
+- **Reused from Menu**: `useTreeState`, `useMenu` (via Menu component)
+- **Search-specific**: `useFilter` - For search filtering functionality
+- **Navigation**: `useKeyboard` - For search input keyboard navigation
+- **Trigger-based**: `useMenuTrigger`, `useMenuTriggerState` (via MenuTrigger)
+- **Positioning**: `useOverlayPosition` (via MenuTrigger/Dialog)
+
+### Accessibility Requirements
+- Full keyboard navigation support
+- Screen reader announcements for state changes
+- Proper ARIA labeling and relationships
+- Focus management with virtual focus
+- Support for aria-activedescendant
+- Proper role assignments
+
+### Performance Considerations
+- Efficient filtering with debouncing if needed
+- Virtual scrolling for large datasets (future enhancement)
+- Memoization of filtered results
+- Optimized re-renders
+
+## Integration Points
+
+### With Menu Component
+- **Direct reuse**: CommandMenu wraps Menu component completely
+- **Inherit all features**: Sections, descriptions, tooltips, hotkeys, selection icons
+- **Consistent API**: All Menu props work the same way
+- **Styling compatibility**: All Menu styling props are supported
+
+### With ListBox Component
+- **Search pattern**: Reuse ListBox's search input implementation and styling
+- **Filtering logic**: Share the same collection filtering approach
+- **Virtual focus**: Use the same keyboard navigation pattern
+
+### With Modal System
+- **MenuTrigger integration**: Works seamlessly with existing MenuTrigger
+- **Dialog integration**: Compatible with useDialogContainer pattern
+- **Focus management**: Leverages existing overlay focus management
+
+## Success Criteria
+
+1. **Functionality**: All core features work as specified
+2. **Accessibility**: Meets WCAG 2.1 AA standards
+3. **Performance**: Smooth interaction with large datasets
+4. **Documentation**: Complete and clear documentation
+5. **Testing**: All tests pass with good coverage
+6. **Integration**: Works seamlessly with existing components
+7. **Consistency**: Follows established patterns and conventions
+
+## Future Enhancements
+
+1. **Virtual scrolling** for large datasets
+2. **Nested command groups** with hierarchical navigation
+3. **Recent commands** history
+4. **useCommandState hook** for accessing internal state
+5. **Custom renderers** for complex command items
+6. **Async loading** with search suggestions
+7. **Command categories** with visual grouping
+8. **Fuzzy search** improvements
\ No newline at end of file
diff --git a/src/components/actions/CommandMenu/CommandMenu.stories.tsx b/src/components/actions/CommandMenu/CommandMenu.stories.tsx
new file mode 100644
index 00000000..ed1e5c96
--- /dev/null
+++ b/src/components/actions/CommandMenu/CommandMenu.stories.tsx
@@ -0,0 +1,848 @@
+import { expect, userEvent, waitFor, within } from '@storybook/test';
+import {
+ IconArrowBack,
+ IconArrowForward,
+ IconClipboard,
+ IconCopy,
+ IconCut,
+ IconDeviceFloppy,
+ IconFile,
+ IconFileText,
+ IconFolder,
+ IconSearch,
+ IconSelect,
+ IconSettings,
+} from '@tabler/icons-react';
+import React, { useState } from 'react';
+
+import {
+ Dialog,
+ DialogTrigger,
+ useDialogContainer,
+} from '../../overlays/Dialog';
+import { Button } from '../Button';
+import { Menu } from '../Menu/Menu';
+
+import { CommandMenu, CubeCommandMenuProps } from './CommandMenu';
+
+import type { StoryFn } from '@storybook/react';
+
+export default {
+ title: 'Actions/CommandMenu',
+ component: CommandMenu,
+ parameters: {
+ docs: {
+ description: {
+ component:
+ 'A searchable menu interface that provides a command-line-like experience for users to quickly find and execute actions.',
+ },
+ },
+ },
+ argTypes: {
+ /* Search */
+ searchPlaceholder: {
+ control: 'text',
+ description: 'Placeholder text for the search input',
+ table: {
+ defaultValue: { summary: 'Search commands...' },
+ },
+ },
+ searchValue: {
+ control: 'text',
+ description: 'The search value in controlled mode',
+ },
+ onSearchChange: {
+ action: 'searchChanged',
+ description: 'Callback fired when search value changes',
+ },
+ filter: {
+ description: 'Custom filter function for search',
+ },
+ emptyLabel: {
+ control: 'text',
+ description: 'Label to show when no results are found',
+ table: {
+ defaultValue: { summary: 'No commands found' },
+ },
+ },
+ searchInputStyles: {
+ description: 'Custom styles for the search input',
+ },
+
+ /* Advanced Features */
+ isLoading: {
+ control: 'boolean',
+ description: 'Whether the command palette is loading',
+ table: {
+ defaultValue: { summary: 'false' },
+ },
+ },
+ shouldFilter: {
+ control: 'boolean',
+ description: 'Whether to filter items based on search',
+ table: {
+ defaultValue: { summary: 'true' },
+ },
+ },
+ autoFocus: {
+ control: 'boolean',
+ description: 'Whether to auto-focus the search input',
+ table: {
+ defaultValue: { summary: 'true' },
+ },
+ },
+
+ /* Menu Props */
+ onAction: {
+ action: 'action',
+ description: 'Callback fired when an item is selected',
+ },
+ onSelectionChange: {
+ action: 'selectionChange',
+ description: 'Callback fired when selection changes',
+ },
+ selectionMode: {
+ control: 'select',
+ options: ['none', 'single', 'multiple'],
+ description: 'Selection mode for the command palette',
+ table: {
+ defaultValue: { summary: 'none' },
+ },
+ },
+ isDisabled: {
+ control: 'boolean',
+ description: 'Whether the command palette is disabled',
+ },
+
+ /* Styling */
+ size: {
+ options: ['small', 'medium'],
+ control: { type: 'radio' },
+ description: 'Size of the select component',
+ table: {
+ type: { summary: 'string' },
+ defaultValue: { summary: 'small' },
+ },
+ },
+ styles: {
+ description: 'Custom styles for the command palette container',
+ },
+ },
+};
+
+const basicCommands = [
+ {
+ key: 'copy',
+ label: 'Copy',
+ description: 'Copy selected text',
+ hotkeys: 'Ctrl+C',
+ icon: ,
+ },
+ {
+ key: 'paste',
+ label: 'Paste',
+ description: 'Paste from clipboard',
+ hotkeys: 'Ctrl+V',
+ icon: ,
+ },
+ {
+ key: 'cut',
+ label: 'Cut',
+ description: 'Cut selected text',
+ hotkeys: 'Ctrl+X',
+ icon: ,
+ },
+ {
+ key: 'undo',
+ label: 'Undo',
+ description: 'Undo last action',
+ hotkeys: 'Ctrl+Z',
+ icon: ,
+ },
+ {
+ key: 'redo',
+ label: 'Redo',
+ description: 'Redo last action',
+ hotkeys: 'Ctrl+Y',
+ icon: ,
+ },
+ {
+ key: 'select-all',
+ label: 'Select All',
+ description: 'Select all text',
+ hotkeys: 'Ctrl+A',
+ icon: ,
+ },
+];
+
+const extendedCommands = [
+ // File operations
+ {
+ key: 'new-file',
+ label: 'New File',
+ description: 'Create a new file',
+ section: 'File',
+ hotkeys: 'Ctrl+N',
+ },
+ {
+ key: 'open-file',
+ label: 'Open File',
+ description: 'Open an existing file',
+ section: 'File',
+ hotkeys: 'Ctrl+O',
+ },
+ {
+ key: 'save-file',
+ label: 'Save File',
+ description: 'Save current file',
+ section: 'File',
+ hotkeys: 'Ctrl+S',
+ },
+ {
+ key: 'save-as',
+ label: 'Save As...',
+ description: 'Save file with new name',
+ section: 'File',
+ },
+
+ // Edit operations
+ {
+ key: 'copy',
+ label: 'Copy',
+ description: 'Copy selected text',
+ section: 'Edit',
+ hotkeys: 'Ctrl+C',
+ keywords: ['duplicate', 'clone'],
+ },
+ {
+ key: 'paste',
+ label: 'Paste',
+ description: 'Paste from clipboard',
+ section: 'Edit',
+ hotkeys: 'Ctrl+V',
+ keywords: ['insert'],
+ },
+ {
+ key: 'cut',
+ label: 'Cut',
+ description: 'Cut selected text',
+ section: 'Edit',
+ hotkeys: 'Ctrl+X',
+ },
+ {
+ key: 'find',
+ label: 'Find',
+ description: 'Search in document',
+ section: 'Edit',
+ hotkeys: 'Ctrl+F',
+ keywords: ['search', 'locate'],
+ },
+ {
+ key: 'replace',
+ label: 'Find and Replace',
+ description: 'Find and replace text',
+ section: 'Edit',
+ hotkeys: 'Ctrl+H',
+ },
+
+ // View operations
+ {
+ key: 'zoom-in',
+ label: 'Zoom In',
+ description: 'Increase zoom level',
+ section: 'View',
+ keywords: ['magnify', 'enlarge'],
+ },
+ {
+ key: 'zoom-out',
+ label: 'Zoom Out',
+ description: 'Decrease zoom level',
+ section: 'View',
+ keywords: ['shrink', 'reduce'],
+ },
+ {
+ key: 'full-screen',
+ label: 'Toggle Full Screen',
+ description: 'Enter or exit full screen',
+ section: 'View',
+ hotkeys: 'F11',
+ },
+ {
+ key: 'sidebar',
+ label: 'Toggle Sidebar',
+ description: 'Show or hide sidebar',
+ section: 'View',
+ },
+
+ // Help
+ {
+ key: 'help',
+ label: 'Help',
+ description: 'Open help documentation',
+ section: 'Help',
+ forceMount: true,
+ },
+ {
+ key: 'about',
+ label: 'About',
+ description: 'About this application',
+ section: 'Help',
+ forceMount: true,
+ },
+];
+
+export const Default: StoryFn> = (args) => (
+
+ {basicCommands.map((command) => (
+
+ {command.label}
+
+ ))}
+
+);
+
+Default.args = {
+ searchPlaceholder: 'Search commands...',
+ autoFocus: true,
+};
+
+export const WithSections: StoryFn> = (args) => {
+ const commandsBySection = extendedCommands.reduce(
+ (acc, command) => {
+ const section = command.section || 'Other';
+ if (!acc[section]) acc[section] = [];
+ acc[section].push(command);
+ return acc;
+ },
+ {} as Record,
+ );
+
+ return (
+
+ {Object.entries(commandsBySection).map(([sectionName, commands]) => (
+
+ {commands.map((command) => (
+
+ {command.label}
+
+ ))}
+
+ ))}
+
+ );
+};
+
+WithSections.args = {
+ searchPlaceholder: 'Search all commands...',
+ autoFocus: true,
+};
+
+export const WithMenuTrigger: StoryFn> = (args) => (
+
+
+
+ {basicCommands.map((command) => (
+
+ {command.label}
+
+ ))}
+
+
+);
+
+WithMenuTrigger.args = {
+ searchPlaceholder: 'Search commands...',
+ autoFocus: true,
+};
+
+WithMenuTrigger.play = async ({ canvasElement, viewMode }) => {
+ if (viewMode === 'docs') return;
+
+ const { findByRole, findByPlaceholderText, queryByPlaceholderText } =
+ within(canvasElement);
+
+ // Click the trigger button to open the command palette
+ await userEvent.click(await findByRole('button'));
+
+ // Wait for the command palette to appear and verify the search input is present
+ const searchInput = await findByPlaceholderText('Search commands...');
+
+ // Verify the search input is focused by checking if it's the active element
+ await waitFor(() => {
+ if (document.activeElement !== searchInput) {
+ throw new Error('Search input should be focused');
+ }
+ });
+
+ // // Test keyboard navigation and action triggering
+ // await userEvent.keyboard('{ArrowDown}'); // Navigate to first item
+ // await userEvent.keyboard('{Enter}'); // Trigger action
+
+ // // Verify the command palette closes after action
+ // await waitFor(() => {
+ // if (queryByPlaceholderText('Search commands...')) {
+ // throw new Error('Command palette should close after action');
+ // }
+ // });
+};
+
+export const ControlledSearch: StoryFn> = (args) => {
+ const [searchValue, setSearchValue] = useState('');
+
+ return (
+