or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdlayout-components.mdmenu-container.mdmenu-items.mdsubmenu-system.md

submenu-system.mddocs/

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

```