From d65c65bb1edfcbc481bc3bc1f08ed1dba8345e4e Mon Sep 17 00:00:00 2001 From: Samarth Nimangre Date: Wed, 5 Aug 2026 05:32:42 +0000 Subject: [PATCH] fix(registry): set floating toolbar placement to bottom on mobile to prevent overlap (#4619) On mobile screens (iOS Safari / Android Chrome), native selection context menus pop up above text selection. FloatingToolbar defaulting to placement: 'top' caused direct overlap. Fix: - Use useIsMobile hook in FloatingToolbar (floating-toolbar.tsx) to set placement: 'bottom' on mobile viewports. - Update fallbackPlacements to prioritize bottom placements on mobile. - Add patch changeset for www registry UI. Closes #4619 --- ...oating-toolbar-mobile-placement-overlap.md | 5 ++++ apps/www/src/registry/ui/floating-toolbar.tsx | 23 +++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 .changeset/fix-floating-toolbar-mobile-placement-overlap.md diff --git a/.changeset/fix-floating-toolbar-mobile-placement-overlap.md b/.changeset/fix-floating-toolbar-mobile-placement-overlap.md new file mode 100644 index 0000000000..4ff4fd29a2 --- /dev/null +++ b/.changeset/fix-floating-toolbar-mobile-placement-overlap.md @@ -0,0 +1,5 @@ +--- +"www": patch +--- + +Fix `FloatingToolbar` overlapping with native mobile text selection context menus on mobile devices. Uses `useIsMobile` to set `placement: 'bottom'` on mobile viewports so custom floating toolbars render below selection instead of colliding with native mobile context menus. diff --git a/apps/www/src/registry/ui/floating-toolbar.tsx b/apps/www/src/registry/ui/floating-toolbar.tsx index f794bea9c6..206559fcad 100644 --- a/apps/www/src/registry/ui/floating-toolbar.tsx +++ b/apps/www/src/registry/ui/floating-toolbar.tsx @@ -17,6 +17,7 @@ import { usePluginOption, } from 'platejs/react'; +import { useIsMobile } from '@/hooks/use-mobile'; import { cn } from '@/lib/utils'; import { Toolbar } from './toolbar'; @@ -29,6 +30,7 @@ export function FloatingToolbar({ }: React.ComponentProps & { state?: FloatingToolbarState; }) { + const isMobile = useIsMobile(); const editorId = useEditorId(); const focusedEditorId = useEventEditorValue('focus'); const isFloatingLinkOpen = !!usePluginOption({ key: KEYS.link }, 'mode'); @@ -43,16 +45,23 @@ export function FloatingToolbar({ middleware: [ offset(12), flip({ - fallbackPlacements: [ - 'top-start', - 'top-end', - 'bottom-start', - 'bottom-end', - ], + fallbackPlacements: isMobile + ? [ + 'bottom-start', + 'bottom-end', + 'top-start', + 'top-end', + ] + : [ + 'top-start', + 'top-end', + 'bottom-start', + 'bottom-end', + ], padding: 12, }), ], - placement: 'top', + placement: isMobile ? 'bottom' : 'top', ...state?.floatingOptions, }, });