Skip to content

fix: chrome should not wrap mid-line #1423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 11, 2025
60 changes: 47 additions & 13 deletions packages/core/src/editor/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -77,23 +77,56 @@ Tippy popups that are appended to document.body directly
opacity: 0.001;
}

/**
Here be dragons!

The collaboration cursor caret needs to:
- exist in the dom as a non-zero width element, so that when hovering over it, the label can display
- yet, effectively not take up space in the dom, so that it doesn't cause wrapping or otherwise effect layout of the page

To achieve this, it took quite a bit of fiddling to figure out how to do this.

The caret is a span which has a before and after pseudo element.
The before element is what actually takes up space in the dom, and is colored via a border.
The color is actually set by reading the current color from the `.collaboration-cursor__caret` element. Allowing for dynamic coloring from JS.

There are a number of browser specific quirks with these hacks:
- Firefox differs from Chrome & Safari in that it will split a word that is wrapping if not displayed as inline-block (whereas the others need display: inline)
- Safari differs from Chrome & Firefox in that it needs the pseudo element to be position: relative to display a pseudo-element element with a negative margin

The word-joiner char (\u2060) is used to make sure the caret doesn't wrap around the text.

Therefore if modifying this code, please test in all major browsers to ensure that the caret is rendered correctly in all browsers.
**/

/* Give a remote user a caret */
.collaboration-cursor__caret {
outline: 1px solid #0d0d0d;
position: relative;
word-break: normal;
white-space: nowrap !important;
}

/* Allow the caret to be hovered over */
.collaboration-cursor__caret::after {
content: "";
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
width: 2px;
/* Allow the caret to be colored & hovered over */
.collaboration-cursor__caret::before {
/* Use currentColor to grab the color from the caret in set by JS */
border-left: 2px solid currentColor;
/* Make the cursor not actually take up the 2px of space within the element */
margin-left: -2px;
/* Fixes Safari's rendering of negative margin elements */
position: relative;
}

/* Firefox will split a word that is wrapping if not displayed as inline-block */
@-moz-document url-prefix() {
.collaboration-cursor__caret::before {
display: inline-block;
}
}

/* Add a word-joiner (\u2060) char to each side of the caret */
.collaboration-cursor__caret::after,
.collaboration-cursor__caret::before {
content: "⁠";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which one is here? Github doesn't show it
nbsp = https://www.compart.com/en/unicode/U+00A0
word joiner = https://www.compart.com/en/unicode/U+2060

the previous code had "word joiner"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

word joiner is there. I'll update the comment with the unicode to make it clear

}

/* Render the username above the caret */
Expand All @@ -103,10 +136,11 @@ Tippy popups that are appended to document.body directly
font-style: normal;
font-weight: 600;
line-height: normal;
left: 0;
left: -2px;
overflow: hidden;
position: absolute;
white-space: nowrap;
user-select: none;

color: transparent;
max-height: 5px;
Expand All @@ -121,8 +155,8 @@ Tippy popups that are appended to document.body directly
max-height: 1.1rem;
max-width: 20rem;
padding: 0.1rem 0.3rem;
top: -18px;
left: -1px;
top: -17px;
left: -2px;
border-radius: 3px 3px 3px 0;

transition: all 0.2s;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export const createCollaborationExtensions = (collaboration: {
const cursorElement = document.createElement("span");

cursorElement.classList.add("collaboration-cursor__caret");
cursorElement.setAttribute("style", `outline-color: ${user.color}`);
cursorElement.setAttribute("style", `color: ${user.color}`);
if (collaboration?.showCursorLabels === "always") {
cursorElement.setAttribute("data-active", "");
}
Expand All @@ -77,9 +77,7 @@ export const createCollaborationExtensions = (collaboration: {
labelElement.setAttribute("style", `background-color: ${user.color}`);
labelElement.insertBefore(document.createTextNode(user.name), null);

cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now let CSS insert these  

cursorElement.insertBefore(labelElement, null);
cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space

return cursorElement;
};
Expand Down
Loading