or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-components.mdindex.mdlayout-components.mdmenu-items.mdportal-context.mdsubmenus.md

submenus.mddocs/

0

# Submenus

1

2

Components for creating nested dropdown menus with submenu triggers and content areas. These components enable complex menu hierarchies with multiple levels of navigation.

3

4

## Capabilities

5

6

### DropdownMenuSub (Sub)

7

8

Container component that manages the state and behavior of a submenu.

9

10

```typescript { .api }

11

/**

12

* Container for submenu functionality

13

* @param children - Child components (typically SubTrigger and SubContent)

14

* @param open - Controlled open state of the submenu

15

* @param defaultOpen - Default open state (uncontrolled)

16

* @param onOpenChange - Callback when submenu open state changes

17

*/

18

interface DropdownMenuSubProps {

19

children?: React.ReactNode;

20

open?: boolean;

21

defaultOpen?: boolean;

22

onOpenChange?(open: boolean): void;

23

}

24

25

const DropdownMenuSub: React.FC<DropdownMenuSubProps>;

26

```

27

28

**Usage Examples:**

29

30

```typescript

31

// Uncontrolled submenu

32

<DropdownMenu.Sub>

33

<DropdownMenu.SubTrigger>More Options</DropdownMenu.SubTrigger>

34

<DropdownMenu.SubContent>

35

<DropdownMenu.Item>Nested Option 1</DropdownMenu.Item>

36

<DropdownMenu.Item>Nested Option 2</DropdownMenu.Item>

37

</DropdownMenu.SubContent>

38

</DropdownMenu.Sub>

39

40

// Controlled submenu

41

const [subOpen, setSubOpen] = React.useState(false);

42

<DropdownMenu.Sub open={subOpen} onOpenChange={setSubOpen}>

43

<DropdownMenu.SubTrigger>Controlled Submenu</DropdownMenu.SubTrigger>

44

<DropdownMenu.SubContent>

45

<DropdownMenu.Item>Nested Item</DropdownMenu.Item>

46

</DropdownMenu.SubContent>

47

</DropdownMenu.Sub>

48

```

49

50

### DropdownMenuSubTrigger (SubTrigger)

51

52

Trigger component that opens a submenu when hovered or activated with keyboard.

53

54

```typescript { .api }

55

/**

56

* Trigger for opening submenu

57

* @param disabled - Whether the trigger is disabled

58

* @param textValue - Text value for typeahead functionality

59

* @param asChild - Compose with child element

60

*/

61

interface DropdownMenuSubTriggerProps {

62

disabled?: boolean;

63

textValue?: string;

64

asChild?: boolean;

65

children?: React.ReactNode;

66

}

67

68

const DropdownMenuSubTrigger: React.ForwardRefExoticComponent<DropdownMenuSubTriggerProps>;

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

// Basic submenu trigger

75

<DropdownMenu.SubTrigger>

76

Share

77

<ChevronRightIcon />

78

</DropdownMenu.SubTrigger>

79

80

// Disabled submenu trigger

81

<DropdownMenu.SubTrigger disabled>

82

Unavailable Options

83

</DropdownMenu.SubTrigger>

84

85

// Custom submenu trigger using asChild

86

<DropdownMenu.SubTrigger asChild>

87

<button className="custom-submenu-trigger">

88

<ShareIcon />

89

Share Options

90

<ArrowIcon />

91

</button>

92

</DropdownMenu.SubTrigger>

93

```

94

95

### DropdownMenuSubContent (SubContent)

96

97

Content container for submenu items that appears when the submenu is triggered.

98

99

```typescript { .api }

100

/**

101

* Content container for submenu items

102

* Similar to DropdownMenuContent but for nested menus

103

* @param loop - Whether focus should loop when navigating

104

* @param onEscapeKeyDown - Callback when Escape key is pressed

105

* @param onKeyDown - Callback for key events

106

* @param forceMount - Force mounting regardless of open state

107

* @param container - Container element for portaling

108

*/

109

interface DropdownMenuSubContentProps {

110

loop?: boolean;

111

onEscapeKeyDown?: (event: KeyboardEvent) => void;

112

onKeyDown?: (event: KeyboardEvent) => void;

113

forceMount?: boolean;

114

container?: HTMLElement;

115

children?: React.ReactNode;

116

}

117

118

const DropdownMenuSubContent: React.ForwardRefExoticComponent<DropdownMenuSubContentProps>;

119

```

120

121

**Usage Examples:**

122

123

```typescript

124

// Basic submenu content

125

<DropdownMenu.SubContent>

126

<DropdownMenu.Item>Copy Link</DropdownMenu.Item>

127

<DropdownMenu.Item>Email</DropdownMenu.Item>

128

<DropdownMenu.Item>Print</DropdownMenu.Item>

129

</DropdownMenu.SubContent>

130

131

// Submenu content with custom behavior

132

<DropdownMenu.SubContent

133

loop={false}

134

onEscapeKeyDown={(e) => console.log('Escaping submenu')}

135

>

136

<DropdownMenu.Item>Option A</DropdownMenu.Item>

137

<DropdownMenu.Item>Option B</DropdownMenu.Item>

138

</DropdownMenu.SubContent>

139

```

140

141

## Complete Submenu Example

142

143

```typescript

144

function MultiLevelDropdownMenu() {

145

return (

146

<DropdownMenu.Root>

147

<DropdownMenu.Trigger>File</DropdownMenu.Trigger>

148

149

<DropdownMenu.Portal>

150

<DropdownMenu.Content>

151

<DropdownMenu.Item>New File</DropdownMenu.Item>

152

<DropdownMenu.Item>Open</DropdownMenu.Item>

153

154

<DropdownMenu.Separator />

155

156

{/* First level submenu */}

157

<DropdownMenu.Sub>

158

<DropdownMenu.SubTrigger>

159

Recent Files

160

<ChevronRightIcon />

161

</DropdownMenu.SubTrigger>

162

<DropdownMenu.SubContent>

163

<DropdownMenu.Item>document1.txt</DropdownMenu.Item>

164

<DropdownMenu.Item>document2.txt</DropdownMenu.Item>

165

166

{/* Second level submenu */}

167

<DropdownMenu.Sub>

168

<DropdownMenu.SubTrigger>

169

More Recent

170

<ChevronRightIcon />

171

</DropdownMenu.SubTrigger>

172

<DropdownMenu.SubContent>

173

<DropdownMenu.Item>old-file1.txt</DropdownMenu.Item>

174

<DropdownMenu.Item>old-file2.txt</DropdownMenu.Item>

175

</DropdownMenu.SubContent>

176

</DropdownMenu.Sub>

177

</DropdownMenu.SubContent>

178

</DropdownMenu.Sub>

179

180

<DropdownMenu.Sub>

181

<DropdownMenu.SubTrigger>

182

Export

183

<ChevronRightIcon />

184

</DropdownMenu.SubTrigger>

185

<DropdownMenu.SubContent>

186

<DropdownMenu.Item>Export as PDF</DropdownMenu.Item>

187

<DropdownMenu.Item>Export as HTML</DropdownMenu.Item>

188

<DropdownMenu.Item>Export as Markdown</DropdownMenu.Item>

189

</DropdownMenu.SubContent>

190

</DropdownMenu.Sub>

191

192

<DropdownMenu.Separator />

193

194

<DropdownMenu.Item>Close</DropdownMenu.Item>

195

</DropdownMenu.Content>

196

</DropdownMenu.Portal>

197

</DropdownMenu.Root>

198

);

199

}

200

```

201

202

## Keyboard Navigation

203

204

Submenus support full keyboard navigation:

205

206

- **Arrow Keys**: Navigate between items and into/out of submenus

207

- **Enter/Space**: Activate items or open submenus

208

- **Escape**: Close current submenu level

209

- **Home/End**: Jump to first/last item in current level

210

- **Letter keys**: Type-ahead search within current level

211

212

## Accessibility Features

213

214

- Proper ARIA attributes for nested menu structure

215

- Screen reader announcements for submenu state changes

216

- Focus management across menu levels

217

- Keyboard navigation between parent and child menus

218

- Automatic focus return when closing submenus

219

220

## Component Aliases

221

222

```typescript { .api }

223

// Short aliases for composition patterns

224

const Sub = DropdownMenuSub;

225

const SubTrigger = DropdownMenuSubTrigger;

226

const SubContent = DropdownMenuSubContent;

227

```

228

229

These submenu components enable the creation of complex, multi-level dropdown menus while maintaining full accessibility and keyboard navigation support.