0
# SubMenu System
1
2
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.
3
4
## Capabilities
5
6
### SubMenu Component
7
8
Nested menu component supporting both popup and inline modes with extensive customization options.
9
10
```typescript { .api }
11
/**
12
* Nested menu component with popup and inline support
13
* @param props - SubMenu configuration props
14
* @returns React component
15
*/
16
declare const SubMenu: React.ForwardRefExoticComponent<SubMenuProps & React.RefAttributes<HTMLLIElement>>;
17
18
interface SubMenuProps {
19
// Content
20
title?: React.ReactNode;
21
children?: React.ReactNode;
22
23
// State
24
disabled?: boolean;
25
26
// Popup Configuration
27
popupClassName?: string;
28
popupStyle?: React.CSSProperties;
29
popupOffset?: number[];
30
overflowedIndicator?: React.ReactNode;
31
32
// Icons
33
itemIcon?: React.ReactNode | ((props: any) => React.ReactNode);
34
expandIcon?: React.ReactNode | ((props: any) => React.ReactNode);
35
36
// Event Handlers
37
onTitleClick?: (info: { key: string; domEvent: React.MouseEvent | React.KeyboardEvent }) => void;
38
onTitleMouseEnter?: (info: { key: string; domEvent: React.MouseEvent }) => void;
39
onTitleMouseLeave?: (info: { key: string; domEvent: React.MouseEvent }) => void;
40
}
41
```
42
43
**Usage Examples:**
44
45
```typescript
46
import Menu, { SubMenu, MenuItem } from "rc-menu";
47
48
// Basic submenu
49
<Menu mode="vertical">
50
<MenuItem key="1">Option 1</MenuItem>
51
<SubMenu key="sub1" title="Sub Menu">
52
<MenuItem key="2">Sub Option 1</MenuItem>
53
<MenuItem key="3">Sub Option 2</MenuItem>
54
</SubMenu>
55
</Menu>
56
57
// Submenu with custom icon
58
<SubMenu
59
key="sub1"
60
title="Settings"
61
itemIcon={<SettingsIcon />}
62
expandIcon={({ isOpen }) => isOpen ? <UpIcon /> : <DownIcon />}
63
>
64
<MenuItem key="profile">Profile</MenuItem>
65
<MenuItem key="preferences">Preferences</MenuItem>
66
</SubMenu>
67
68
// Submenu with popup styling
69
<SubMenu
70
key="sub1"
71
title="Advanced"
72
popupClassName="custom-popup"
73
popupStyle={{ borderRadius: '8px', boxShadow: '0 4px 12px rgba(0,0,0,0.1)' }}
74
popupOffset={[0, 8]}
75
>
76
<MenuItem key="advanced1">Advanced Option 1</MenuItem>
77
<MenuItem key="advanced2">Advanced Option 2</MenuItem>
78
</SubMenu>
79
```
80
81
### Display Modes
82
83
SubMenu behavior changes based on the parent Menu's mode property.
84
85
**Inline Mode:**
86
87
```typescript
88
// SubMenus expand/collapse within the menu container
89
<Menu mode="inline" defaultOpenKeys={['sub1']}>
90
<MenuItem key="1">Item 1</MenuItem>
91
<SubMenu key="sub1" title="Inline SubMenu">
92
<MenuItem key="2">Sub Item 1</MenuItem>
93
<MenuItem key="3">Sub Item 2</MenuItem>
94
<SubMenu key="sub2" title="Nested SubMenu">
95
<MenuItem key="4">Nested Item</MenuItem>
96
</SubMenu>
97
</SubMenu>
98
</Menu>
99
```
100
101
**Vertical Mode:**
102
103
```typescript
104
// SubMenus appear as popups to the right
105
<Menu mode="vertical" triggerSubMenuAction="hover">
106
<MenuItem key="1">Item 1</MenuItem>
107
<SubMenu key="sub1" title="Vertical SubMenu">
108
<MenuItem key="2">Popup Item 1</MenuItem>
109
<MenuItem key="3">Popup Item 2</MenuItem>
110
</SubMenu>
111
</Menu>
112
```
113
114
**Horizontal Mode:**
115
116
```typescript
117
// SubMenus appear as dropdowns below
118
<Menu mode="horizontal" triggerSubMenuAction="hover">
119
<MenuItem key="1">Home</MenuItem>
120
<SubMenu key="sub1" title="Products">
121
<MenuItem key="2">Product 1</MenuItem>
122
<MenuItem key="3">Product 2</MenuItem>
123
</SubMenu>
124
<MenuItem key="4">About</MenuItem>
125
</Menu>
126
```
127
128
### Trigger Configuration
129
130
Configure how submenus open and close using different trigger actions.
131
132
```typescript
133
// Hover trigger (default for horizontal/vertical modes)
134
<Menu mode="vertical" triggerSubMenuAction="hover">
135
<SubMenu key="sub1" title="Hover to Open">
136
<MenuItem key="1">Item 1</MenuItem>
137
</SubMenu>
138
</Menu>
139
140
// Click trigger
141
<Menu mode="vertical" triggerSubMenuAction="click">
142
<SubMenu key="sub1" title="Click to Open">
143
<MenuItem key="1">Item 1</MenuItem>
144
</SubMenu>
145
</Menu>
146
147
// Custom delay timing
148
<Menu
149
mode="vertical"
150
triggerSubMenuAction="hover"
151
subMenuOpenDelay={0.2}
152
subMenuCloseDelay={0.3}
153
>
154
<SubMenu key="sub1" title="Delayed Hover">
155
<MenuItem key="1">Item 1</MenuItem>
156
</SubMenu>
157
</Menu>
158
```
159
160
### Event Handling
161
162
SubMenus provide detailed event handling for both the submenu container and title interactions.
163
164
```typescript
165
const handleTitleClick = (info: { key: string; domEvent: React.MouseEvent | React.KeyboardEvent }) => {
166
console.log('SubMenu title clicked:', info.key);
167
console.log('DOM event:', info.domEvent);
168
};
169
170
const handleTitleHover = (info: { key: string; domEvent: React.MouseEvent }) => {
171
console.log('SubMenu title hovered:', info.key);
172
};
173
174
const handleSubMenuHover = (info: { key: string; domEvent: React.MouseEvent }) => {
175
console.log('SubMenu container hovered:', info.key);
176
};
177
178
<SubMenu
179
key="sub1"
180
title="Event SubMenu"
181
onTitleClick={handleTitleClick}
182
onTitleMouseEnter={handleTitleHover}
183
onTitleMouseLeave={handleTitleHover}
184
onMouseEnter={handleSubMenuHover}
185
onMouseLeave={handleSubMenuHover}
186
>
187
<MenuItem key="1">Item 1</MenuItem>
188
<MenuItem key="2">Item 2</MenuItem>
189
</SubMenu>
190
```
191
192
### Nested SubMenus
193
194
SubMenus can be nested to create multi-level menu hierarchies.
195
196
```typescript
197
<Menu mode="inline" defaultOpenKeys={['sub1', 'sub1-1']}>
198
<MenuItem key="1">Top Level Item</MenuItem>
199
<SubMenu key="sub1" title="Level 1 SubMenu">
200
<MenuItem key="2">Level 1 Item</MenuItem>
201
<SubMenu key="sub1-1" title="Level 2 SubMenu">
202
<MenuItem key="3">Level 2 Item</MenuItem>
203
<SubMenu key="sub1-1-1" title="Level 3 SubMenu">
204
<MenuItem key="4">Level 3 Item</MenuItem>
205
</SubMenu>
206
</SubMenu>
207
</SubMenu>
208
</Menu>
209
```
210
211
### Popup Positioning and Styling
212
213
Fine-tune popup appearance and positioning for non-inline modes.
214
215
```typescript
216
// Custom popup container
217
const getPopupContainer = (node: HTMLElement) => {
218
return document.getElementById('menu-container') || document.body;
219
};
220
221
// Custom placements for popup positioning
222
const customPlacements = {
223
rightTop: {
224
points: ['tl', 'tr'],
225
overflow: { adjustX: 1, adjustY: 1 },
226
offset: [4, 0],
227
},
228
};
229
230
<Menu
231
mode="vertical"
232
getPopupContainer={getPopupContainer}
233
builtinPlacements={customPlacements}
234
>
235
<SubMenu
236
key="sub1"
237
title="Custom Positioned SubMenu"
238
popupClassName="custom-submenu-popup"
239
popupOffset={[8, 0]}
240
>
241
<MenuItem key="1">Custom Item 1</MenuItem>
242
<MenuItem key="2">Custom Item 2</MenuItem>
243
</SubMenu>
244
</Menu>
245
```
246
247
### SubMenu State Management
248
249
Control SubMenu open/close states programmatically.
250
251
```typescript
252
import { useState } from 'react';
253
254
const [openKeys, setOpenKeys] = useState<string[]>(['sub1']);
255
256
const handleOpenChange = (keys: string[]) => {
257
// Keep only one submenu open at a time
258
const latestOpenKey = keys.find(key => openKeys.indexOf(key) === -1);
259
setOpenKeys(latestOpenKey ? [latestOpenKey] : []);
260
};
261
262
<Menu
263
mode="inline"
264
openKeys={openKeys}
265
onOpenChange={handleOpenChange}
266
>
267
<SubMenu key="sub1" title="SubMenu 1">
268
<MenuItem key="1">Item 1</MenuItem>
269
</SubMenu>
270
<SubMenu key="sub2" title="SubMenu 2">
271
<MenuItem key="2">Item 2</MenuItem>
272
</SubMenu>
273
</Menu>
274
```
275
276
### Overflow Handling
277
278
Handle overflow scenarios in horizontal menus with custom indicators.
279
280
```typescript
281
<Menu mode="horizontal">
282
<MenuItem key="1">Item 1</MenuItem>
283
<MenuItem key="2">Item 2</MenuItem>
284
<MenuItem key="3">Item 3</MenuItem>
285
<SubMenu
286
key="sub1"
287
title="More Items"
288
overflowedIndicator={<MoreIcon />}
289
>
290
<MenuItem key="4">Overflow Item 1</MenuItem>
291
<MenuItem key="5">Overflow Item 2</MenuItem>
292
</SubMenu>
293
</Menu>
294
```