vscode-webview-ui-toolkit
vscode-webview-ui-toolkit copied to clipboard
Not rendering newlines in DataGridCell
I think I might be hitting same/variation as #484 when the content being rendered from the data source has newlines.
Example content:
ZZZAboutHeader22
test Test
How it is rendered in the cell:
Expected rendering in the cell:
Hey @timheuer! I'm circling back to old issues this week and have some updates and a question!
Currently, it looks like data grid cells have a CSS declaration that might be causing this issue. Each cell is set with white-space: wrap; which actually seems to be a non-valid value for this property (whoops 😅) and defaults to collapsing all whitespace (including newlines) as a result. I've experimented with other values and landed on pre-line as the option that gets the closest to what you're looking for.
With that said, extra newlines are added when this value is present (for a yet-to-be-determined reason) and results in a cell that has more spacing/padding than it should.
Given the following code:
<vscode-data-grid id="default-grid" grid-template-columns="1fr 1fr 1fr 1fr" aria-label="Default"></vscode-data-grid>
const defaultDataGrid = document.getElementById("default-grid") as DataGrid;
defaultDataGrid.rowsData = [
{
column1: "Cell Data\nHello world",
column2: "Cell Data",
column3: "Cell Data",
column4: "Cell Data",
},
// More data...
];
vscode-data-grid-cell {
white-space: pre-line;
}
The following output is produced:
A question for you:
I'll try and experiment with all of this a bit more, but I've realized it would really help to have more details on how you're trying/hoping to implement and use this kind of functionality.
Specifically, how will newlines get added? Will it be like I've demonstrated above (i.e. adding intentional newline characters to strings), or be the result of user interaction/editing, since I know you've been working on an editable data grid for a while correct, or something else entirely?
The newlines would likely mostly be editing by interacting normally with keystrokes, e.g., "return" key activity.
Okay cool, and to extra extra clear those interactions are enabled with the contenteditable attribute right?
The casual update is I resolved the extra spacing issue, but if newlines will mainly come as a result of contenteditable I think I just discovered a new problem
those interactions are enabled with the
contenteditableattribute right?
Correct.
Okay, so I thinkkkk I may have something that works, but I would love a sanity check to make sure I haven't missed anything, especially in the editable data grid category.
I created a demo extension that shows off these changes using the editable-data-grid sample extension as a starting point. If you have some time next week to test it out and see if there are any glaring issues I'd greatly appreciate that.
We could even hop on a call to really chat through the details and potentially save some async back and forth if you have the time. Regardless, let me know and have a great weekend!
@hawkticehurst - looks good! spent about 7 minutes typing around, etc. -- like you note the arrow keys not being able to navigate the cursor while in edit.
is the resulting new line saving as \n or <br/>?
is the resulting new line saving as
\nor<br/>?
This is the part of the solution (and contenteditable at large?) I'm most uncertain about... I've been working on cataloging this all afternoon and a few scenarios occur when I look at dev tools while testing everything.
Scenario 1: \n is (seemingly) only used when directly embedded into predefined strings
Given the following code:
basicDataGrid.rowsData = [
{
name: "Tasha Hess\n\nHere's some text that already\ncomes with newlines included!",
email: "[email protected]",
phone: "(578) 194-4268",
country: "Canada",
},
// Other data...
];
A single string is inserted into the DOM (with the \n directly embedded in the string –– even though you can't see them in dev tools).
And corresponds to this rendered output:
Scenario 2: A combo of and separate strings are used when shift + enter keys are clicked
So a few different things happen when the shift + enter keys are clicked.
The first time these keys are clicked (used with existing content in a cell), a separate string with three instances of (i.e. the HTML entity for a "non-breaking space") is created.
As you then type out new content in the newline the text is appended before the characters.
This corresponds to the following rendered data grid cell:
If you keep clicking shift + enter to add even more newlines the number and location of entities don't change, but each new line is associated with a separate string.
Here's the corresponding output:
Scenario 3: <br> is used when deleting lines of content?
This is one of the more perplexing scenarios for me. If I were to click backspace to delete the previously shown output, once I get to the point where there's one line of content in the cell a <br> element is added for some (unknown to me) reason.
The separate strings of content and entities will be deleted (as expected), but then this <br> tag will be added??
Current thoughts/conclusions
From the brief bit of googling I've been doing this behavior seems to be coming from contenteditable more than the changes to CSS I've made.
Also while these weird inconsistencies make me uncomfortable from a programming perspective, it doesn't seem to affect the actual experience of creating newlines in a data grid cell... so maybe it's fine??
Also maybe you know more about how contenteditable should be behaving vs not?
One more update before the weekend, I finally figured out how to prevent the FAST data-grid arrow key behavior when in cell edit mode!
I updated the demo app with the change, so feel free to check it out (see the handleKeydown function in src/webview/main.ts) and do another round of testing on the demo.
I'll also update the actual editable-data-grid sample extension next week too.
@timheuer okay another interesting update.
I've been updating the editable data grid sample today with the new features (i.e. render new line with shift + enter and enable cursor movement when in edit mode) and I realized that without any of the earlier mentioned CSS changes to our core data-grid component, rendering newlines actually works just fine and is muchhh more consistent.
Namely, without the CSS changes only <br> is used to render newlines:
If you have some cycles to try this out, I'd love your feedback on whether this might be a better/more consistent solution for your needs.
The important parts are:
- When in cell edit mode, do nothing when
enter + shiftare clicked –– this will render a newline - When in cell edit mode, stop event propagation –– this will allow arrow keys to move the cursor
function handleKeydown(e: KeyboardEvent, cell: DataGridCell) {
if (!cell.hasAttribute("contenteditable") || cell.getAttribute("contenteditable") === "false") {
if (e.key === "Enter") {
// Enable cell edit mode
e.preventDefault();
setCellEditable(cell);
}
} else {
if (e.key === "Enter" && e.shiftKey) {
// When in cell edit mode do nothing, let default behavior execute –– render newline
} else if (e.key === "ArrowLeft" || e.key === "ArrowRight" || e.key === "ArrowUp" || e.key === "ArrowDown") {
// When in cell edit mode, arrow keys will move the cursor
// This will stop event propagation so that the underlying FAST
// data-grid arrow events are not triggered
e.stopPropagation();
} else if (e.key === "Enter" || e.key === "Escape") {
// Exit cell edit mode
e.preventDefault();
syncCellChanges(cell);
unsetCellEditable(cell);
}
}
}
The only drawback of this solution is that you cannot get a string predefined string to render a newline when using the rowsData API, but since you mentioned you expect user input to be the primary method of rendering newlines I'm hoping that trade might be okay.
Thanks, I think
will not be what I'm looking for in this scenario as my use cases are for localized strings that may/may not be HTML use cases. For context my extension: https://marketplace.visualstudio.com/items?itemName=TimHeuer.resx-editor
Okay got it! Thanks for the extra context, I'll take a look at your extension tomorrow and go from there