Overlay

Context Menu

A context menu displays a menu at the user's pointer.

On web, call BrowserContextMenu.disableContextMenu() to prevent the browser's native context menu from appearing.

1class ContextMenuExample extends StatefulWidget {
2 @override
3 State<ContextMenuExample> createState() => _ContextMenuState();
4}
5
6class _ContextMenuState extends State<ContextMenuExample> {
7 @override
8 void initState() {
9 super.initState();
10 unawaited(BrowserContextMenu.disableContextMenu());
11 }
12
13 @override
14 void dispose() {
15 unawaited(BrowserContextMenu.enableContextMenu());
16 super.dispose();
17 }
18
19 @override
20 Widget build(BuildContext context) => FContextMenu(
21 menu: [
22 .group(
23 children: [
24 .item(
25 prefix: const Icon(FLucideIcons.scissors),
26 title: const Text('Cut'),
27 onPress: () {},
28 ),
29 .item(
30 prefix: const Icon(FLucideIcons.copy),
31 title: const Text('Copy'),
32 onPress: () {},
33 ),
34 .item(
35 prefix: const Icon(FLucideIcons.clipboardPaste),
36 title: const Text('Paste'),
37 onPress: () {},
38 ),
39 ],
40 ),
41 .group(
42 children: [
43 .item(
44 prefix: const Icon(FLucideIcons.textSelect),
45 title: const Text('Select All'),
46 onPress: () {},
47 ),
48 ],
49 ),
50 ],
51 child: Container(
52 width: 350,
53 height: 200,
54 decoration: ShapeDecoration(
55 shape: RoundedSuperellipseBorder(
56 side: BorderSide(color: context.theme.colors.border),
57 borderRadius: context.theme.style.borderRadius.lg,
58 ),
59 ),
60 alignment: .center,
61 child: const Text('Right-click/long press here'),
62 ),
63 );
64}
65

Usage

FContextMenu(...)

1FContextMenu(
2 style: const .delta(maxWidth: 250),
3 longPress: null,
4 secondaryPress: null,
5 faded: null,
6 divider: .full,
7 menu: [
8 .group(
9 children: [
10 .item(title: const Text('Edit'), onPress: () {}),
11 .item(title: const Text('Delete'), onPress: () {}),
12 ],
13 ),
14 ],
15 menuBuilder: (context, controller, menu) => menu!,
16 builder: (context, controller, child) => child!,
17 child: const SizedBox.square(dimension: 200),
18)

FContextMenu.tiles(...)

1FContextMenu.tiles(
2 style: const .delta(maxWidth: 250),
3 longPress: null,
4 secondaryPress: null,
5 faded: null,
6 divider: .full,
7 menu: [
8 .group(
9 children: [
10 .tile(title: const Text('Edit'), onPress: () {}),
11 .tile(title: const Text('Delete'), onPress: () {}),
12 ],
13 ),
14 ],
15 menuBuilder: (context, controller, menu) => menu!,
16 builder: (context, controller, child) => child!,
17 child: const SizedBox.square(dimension: 200),
18)

Examples

Nested Submenu

1class NestedContextMenuExample extends StatefulWidget {
2 @override
3 State<NestedContextMenuExample> createState() => _NestedContextMenuState();
4}
5
6class _NestedContextMenuState extends State<NestedContextMenuExample> {
7 @override
8 void initState() {
9 super.initState();
10 unawaited(BrowserContextMenu.disableContextMenu());
11 }
12
13 @override
14 void dispose() {
15 unawaited(BrowserContextMenu.enableContextMenu());
16 super.dispose();
17 }
18
19 @override
20 Widget build(BuildContext _) => FContextMenu(
21 menu: [
22 .group(
23 children: [
24 .item(
25 prefix: const Icon(FLucideIcons.scissors),
26 title: const Text('Cut'),
27 onPress: () {},
28 ),
29 .item(
30 prefix: const Icon(FLucideIcons.copy),
31 title: const Text('Copy'),
32 onPress: () {},
33 ),
34 .item(
35 prefix: const Icon(FLucideIcons.clipboardPaste),
36 title: const Text('Paste'),
37 onPress: () {},
38 ),
39 .submenu(
40 title: const Text('Share'),
41 prefix: const Icon(FLucideIcons.share2),
42 submenu: [
43 .group(
44 children: [
45 .item(
46 prefix: const Icon(FLucideIcons.mail),
47 title: const Text('Email'),
48 onPress: () {},
49 ),
50 .item(
51 prefix: const Icon(FLucideIcons.messageSquare),
52 title: const Text('Message'),
53 onPress: () {},
54 ),
55 .item(
56 prefix: const Icon(FLucideIcons.link),
57 title: const Text('Copy Link'),
58 onPress: () {},
59 ),
60 ],
61 ),
62 ],
63 ),
64 ],
65 ),
66 .group(
67 children: [
68 .item(
69 prefix: const Icon(FLucideIcons.textSelect),
70 title: const Text('Select All'),
71 onPress: () {},
72 ),
73 ],
74 ),
75 ],
76 child: Container(
77 width: 350,
78 height: 200,
79 decoration: ShapeDecoration(
80 shape: RoundedSuperellipseBorder(
81 side: BorderSide(color: context.theme.colors.border),
82 borderRadius: context.theme.style.borderRadius.lg,
83 ),
84 ),
85 alignment: .center,
86 child: const Text('Right-click/long press here'),
87 ),
88 );
89}
90

Tiles

1class TileContextMenuExample extends StatefulWidget {
2 @override
3 State<TileContextMenuExample> createState() => _TileContextMenuState();
4}
5
6class _TileContextMenuState extends State<TileContextMenuExample> {
7 @override
8 void initState() {
9 super.initState();
10 unawaited(BrowserContextMenu.disableContextMenu());
11 }
12
13 @override
14 void dispose() {
15 unawaited(BrowserContextMenu.enableContextMenu());
16 super.dispose();
17 }
18
19 @override
20 Widget build(BuildContext _) =>
21 FContextMenu.tiles(
22 menu: [
23 .group(
24 children: [
25 .tile(
26 prefix: const Icon(FLucideIcons.scissors),
27 title: const Text('Cut'),
28 onPress: () {},
29 ),
30 .tile(
31 prefix: const Icon(FLucideIcons.copy),
32 title: const Text('Copy'),
33 onPress: () {},
34 ),
35 .tile(
36 prefix: const Icon(FLucideIcons.clipboardPaste),
37 title: const Text('Paste'),
38 onPress: () {},
39 ),
40 ],
41 ),
42 .group(
43 children: [
44 .tile(
45 prefix: const Icon(FLucideIcons.textSelect),
46 title: const Text('Select All'),
47 onPress: () {},
48 ),
49 ],
50 ),
51 ],
52 child: Container(
53 width: 350,
54 height: 200,
55 decoration: ShapeDecoration(
56 shape: RoundedSuperellipseBorder(
57 side: BorderSide(color: context.theme.colors.border),
58 borderRadius: context.theme.style.borderRadius.lg,
59 ),
60 ),
61 alignment: .center,
62 child: const Text('Right-click/long press here'),
63 ),
64 );
65}
66

On this page