Foundation
Point Portal
A "floating" portal anchored at a specific point within a child widget's coordinate space.
This widget is typically used to create other high-level widgets, e.g., context menu. You should prefer those high-level widgets unless you're creating a custom widget.
1class PointPortalExample extends StatefulWidget {2 @override3 State<PointPortalExample> createState() => _State();4}56class _State extends State<PointPortalExample> {7 final _controller = OverlayPortalController();8 Offset _point = const Offset(75, 50);910 @override11 Widget build(BuildContext context) => FPointPortal(12 control: .managed(controller: _controller),13 point: _point,14 padding: const .all(5),15 portalBuilder: (context, _) => Container(16 decoration: BoxDecoration(17 color: context.theme.colors.background,18 border: .all(color: context.theme.colors.border),19 borderRadius: .circular(4),20 ),21 padding: const .only(left: 20, top: 14, right: 20, bottom: 10),22 child: SizedBox(23 width: 288,24 child: Column(25 mainAxisSize: .min,26 crossAxisAlignment: .start,27 children: [28 Text('Dimensions', style: context.theme.typography.body.md),29 const SizedBox(height: 7),30 Text(31 'Set the dimensions for the layer.',32 style: context.theme.typography.body.sm.copyWith(33 color: context.theme.colors.mutedForeground,34 fontWeight: FontWeight.w300,35 ),36 ),37 const SizedBox(height: 15),38 for (final (label, value) in [39 ('Width', '100%'),40 ('Max. Width', '300px'),41 ]) ...[42 Row(43 children: [44 Expanded(45 child: Text(label, style: context.theme.typography.body.sm),46 ),47 Expanded(48 flex: 2,49 child: FTextField(50 control: .managed(initial: TextEditingValue(text: value)),51 ),52 ),53 ],54 ),55 const SizedBox(height: 7),56 ],57 ],58 ),59 ),60 ),61 child: GestureDetector(62 onTapDown: (d) {63 setState(() => _point = d.localPosition);64 _controller.show();65 },66 child: Container(67 width: 300,68 height: 150,69 decoration: BoxDecoration(70 color: context.theme.colors.muted,71 borderRadius: .circular(4),72 ),73 alignment: .center,74 child: Text('Tap anywhere', style: context.theme.typography.body.sm),75 ),76 ),77 );78}79Usage
FPointPortal(...)
1FPointPortal(2 point: const Offset(100, 100),3 portalBuilder: (context, controller) => const Text('Portal content'),4 builder: (context, controller, child) => child!,5 child: const Text('Child'),6 barrier: null,7)