Skip to content

Commit ca10bed

Browse files
authored
[lexical-playground] Bug Fix: Table action menu visibility with cell overflow (#7334)
1 parent 9a851da commit ca10bed

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

packages/lexical-playground/__tests__/e2e/Tables.spec.mjs

+56
Original file line numberDiff line numberDiff line change
@@ -6181,4 +6181,60 @@ test.describe.parallel('Tables', () => {
61816181
),
61826182
);
61836183
});
6184+
6185+
test(`Table action menu is hidden when cell overflows`, async ({
6186+
page,
6187+
isPlainText,
6188+
isCollab,
6189+
browserName,
6190+
}) => {
6191+
// The way that the clicks happen in test doesn't work in firefox for some reason
6192+
// but it does seem to work when you do it by hand
6193+
test.fixme(browserName === 'firefox');
6194+
test.skip(isPlainText || isCollab);
6195+
await initialize({isCollab, page});
6196+
await focusEditor(page);
6197+
6198+
// Insert a 2x2 table
6199+
await insertTable(page, 2, 2);
6200+
6201+
// Find and drag the column resize handle
6202+
const firstCell = await page.$('th >> nth=0');
6203+
const firstCellBox = await firstCell.boundingBox();
6204+
6205+
// Click the cell in 2nd column
6206+
await click(page, 'th >> nth=1');
6207+
6208+
// Check that the action menu button is visible when no overflow
6209+
const menuVisible = await page.evaluate(() => {
6210+
const button = document.querySelector('.table-cell-action-button');
6211+
// If button exists, menu is visible
6212+
return !!button;
6213+
});
6214+
6215+
expect(menuVisible).toBe(true);
6216+
6217+
// Make the column very wide to ensure overflow
6218+
await page.mouse.move(
6219+
firstCellBox.x + firstCellBox.width - 5,
6220+
firstCellBox.y + firstCellBox.height / 2,
6221+
);
6222+
await page.mouse.down();
6223+
await page.mouse.move(
6224+
firstCellBox.x + 2000, // Make column very wide - 2000 for more scroll space
6225+
firstCellBox.y + firstCellBox.height / 2,
6226+
);
6227+
await page.mouse.up();
6228+
6229+
// Click the cell
6230+
await click(page, 'th >> nth=0');
6231+
6232+
const menuHidden = await page.evaluate(() => {
6233+
const button = document.querySelector('.table-cell-action-button');
6234+
// If button doesn't exist, menu is hidden
6235+
return !button;
6236+
});
6237+
6238+
expect(menuHidden).toBe(true);
6239+
});
61846240
});

packages/lexical-playground/src/plugins/TableActionMenuPlugin/index.tsx

+42-1
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,35 @@ function TableCellActionMenuContainer({
799799

800800
const [colorPickerModal, showColorPickerModal] = useModal();
801801

802+
const checkTableCellOverflow = useCallback(
803+
(tableCellParentNodeDOM: HTMLElement): boolean => {
804+
const scrollableContainer = tableCellParentNodeDOM.closest(
805+
'.PlaygroundEditorTheme__tableScrollableWrapper',
806+
);
807+
if (scrollableContainer) {
808+
const containerRect = (
809+
scrollableContainer as HTMLElement
810+
).getBoundingClientRect();
811+
const cellRect = tableCellParentNodeDOM.getBoundingClientRect();
812+
813+
// Calculate where the action button would be positioned (5px from right edge of cell)
814+
// Also account for the button width and table cell padding (8px)
815+
const actionButtonRight = cellRect.right - 5;
816+
const actionButtonLeft = actionButtonRight - 28; // 20px width + 8px padding
817+
818+
// Only hide if the action button would overflow the container
819+
if (
820+
actionButtonRight > containerRect.right ||
821+
actionButtonLeft < containerRect.left
822+
) {
823+
return true;
824+
}
825+
}
826+
return false;
827+
},
828+
[],
829+
);
830+
802831
const $moveMenu = useCallback(() => {
803832
const menu = menuButtonRef.current;
804833
const selection = $getSelection();
@@ -845,6 +874,10 @@ function TableCellActionMenuContainer({
845874
return disable();
846875
}
847876

877+
if (checkTableCellOverflow(tableCellParentNodeDOM)) {
878+
return disable();
879+
}
880+
848881
const tableNode = $getTableNodeFromLexicalNodeOrThrow(
849882
tableCellNodeFromSelection,
850883
);
@@ -879,6 +912,14 @@ function TableCellActionMenuContainer({
879912
);
880913
tableObserver = getTableObserverFromTableElement(tableElement);
881914
tableCellParentNodeDOM = editor.getElementByKey(anchorNode.getKey());
915+
916+
if (tableCellParentNodeDOM === null) {
917+
return disable();
918+
}
919+
920+
if (checkTableCellOverflow(tableCellParentNodeDOM)) {
921+
return disable();
922+
}
882923
} else if (!activeElement) {
883924
return disable();
884925
}
@@ -901,7 +942,7 @@ function TableCellActionMenuContainer({
901942
const left = tableCellRect.right - anchorRect.left;
902943
menu.style.transform = `translate(${left}px, ${top}px)`;
903944
}
904-
}, [editor, anchorElem]);
945+
}, [editor, anchorElem, checkTableCellOverflow]);
905946

906947
useEffect(() => {
907948
// We call the $moveMenu callback every time the selection changes,

0 commit comments

Comments
 (0)