CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-rc-menu

React menu UI component library providing comprehensive menu components for interactive navigation systems

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

submenu-system.mddocs/

SubMenu System

The SubMenu system provides nested menu functionality with support for both popup and inline display modes, configurable triggers, animations, and comprehensive event handling for complex menu hierarchies.

Capabilities

SubMenu Component

Nested menu component supporting both popup and inline modes with extensive customization options.

/**
 * Nested menu component with popup and inline support
 * @param props - SubMenu configuration props
 * @returns React component
 */
declare const SubMenu: React.ForwardRefExoticComponent<SubMenuProps & React.RefAttributes<HTMLLIElement>>;

interface SubMenuProps {
  // Content
  title?: React.ReactNode;
  children?: React.ReactNode;
  
  // State
  disabled?: boolean;
  
  // Popup Configuration
  popupClassName?: string;
  popupStyle?: React.CSSProperties;
  popupOffset?: number[];
  overflowedIndicator?: React.ReactNode;
  
  // Icons
  itemIcon?: React.ReactNode | ((props: any) => React.ReactNode);
  expandIcon?: React.ReactNode | ((props: any) => React.ReactNode);
  
  // Event Handlers
  onTitleClick?: (info: { key: string; domEvent: React.MouseEvent | React.KeyboardEvent }) => void;
  onTitleMouseEnter?: (info: { key: string; domEvent: React.MouseEvent }) => void;
  onTitleMouseLeave?: (info: { key: string; domEvent: React.MouseEvent }) => void;
}

Usage Examples:

import Menu, { SubMenu, MenuItem } from "rc-menu";

// Basic submenu
<Menu mode="vertical">
  <MenuItem key="1">Option 1</MenuItem>
  <SubMenu key="sub1" title="Sub Menu">
    <MenuItem key="2">Sub Option 1</MenuItem>
    <MenuItem key="3">Sub Option 2</MenuItem>
  </SubMenu>
</Menu>

// Submenu with custom icon
<SubMenu
  key="sub1"
  title="Settings"
  itemIcon={<SettingsIcon />}
  expandIcon={({ isOpen }) => isOpen ? <UpIcon /> : <DownIcon />}
>
  <MenuItem key="profile">Profile</MenuItem>
  <MenuItem key="preferences">Preferences</MenuItem>
</SubMenu>

// Submenu with popup styling
<SubMenu
  key="sub1"
  title="Advanced"
  popupClassName="custom-popup"
  popupStyle={{ borderRadius: '8px', boxShadow: '0 4px 12px rgba(0,0,0,0.1)' }}
  popupOffset={[0, 8]}
>
  <MenuItem key="advanced1">Advanced Option 1</MenuItem>
  <MenuItem key="advanced2">Advanced Option 2</MenuItem>
</SubMenu>

Display Modes

SubMenu behavior changes based on the parent Menu's mode property.

Inline Mode:

// SubMenus expand/collapse within the menu container
<Menu mode="inline" defaultOpenKeys={['sub1']}>
  <MenuItem key="1">Item 1</MenuItem>
  <SubMenu key="sub1" title="Inline SubMenu">
    <MenuItem key="2">Sub Item 1</MenuItem>
    <MenuItem key="3">Sub Item 2</MenuItem>
    <SubMenu key="sub2" title="Nested SubMenu">
      <MenuItem key="4">Nested Item</MenuItem>
    </SubMenu>
  </SubMenu>
</Menu>

Vertical Mode:

// SubMenus appear as popups to the right
<Menu mode="vertical" triggerSubMenuAction="hover">
  <MenuItem key="1">Item 1</MenuItem>
  <SubMenu key="sub1" title="Vertical SubMenu">
    <MenuItem key="2">Popup Item 1</MenuItem>
    <MenuItem key="3">Popup Item 2</MenuItem>
  </SubMenu>
</Menu>

Horizontal Mode:

// SubMenus appear as dropdowns below
<Menu mode="horizontal" triggerSubMenuAction="hover">
  <MenuItem key="1">Home</MenuItem>
  <SubMenu key="sub1" title="Products">
    <MenuItem key="2">Product 1</MenuItem>
    <MenuItem key="3">Product 2</MenuItem>
  </SubMenu>
  <MenuItem key="4">About</MenuItem>
</Menu>

Trigger Configuration

Configure how submenus open and close using different trigger actions.

// Hover trigger (default for horizontal/vertical modes)
<Menu mode="vertical" triggerSubMenuAction="hover">
  <SubMenu key="sub1" title="Hover to Open">
    <MenuItem key="1">Item 1</MenuItem>
  </SubMenu>
</Menu>

// Click trigger
<Menu mode="vertical" triggerSubMenuAction="click">
  <SubMenu key="sub1" title="Click to Open">
    <MenuItem key="1">Item 1</MenuItem>
  </SubMenu>
</Menu>

// Custom delay timing
<Menu
  mode="vertical"
  triggerSubMenuAction="hover"
  subMenuOpenDelay={0.2}
  subMenuCloseDelay={0.3}
>
  <SubMenu key="sub1" title="Delayed Hover">
    <MenuItem key="1">Item 1</MenuItem>
  </SubMenu>
</Menu>

Event Handling

SubMenus provide detailed event handling for both the submenu container and title interactions.

const handleTitleClick = (info: { key: string; domEvent: React.MouseEvent | React.KeyboardEvent }) => {
  console.log('SubMenu title clicked:', info.key);
  console.log('DOM event:', info.domEvent);
};

const handleTitleHover = (info: { key: string; domEvent: React.MouseEvent }) => {
  console.log('SubMenu title hovered:', info.key);
};

const handleSubMenuHover = (info: { key: string; domEvent: React.MouseEvent }) => {
  console.log('SubMenu container hovered:', info.key);
};

<SubMenu
  key="sub1"
  title="Event SubMenu"
  onTitleClick={handleTitleClick}
  onTitleMouseEnter={handleTitleHover}
  onTitleMouseLeave={handleTitleHover}
  onMouseEnter={handleSubMenuHover}
  onMouseLeave={handleSubMenuHover}
>
  <MenuItem key="1">Item 1</MenuItem>
  <MenuItem key="2">Item 2</MenuItem>
</SubMenu>

Nested SubMenus

SubMenus can be nested to create multi-level menu hierarchies.

<Menu mode="inline" defaultOpenKeys={['sub1', 'sub1-1']}>
  <MenuItem key="1">Top Level Item</MenuItem>
  <SubMenu key="sub1" title="Level 1 SubMenu">
    <MenuItem key="2">Level 1 Item</MenuItem>
    <SubMenu key="sub1-1" title="Level 2 SubMenu">
      <MenuItem key="3">Level 2 Item</MenuItem>
      <SubMenu key="sub1-1-1" title="Level 3 SubMenu">
        <MenuItem key="4">Level 3 Item</MenuItem>
      </SubMenu>
    </SubMenu>
  </SubMenu>
</Menu>

Popup Positioning and Styling

Fine-tune popup appearance and positioning for non-inline modes.

// Custom popup container
const getPopupContainer = (node: HTMLElement) => {
  return document.getElementById('menu-container') || document.body;
};

// Custom placements for popup positioning
const customPlacements = {
  rightTop: {
    points: ['tl', 'tr'],
    overflow: { adjustX: 1, adjustY: 1 },
    offset: [4, 0],
  },
};

<Menu
  mode="vertical"
  getPopupContainer={getPopupContainer}
  builtinPlacements={customPlacements}
>
  <SubMenu
    key="sub1"
    title="Custom Positioned SubMenu"
    popupClassName="custom-submenu-popup"
    popupOffset={[8, 0]}
  >
    <MenuItem key="1">Custom Item 1</MenuItem>
    <MenuItem key="2">Custom Item 2</MenuItem>
  </SubMenu>
</Menu>

SubMenu State Management

Control SubMenu open/close states programmatically.

import { useState } from 'react';

const [openKeys, setOpenKeys] = useState<string[]>(['sub1']);

const handleOpenChange = (keys: string[]) => {
  // Keep only one submenu open at a time
  const latestOpenKey = keys.find(key => openKeys.indexOf(key) === -1);
  setOpenKeys(latestOpenKey ? [latestOpenKey] : []);
};

<Menu
  mode="inline"
  openKeys={openKeys}
  onOpenChange={handleOpenChange}
>
  <SubMenu key="sub1" title="SubMenu 1">
    <MenuItem key="1">Item 1</MenuItem>
  </SubMenu>
  <SubMenu key="sub2" title="SubMenu 2">
    <MenuItem key="2">Item 2</MenuItem>
  </SubMenu>
</Menu>

Overflow Handling

Handle overflow scenarios in horizontal menus with custom indicators.

<Menu mode="horizontal">
  <MenuItem key="1">Item 1</MenuItem>
  <MenuItem key="2">Item 2</MenuItem>
  <MenuItem key="3">Item 3</MenuItem>
  <SubMenu
    key="sub1"
    title="More Items"
    overflowedIndicator={<MoreIcon />}
  >
    <MenuItem key="4">Overflow Item 1</MenuItem>
    <MenuItem key="5">Overflow Item 2</MenuItem>
  </SubMenu>
</Menu>

Install with Tessl CLI

npx tessl i tessl/npm-rc-menu

docs

index.md

layout-components.md

menu-container.md

menu-items.md

submenu-system.md

tile.json