or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application-framework.mdcommands.mddependency-injection.mdevents-messaging.mdindex.mdkeybindings.mdmenus.mdpreferences-configuration.mdresources-files.mdwidgets-ui.md

menus.mddocs/

0

# Menus

1

2

Theia's menu system provides hierarchical menu management with dynamic contributions, context menus, and command integration for building comprehensive application interfaces.

3

4

## Capabilities

5

6

### Menu Model Registry

7

8

Central registry for menu structure and menu items.

9

10

```typescript { .api }

11

/**

12

* Registry for menu models and actions

13

*/

14

interface MenuModelRegistry {

15

/**

16

* Register menu action

17

* @param menuPath - Path to menu location

18

* @param item - Menu action to register

19

* @returns Disposable to unregister

20

*/

21

registerMenuAction(menuPath: MenuPath, item: MenuAction): Disposable;

22

23

/**

24

* Register submenu

25

* @param menuPath - Path to parent menu

26

* @param label - Submenu label

27

* @returns Menu path for the new submenu

28

*/

29

registerSubmenu(menuPath: MenuPath, label: string): MenuPath;

30

31

/**

32

* Get menu model for path

33

* @param menuPath - Menu path

34

* @returns Menu model

35

*/

36

getMenu(menuPath: MenuPath): CompositeMenuNode;

37

38

/**

39

* Get all menu paths

40

* @returns Array of menu paths

41

*/

42

getMenuPaths(): MenuPath[];

43

}

44

45

/**

46

* Service token for MenuModelRegistry

47

*/

48

const MenuModelRegistry: symbol;

49

```

50

51

### Menu Paths

52

53

Hierarchical menu location identifiers.

54

55

```typescript { .api }

56

/**

57

* Menu path array for identifying menu locations

58

*/

59

type MenuPath = string[];

60

61

/**

62

* Common menu paths

63

*/

64

namespace MenuPaths {

65

/** File menu */

66

const File: MenuPath;

67

68

/** Edit menu */

69

const Edit: MenuPath;

70

71

/** View menu */

72

const View: MenuPath;

73

74

/** Help menu */

75

const Help: MenuPath;

76

}

77

```

78

79

### Menu Actions

80

81

Individual menu items that execute commands.

82

83

```typescript { .api }

84

/**

85

* Menu action definition

86

*/

87

interface MenuAction {

88

/** Command to execute */

89

commandId: string;

90

91

/** Display label (overrides command label) */

92

label?: string;

93

94

/** Icon CSS class */

95

icon?: string;

96

97

/** Menu item order/priority */

98

order?: string;

99

100

/** Alt text for accessibility */

101

alt?: string;

102

103

/** When clause for conditional display */

104

when?: string;

105

106

/** Group for menu organization */

107

group?: string;

108

}

109

```

110

111

**Usage Example:**

112

113

```typescript

114

import { injectable, inject } from "@theia/core";

115

import { MenuModelRegistry, MenuAction } from "@theia/core/lib/common";

116

117

@injectable()

118

export class MyMenuContribution {

119

constructor(

120

@inject(MenuModelRegistry)

121

private readonly menus: MenuModelRegistry

122

) {}

123

124

registerMenus(): void {

125

// Register action in File menu

126

const openAction: MenuAction = {

127

commandId: 'my-extension.open-file',

128

label: 'Open Special File',

129

icon: 'fa fa-file-o',

130

order: '1',

131

group: 'file'

132

};

133

134

this.menus.registerMenuAction(['file'], openAction);

135

136

// Create submenu

137

const mySubmenu = this.menus.registerSubmenu(['view'], 'My Extension');

138

139

// Add actions to submenu

140

this.menus.registerMenuAction(mySubmenu, {

141

commandId: 'my-extension.show-panel',

142

label: 'Show Panel',

143

order: '1'

144

});

145

146

this.menus.registerMenuAction(mySubmenu, {

147

commandId: 'my-extension.settings',

148

label: 'Settings',

149

order: '2'

150

});

151

}

152

}

153

```

154

155

### Menu Nodes

156

157

Menu structure representation.

158

159

```typescript { .api }

160

/**

161

* Base menu node interface

162

*/

163

interface MenuNode {

164

/** Node identifier */

165

readonly id: string;

166

167

/** Display label */

168

readonly label?: string;

169

170

/** Icon CSS class */

171

readonly icon?: string;

172

173

/** Sort string for ordering */

174

readonly sortString?: string;

175

176

/** When clause for visibility */

177

readonly when?: string;

178

}

179

180

/**

181

* Composite menu node containing child nodes

182

*/

183

interface CompositeMenuNode extends MenuNode {

184

/** Child menu nodes */

185

readonly children: MenuNode[];

186

187

/** True if node has children */

188

readonly hasChildren: boolean;

189

}

190

191

/**

192

* Action menu node that executes commands

193

*/

194

interface ActionMenuNode extends MenuNode {

195

/** Command to execute */

196

readonly command: string;

197

198

/** Command arguments */

199

readonly args?: any[];

200

201

/** Alt text */

202

readonly alt?: string;

203

}

204

```

205

206

### Context Menus

207

208

Dynamic context menus for widgets and UI elements.

209

210

```typescript { .api }

211

/**

212

* Context menu renderer interface

213

*/

214

interface ContextMenuRenderer {

215

/**

216

* Render context menu

217

* @param menuPath - Menu path

218

* @param anchor - Anchor element or coordinates

219

* @param onHide - Callback when menu hides

220

*/

221

render(

222

menuPath: MenuPath,

223

anchor: Element | { x: number; y: number },

224

onHide?: () => void

225

): Promise<void>;

226

}

227

228

/**

229

* Service token for ContextMenuRenderer

230

*/

231

const ContextMenuRenderer: symbol;

232

```

233

234

**Usage Example:**

235

236

```typescript

237

import { inject, injectable } from "@theia/core";

238

import { ContextMenuRenderer } from "@theia/core/lib/browser";

239

240

@injectable()

241

export class MyWidget {

242

constructor(

243

@inject(ContextMenuRenderer)

244

private readonly contextMenuRenderer: ContextMenuRenderer

245

) {}

246

247

private handleContextMenu(event: MouseEvent): void {

248

event.preventDefault();

249

250

// Render context menu at mouse position

251

this.contextMenuRenderer.render(

252

['my-widget-context'],

253

{ x: event.clientX, y: event.clientY }

254

);

255

}

256

257

private setupContextMenu(): void {

258

// Register context menu items

259

this.menus.registerMenuAction(['my-widget-context'], {

260

commandId: 'my-widget.copy',

261

label: 'Copy',

262

order: '1'

263

});

264

265

this.menus.registerMenuAction(['my-widget-context'], {

266

commandId: 'my-widget.paste',

267

label: 'Paste',

268

order: '2'

269

});

270

}

271

}

272

```

273

274

### Menu Contribution

275

276

Extension point for contributing menus.

277

278

```typescript { .api }

279

/**

280

* Menu contribution interface

281

*/

282

interface MenuContribution {

283

/**

284

* Register menus

285

* @param menus - Menu model registry

286

*/

287

registerMenus(menus: MenuModelRegistry): void;

288

}

289

290

/**

291

* Service token for MenuContribution

292

*/

293

const MenuContribution: symbol;

294

```

295

296

## Advanced Features

297

298

### Conditional Menus

299

300

Menus that appear based on context conditions.

301

302

```typescript

303

// Register conditional menu action

304

this.menus.registerMenuAction(['edit'], {

305

commandId: 'editor.action.rename',

306

label: 'Rename Symbol',

307

when: 'editorHasRenameProvider && editorTextFocus'

308

});

309

```

310

311

### Menu Groups

312

313

Organize menu items into logical groups with separators.

314

315

```typescript

316

// Actions in same group appear together

317

this.menus.registerMenuAction(['file'], {

318

commandId: 'file.new',

319

group: 'new',

320

order: '1'

321

});

322

323

this.menus.registerMenuAction(['file'], {

324

commandId: 'file.open',

325

group: 'new',

326

order: '2'

327

});

328

329

// Different group creates separator

330

this.menus.registerMenuAction(['file'], {

331

commandId: 'file.save',

332

group: 'save',

333

order: '1'

334

});

335

```

336

337

## Types

338

339

```typescript { .api }

340

/**

341

* Menu-related type definitions

342

*/

343

type MenuItemRole = 'normal' | 'separator' | 'submenu';

344

345

interface MenuOptions {

346

role?: MenuItemRole;

347

type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio';

348

checked?: boolean;

349

enabled?: boolean;

350

visible?: boolean;

351

}

352

353

type MenuCallback = () => void;

354

```