Skip to content

Commit e6f9cf6

Browse files
schloerkecpsievert
andauthored
fix(dataframe): Use absolute position text area over existing cell content (#1278)
Co-authored-by: Carson Sievert <[email protected]>
1 parent 8d45c26 commit e6f9cf6

File tree

4 files changed

+72
-49
lines changed

4 files changed

+72
-49
lines changed

js/dataframe/cell.tsx

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -332,25 +332,25 @@ export const TableBodyCell: FC<TableBodyCellProps> = ({
332332
setValue(e.target.value);
333333
}
334334

335-
// https://medium.com/@oherterich/creating-a-textarea-with-dynamic-height-using-react-and-typescript-5ed2d78d9848
336-
// Updates the height of a <textarea> when the value changes.
337-
const useAutosizeTextArea = (
338-
textAreaRef: HTMLTextAreaElement | null,
339-
value: string
340-
) => {
341-
useEffect(() => {
342-
if (textAreaRef) {
343-
// We need to reset the height momentarily to get the correct scrollHeight for the textarea
344-
textAreaRef.style.height = "0px";
345-
const scrollHeight = textAreaRef.scrollHeight;
346-
347-
// We then set the height directly, outside of the render loop
348-
// Trying to set this with state or a ref will product an incorrect value.
349-
textAreaRef.style.height = scrollHeight + "px";
350-
}
351-
}, [textAreaRef, value]);
352-
};
353-
useAutosizeTextArea(inputRef.current, value as string);
335+
// // https://medium.com/@oherterich/creating-a-textarea-with-dynamic-height-using-react-and-typescript-5ed2d78d9848
336+
// // Updates the height of a <textarea> when the value changes.
337+
// const useAutosizeTextArea = (
338+
// textAreaRef: HTMLTextAreaElement | null,
339+
// value: string
340+
// ) => {
341+
// useEffect(() => {
342+
// if (textAreaRef) {
343+
// // We need to reset the height momentarily to get the correct scrollHeight for the textarea
344+
// textAreaRef.style.height = "0px";
345+
// const scrollHeight = textAreaRef.scrollHeight;
346+
347+
// // We then set the height directly, outside of the render loop
348+
// // Trying to set this with state or a ref will product an incorrect value.
349+
// textAreaRef.style.height = scrollHeight + "px";
350+
// }
351+
// }, [textAreaRef, value]);
352+
// };
353+
// useAutosizeTextArea(inputRef.current, value as string);
354354

355355
let onClick:
356356
| ((e: ReactMouseEvent<HTMLTableCellElement>) => void)
@@ -361,21 +361,23 @@ export const TableBodyCell: FC<TableBodyCellProps> = ({
361361
const tableCellClass = CellStateClassEnum[cellState];
362362
// let cellContentEditable: boolean = false;
363363

364+
let editContent: ReactElement | null = null;
364365
if (cellState === CellStateEnum.EditSaving) {
365366
content = <em>{value as string}</em>;
366-
} else if (cellState === CellStateEnum.Editing) {
367-
content = (
368-
<textarea
369-
value={value as string}
370-
onChange={onChange}
371-
// onBlur={onBlur}
372-
onFocus={onFocus}
373-
onKeyDown={onInputKeyDown}
374-
ref={inputRef}
375-
style={{ width: "100%", height: "100%" }}
376-
/>
377-
);
378367
} else {
368+
if (cellState === CellStateEnum.Editing) {
369+
editContent = (
370+
<textarea
371+
value={value as string}
372+
onChange={onChange}
373+
// onBlur={onBlur}
374+
onFocus={onFocus}
375+
onKeyDown={onInputKeyDown}
376+
ref={inputRef}
377+
// style={{ width: "100%", height: "100%" }}
378+
/>
379+
);
380+
}
379381
// Only allow transition to edit mode if the cell can be edited
380382
if (editCellsIsAllowed) {
381383
onClick = (e: ReactMouseEvent<HTMLTableCellElement>) => {
@@ -419,6 +421,7 @@ export const TableBodyCell: FC<TableBodyCellProps> = ({
419421
title={cellTitle}
420422
className={tableCellClass}
421423
>
424+
{editContent}
422425
{content}
423426
</td>
424427
);

js/dataframe/styles.scss

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -273,13 +273,27 @@ shiny-data-frame {
273273
* # CELL EDITING STYLES
274274
*
275275
*/
276-
shiny-data-frame .shiny-data-grid > table > tbody > tr > td:has(> textarea.cell-edit-editing) {
277-
padding: 0;
278-
margin: 0;
276+
shiny-data-frame .shiny-data-grid > table > tbody > tr > td.cell-edit-editing {
277+
// padding: 0;
278+
// margin: 0;
279279

280+
:not(textarea) {
281+
visibility: hidden;
282+
}
283+
284+
color: transparent;
285+
286+
// Position the textarea over the existing cell via absolute positioning and inset
287+
// Use absolute positioning to ensure the textarea is using the full available space!
288+
position: relative;
280289
& > textarea {
281-
width: 100%;
282-
height: 100%;
290+
position: absolute;
291+
inset: var(--shiny-datagrid-padding-x) var(--shiny-datagrid-padding-y);
292+
293+
background-color: inherit;
294+
padding: 0px;
295+
// overflow: hidden;
296+
resize: none;
283297
}
284298
}
285299

0 commit comments

Comments
 (0)