fix(richtext-lexical): inline editor is overlapping the clickable link editor for the first line
This commit is contained in:
@@ -7,11 +7,11 @@ html[data-theme='light'] {
|
||||
}
|
||||
|
||||
.link-editor {
|
||||
z-index: 10;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--color-base-0);
|
||||
padding: 0px 3.72px 0px 6.25px;
|
||||
padding: 0 3.72px 0 6.25px;
|
||||
vertical-align: middle;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
|
||||
@@ -52,7 +52,7 @@ html[data-theme='dark'] {
|
||||
vertical-align: middle;
|
||||
height: 37.5px;
|
||||
position: sticky;
|
||||
z-index: 2;
|
||||
z-index: 3;
|
||||
top: var(--doc-controls-height);
|
||||
margin-bottom: $baseline;
|
||||
border: $style-stroke-width-s solid var(--theme-elevation-150);
|
||||
|
||||
@@ -15,7 +15,7 @@ html[data-theme='light'] {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
z-index: 2;
|
||||
opacity: 0;
|
||||
border-radius: 6.25px;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
@@ -179,7 +179,7 @@ function InlineToolbar({
|
||||
floatingToolbarRef.current.style.pointerEvents = 'auto'
|
||||
}
|
||||
}
|
||||
}, [floatingToolbarRef])
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('mousemove', mouseMoveListener)
|
||||
@@ -200,6 +200,12 @@ function InlineToolbar({
|
||||
return
|
||||
}
|
||||
|
||||
const possibleLinkEditor = anchorElem.querySelector(':scope > .link-editor')
|
||||
const isLinkEditorVisible =
|
||||
possibleLinkEditor !== null &&
|
||||
'style' in possibleLinkEditor &&
|
||||
possibleLinkEditor?.style?.['opacity'] === '1'
|
||||
|
||||
const rootElement = editor.getRootElement()
|
||||
if (
|
||||
selection !== null &&
|
||||
@@ -211,28 +217,31 @@ function InlineToolbar({
|
||||
const rangeRect = getDOMRangeRect(nativeSelection, rootElement)
|
||||
|
||||
// Position floating toolbar
|
||||
const offsetIfFlipped = setFloatingElemPosition(
|
||||
rangeRect, // selection to position around
|
||||
floatingToolbarRef.current, // what to position
|
||||
anchorElem, // anchor elem
|
||||
'center',
|
||||
)
|
||||
const offsetIfFlipped = setFloatingElemPosition({
|
||||
alwaysDisplayOnTop: isLinkEditorVisible,
|
||||
anchorElem,
|
||||
floatingElem: floatingToolbarRef.current,
|
||||
horizontalPosition: 'center',
|
||||
targetRect: rangeRect,
|
||||
})
|
||||
|
||||
// Position caret
|
||||
if (caretRef.current) {
|
||||
setFloatingElemPosition(
|
||||
rangeRect, // selection to position around
|
||||
caretRef.current, // what to position
|
||||
floatingToolbarRef.current, // anchor elem
|
||||
'center',
|
||||
10,
|
||||
5,
|
||||
true,
|
||||
offsetIfFlipped,
|
||||
)
|
||||
setFloatingElemPosition({
|
||||
anchorElem: floatingToolbarRef.current,
|
||||
anchorFlippedOffset: offsetIfFlipped,
|
||||
floatingElem: caretRef.current,
|
||||
horizontalOffset: 5,
|
||||
horizontalPosition: 'center',
|
||||
specialHandlingForCaret: true,
|
||||
targetRect: rangeRect,
|
||||
verticalGap: 10,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
closeFloatingToolbar()
|
||||
}
|
||||
}, [editor, anchorElem])
|
||||
}, [editor, closeFloatingToolbar, anchorElem])
|
||||
|
||||
useEffect(() => {
|
||||
const scrollerElem = anchorElem.parentElement
|
||||
|
||||
@@ -5,16 +5,28 @@ const HORIZONTAL_OFFSET = 5
|
||||
// This is supposed to position the floatingElem based on the parent (anchorElem) and the target (targetRect) which is usually the selected text.
|
||||
// So basically, it positions the floatingElem either below or above the target (targetRect) and aligns it to the left or center of the target (targetRect).
|
||||
// This is used for positioning the floating toolbar (anchor: richtext editor) and its caret (anchor: floating toolbar)
|
||||
export function setFloatingElemPosition(
|
||||
targetRect: ClientRect | null,
|
||||
floatingElem: HTMLElement,
|
||||
anchorElem: HTMLElement,
|
||||
horizontalPosition: 'center' | 'left' = 'left',
|
||||
verticalGap: number = VERTICAL_GAP,
|
||||
horizontalOffset: number = HORIZONTAL_OFFSET,
|
||||
specialHandlingForCaret = false,
|
||||
anchorFlippedOffset = 0, // Offset which was added to the anchor (for caret, floating toolbar) if it was flipped
|
||||
): number {
|
||||
export function setFloatingElemPosition(args: {
|
||||
alwaysDisplayOnTop?: boolean
|
||||
anchorElem: HTMLElement
|
||||
anchorFlippedOffset?: number // Offset which was added to the anchor (for caret, floating toolbar) if it was flipped
|
||||
floatingElem: HTMLElement
|
||||
horizontalOffset?: number
|
||||
horizontalPosition?: 'center' | 'left'
|
||||
specialHandlingForCaret?: boolean
|
||||
targetRect: ClientRect | null
|
||||
verticalGap?: number
|
||||
}): number {
|
||||
const {
|
||||
alwaysDisplayOnTop = false,
|
||||
anchorElem,
|
||||
anchorFlippedOffset = 0, // Offset which was added to the anchor (for caret, floating toolbar) if it was flipped
|
||||
floatingElem,
|
||||
horizontalOffset = HORIZONTAL_OFFSET,
|
||||
horizontalPosition = 'left',
|
||||
specialHandlingForCaret = false,
|
||||
targetRect,
|
||||
verticalGap = VERTICAL_GAP,
|
||||
} = args
|
||||
// Returns the top offset if the target was flipped
|
||||
const scrollerElem = anchorElem.parentElement
|
||||
|
||||
@@ -37,7 +49,7 @@ export function setFloatingElemPosition(
|
||||
}
|
||||
|
||||
let addedToTop = 0
|
||||
if (top < editorScrollerRect.top && !specialHandlingForCaret) {
|
||||
if (!alwaysDisplayOnTop && top < editorScrollerRect.top && !specialHandlingForCaret) {
|
||||
addedToTop = floatingElemRect.height + targetRect.height + verticalGap * 2
|
||||
|
||||
top += addedToTop
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 2;
|
||||
z-index: 5;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
align-items: center;
|
||||
gap: var(--base);
|
||||
padding-bottom: 1px;
|
||||
z-index: 1;
|
||||
z-index: 4;
|
||||
height: var(--doc-controls-height);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user