Skip to content

Commit c5be795

Browse files
Fix suggestion list position
1 parent 33ef92a commit c5be795

4 files changed

Lines changed: 128 additions & 15 deletions

File tree

src/visualBuilder/components/Collab/ThreadPopup/CommentTextArea.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const CommentTextArea: React.FC<ICommentTextAreaProps> = React.memo(
1414
state,
1515
error,
1616
showSuggestions,
17+
cursorPosition,
1718
selectedIndex,
1819
filteredUsers,
1920
inputRef,
@@ -79,10 +80,16 @@ const CommentTextArea: React.FC<ICommentTextAreaProps> = React.memo(
7980
"collab-thread-body--input--textarea--suggestionsList"
8081
]
8182
)}
82-
// style={{
83-
// left: `${cursorPosition.left}px`,
84-
// top: `${cursorPosition.top}px`,
85-
// }}
83+
style={{
84+
...(cursorPosition.showAbove
85+
? {
86+
bottom: `${window.innerHeight - (inputRef.current?.getBoundingClientRect().top || 0) - cursorPosition.top}px`,
87+
top: "auto",
88+
}
89+
: {
90+
top: `${(inputRef.current?.getBoundingClientRect().top || 0) + cursorPosition.top}px`,
91+
}),
92+
}}
8693
ref={listRef}
8794
>
8895
{filteredUsers.map((user, index) => (

src/visualBuilder/generators/generateThread.tsx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,101 @@ export function updatePopupPositions() {
225225
});
226226
}
227227

228+
export function updateSuggestionListPosition() {
229+
const suggestionLists = document.querySelectorAll(
230+
".collab-thread-body--input--textarea--suggestionsList"
231+
);
232+
233+
if (!suggestionLists.length) return;
234+
235+
suggestionLists.forEach((list) => {
236+
if (!(list instanceof HTMLElement)) return;
237+
238+
const textarea = document.querySelector(
239+
".collab-thread-body--input--textarea"
240+
) as HTMLTextAreaElement | null;
241+
242+
if (!textarea) return;
243+
const positionData = list.getAttribute("data-position");
244+
const parsedData = positionData ? JSON.parse(positionData) : null;
245+
const showAbove = window.getComputedStyle(list).bottom !== "auto";
246+
const textareaRect = textarea.getBoundingClientRect();
247+
if (showAbove) {
248+
const lineHeight =
249+
parseInt(window.getComputedStyle(textarea).lineHeight) || 20;
250+
const paddingTop =
251+
parseInt(window.getComputedStyle(textarea).paddingTop) || 8;
252+
const cursorLineY =
253+
parsedData?.cursorLineY || paddingTop + lineHeight;
254+
255+
list.style.position = "fixed";
256+
list.style.bottom = `${window.innerHeight - textareaRect.top - cursorLineY + lineHeight}px`;
257+
list.style.top = "auto";
258+
} else {
259+
const lineHeight =
260+
parseInt(window.getComputedStyle(textarea).lineHeight) || 20;
261+
const paddingTop =
262+
parseInt(window.getComputedStyle(textarea).paddingTop) || 8;
263+
264+
const cursorLineY =
265+
parsedData?.cursorLineY || paddingTop + lineHeight;
266+
267+
list.style.position = "fixed";
268+
list.style.top = `${textareaRect.top + cursorLineY}px`;
269+
list.style.bottom = "auto";
270+
}
271+
272+
if (!positionData && textareaRect) {
273+
const lineHeight =
274+
parseInt(window.getComputedStyle(textarea).lineHeight) || 20;
275+
const paddingTop =
276+
parseInt(window.getComputedStyle(textarea).paddingTop) || 8;
277+
278+
const positionInfo = {
279+
showAbove: showAbove,
280+
cursorLineY: paddingTop + lineHeight,
281+
};
282+
list.setAttribute("data-position", JSON.stringify(positionInfo));
283+
}
284+
285+
const listRect = list.getBoundingClientRect();
286+
287+
if (!showAbove && listRect.bottom > window.innerHeight) {
288+
const lineHeight =
289+
parseInt(window.getComputedStyle(textarea).lineHeight) || 20;
290+
const paddingTop =
291+
parseInt(window.getComputedStyle(textarea).paddingTop) || 8;
292+
const cursorLineY =
293+
parsedData?.cursorLineY || paddingTop + lineHeight;
294+
295+
list.style.bottom = `${window.innerHeight - textareaRect.top - cursorLineY + lineHeight}px`;
296+
list.style.top = "auto";
297+
298+
if (positionData) {
299+
const updatedData = JSON.parse(positionData);
300+
updatedData.showAbove = true;
301+
list.setAttribute("data-position", JSON.stringify(updatedData));
302+
}
303+
} else if (showAbove && listRect.top < 0) {
304+
const lineHeight =
305+
parseInt(window.getComputedStyle(textarea).lineHeight) || 20;
306+
const paddingTop =
307+
parseInt(window.getComputedStyle(textarea).paddingTop) || 8;
308+
const cursorLineY =
309+
parsedData?.cursorLineY || paddingTop + lineHeight;
310+
311+
list.style.top = `${textareaRect.top + cursorLineY}px`;
312+
list.style.bottom = "auto";
313+
314+
if (positionData) {
315+
const updatedData = JSON.parse(positionData);
316+
updatedData.showAbove = false;
317+
list.setAttribute("data-position", JSON.stringify(updatedData));
318+
}
319+
}
320+
});
321+
}
322+
228323
export function calculatePopupPosition(
229324
button: HTMLElement,
230325
popup: HTMLElement

src/visualBuilder/hooks/useCommentTextArea.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ export const useCommentTextArea = (
4848
const [state, setState] = useState<ICommentState>(initialState);
4949

5050
const [showSuggestions, setShowSuggestions] = useState(false);
51-
const [cursorPosition, setCursorPosition] = useState({ top: 0, left: 0 });
51+
const [cursorPosition, setCursorPosition] = useState({
52+
top: 0,
53+
left: 0,
54+
showAbove: false,
55+
});
5256
const [searchTerm, setSearchTerm] = useState("");
5357
const [selectedIndex, setSelectedIndex] = useState(0);
5458
const [filteredUsers, setFilteredUsers] = useState<IMentionList[]>([]);
@@ -223,25 +227,27 @@ export const useCommentTextArea = (
223227
);
224228
document.body.removeChild(span);
225229

226-
const currentLineY = currentLineNumber * lineHeight + paddingTop;
230+
const scrollTop = textarea.scrollTop;
231+
const currentLineY =
232+
currentLineNumber * lineHeight + paddingTop - scrollTop;
227233
const nextLineY = currentLineY + lineHeight;
228234

229235
const viewportHeight = window.innerHeight;
230236
const suggestionsHeight = 160;
231237

232-
const spaceBelow =
233-
viewportHeight -
234-
(textarea.getBoundingClientRect().top + nextLineY);
238+
const textareaRect = textarea.getBoundingClientRect();
239+
const absoluteTop = textareaRect.top + nextLineY;
240+
const spaceBelow = viewportHeight - absoluteTop;
235241
const showAbove = spaceBelow < suggestionsHeight;
236-
237-
const top = showAbove
238-
? currentLineY - suggestionsHeight
239-
: nextLineY;
242+
const top = showAbove ? currentLineY : nextLineY;
240243

241244
return {
242245
top,
243246
left,
244247
showAbove,
248+
absoluteTop,
249+
scrollTop,
250+
currentLineNumber,
245251
};
246252
},
247253
[]

src/visualBuilder/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,11 @@ import {
4141
} from "./utils/updateFocussedState";
4242
import { useHighlightCommentIcon } from "./eventManager/useHighlightCommentIcon";
4343
import { updateHighlightedCommentIconPosition } from "./generators/generateHighlightedComment";
44-
import { updateCollabIconPosition } from "./generators/generateThread";
45-
import { updatePopupPositions } from "./generators/generateThread";
44+
import {
45+
updateCollabIconPosition,
46+
updatePopupPositions,
47+
updateSuggestionListPosition,
48+
} from "./generators/generateThread";
4649
import { useRecalculateVariantDataCSLPValues } from "./eventManager/useRecalculateVariantDataCSLPValues";
4750
import { VB_EmptyBlockParentClass } from "..";
4851
import { useCollab } from "./eventManager/useCollab";
@@ -98,6 +101,7 @@ export class VisualBuilder {
98101
private scrollEventHandler = () => {
99102
updateCollabIconPosition();
100103
updatePopupPositions();
104+
updateSuggestionListPosition();
101105
updateHighlightedCommentIconPosition(); // Update icons position
102106
};
103107

@@ -108,6 +112,7 @@ export class VisualBuilder {
108112
updateHighlightedCommentIconPosition();
109113
updateCollabIconPosition();
110114
updatePopupPositions();
115+
updateSuggestionListPosition();
111116
if (previousSelectedEditableDOM) {
112117
this.handlePositionChange(
113118
previousSelectedEditableDOM as HTMLElement

0 commit comments

Comments
 (0)