Skip to content

Commit f8d1841

Browse files
committed
fix(rich-md-editor): portal the toolbar + link card to body so a transformed ancestor can't offset them; align fade with the tooltip
1 parent 138a0c9 commit f8d1841

2 files changed

Lines changed: 13 additions & 5 deletions

File tree

apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ function hasFormattableSelection(editor: Editor, from: number, to: number): bool
3636
// a selection it stays put while the document scrolls instead of tracking the text — matching Linear.
3737
const FLOATING_OPTIONS = { strategy: 'fixed' } as const
3838

39+
// Render into the body so a transformed/clipping ancestor (e.g. the mothership panels) can't reparent
40+
// the fixed-positioned toolbar and shift it off the selection.
41+
const APPEND_TO_BODY = () => document.body
42+
3943
interface EditorBubbleMenuProps {
4044
editor: Editor
4145
/** The editor's scrollable viewport, used to keep the toolbar on-screen for selections taller than it. */
@@ -205,6 +209,7 @@ export function EditorBubbleMenu({ editor, scrollContainerRef }: EditorBubbleMen
205209
pluginKey={bubbleMenuKey}
206210
getReferencedVirtualElement={resolveAnchor}
207211
options={FLOATING_OPTIONS}
212+
appendTo={APPEND_TO_BODY}
208213
role='toolbar'
209214
aria-label='Text formatting'
210215
updateDelay={0}
@@ -217,7 +222,7 @@ export function EditorBubbleMenu({ editor, scrollContainerRef }: EditorBubbleMen
217222
if (isPointerDownRef.current) return false
218223
return hasFormattableSelection(e, from, to)
219224
}}
220-
className='fade-in-0 z-[var(--z-popover)] flex animate-in items-center gap-0.5 rounded-lg border border-[var(--border)] bg-[var(--bg)] p-1 shadow-sm duration-100 motion-reduce:animate-none'
225+
className='fade-in-0 z-[var(--z-popover)] flex animate-in items-center gap-0.5 rounded-lg border border-[var(--border)] bg-[var(--bg)] p-1 shadow-sm duration-150 ease-out motion-reduce:animate-none'
221226
>
222227
{isEditingLink ? (
223228
<>

apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/link-hover-card.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/d
33
import { getMarkRange } from '@tiptap/core'
44
import type { Editor } from '@tiptap/react'
55
import { Check, Copy, Pencil, Unlink } from 'lucide-react'
6+
import { createPortal } from 'react-dom'
67
import { normalizeLinkHref } from '../markdown-fidelity'
78
import { ToolbarButton } from './toolbar-button'
89

@@ -136,21 +137,22 @@ export function LinkHoverCard({ editor }: LinkHoverCardProps) {
136137
dismiss()
137138
}
138139

139-
return (
140+
return createPortal(
140141
<div
141142
ref={floatingRef}
142143
style={{
143144
position: 'fixed',
144145
top: 0,
145146
left: 0,
146147
transform: position ? `translate(${position.x}px, ${position.y}px)` : undefined,
147-
visibility: position ? 'visible' : 'hidden',
148+
opacity: position ? 1 : 0,
149+
pointerEvents: position ? undefined : 'none',
148150
}}
149151
role='dialog'
150152
aria-label='Link'
151153
onMouseEnter={cancelHide}
152154
onMouseLeave={scheduleHide}
153-
className='fade-in-0 z-[var(--z-popover)] flex animate-in items-center gap-0.5 rounded-lg border border-[var(--border)] bg-[var(--bg)] p-1 shadow-sm duration-100 motion-reduce:animate-none'
155+
className='z-[var(--z-popover)] flex items-center gap-0.5 rounded-lg border border-[var(--border)] bg-[var(--bg)] p-1 shadow-sm transition-opacity duration-150 ease-out'
154156
>
155157
{isEditing ? (
156158
<>
@@ -197,7 +199,8 @@ export function LinkHoverCard({ editor }: LinkHoverCardProps) {
197199
{canEdit && <ToolbarButton icon={Unlink} label='Remove link' onClick={removeLink} />}
198200
</>
199201
)}
200-
</div>
202+
</div>,
203+
document.body
201204
)
202205
}
203206

0 commit comments

Comments
 (0)