-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Use stylesheets to give Editable components default styles #5206
Use stylesheets to give Editable components default styles #5206
Conversation
🦋 Changeset detectedLatest commit: d04fcca The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this is long needed improvement, and I appreciate your approach and detailed explanation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe you may be missing the commit to yarn.lock which is blocking the automated tests.
Thank you. I've added the yarn.lock change. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
As a note @kylemclean we accepted this and released it, but we do think there are things that could be done a bit more efficiently with respect to the observer logic that was added if you have time. Not urgent (unless the change causes a performance regression when more people upgrade). |
I can look into improving it. Are there any specific issues you can identify? |
This causes |
@dylans Should a polyfill be added for |
Yes I think it should be polyfilled Also this whole placeholder min height business seems pretty convoluted and error-prone at this point. I haven't really needed it to implement placeholders for elements so I'm not quite sure when it becomes required? Perhaps just leaving it for user-land with some examples might be a better idea in the future? |
@bryanph I'll try adding a polyfill for |
so all of the innerHtml calls destroyed content security policy. With this release, CSP doesn't really work with Slate unless we allow unsafe-inlinfe which is pretty bad. |
@vshlos Could you reply with the CSP you are using? |
Sorry, I forgot about the impact of innerHTML on CSP. We'll need to find another way and release an update. |
@dylans I have been reconsidering the changes made in this PR. I chose the method of dynamically injecting Unfortunately, dynamically injecting To summarize, here are two possible paths (there might other options that are better):
I'm leaning towards the latter option, so I might try implementing that along with the original fix to #4314 that I made. [1] https://cssinjs.org/csp/?v=v10.9.2 |
@kylemclean Agreed, sounds like the most straightforward path is the latter, and then if a better solution emerges we can pursue it separately. Thanks for your thorough response and explanation! |
Also keep in mind we are not really doing any custom styling at all. So even if you keep this approach, it should not be injecting a custom style element unless styles are provided. If you do want to keep supporting this, you can always use a nonce. Here is another library we are using that takes a nonce as a parameter and injects it into the style element that gets created: https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/guides/content-security-policy.md |
…aylor#5206) * Use stylesheet to give Editable components a default style * Give Editors a unique id * Use per-editor stylesheets to give editors a min-height * Make editor min-height respond to changes in placeholder height * Add changeset for stylesheet changes * Prevent unnecessary creations of ResizeObservers * Update yarn.lock
Description
This PR makes the default styles of an
Editable
component come from stylesheets added to the DOM rather than inline styles on the editor element. This resolves an issue in which setting theposition
,outline
,white-space
, orword-wrap
properties using theclassName
prop would have no effect. It also resolves issue #4314 in which setting themin-height
property on an editor would have no effect.Additionally, a change was made to make the
min-height
of editors change when the size of their placeholder element changes.Issue
Fixes: #4314
Example
Pictured is a modification of the custom placeholder example.
Old
The
min-height
changes have no effect, and the change tooutline
only has an effect when passed as part of thestyle
prop.New
The
min-height
andoutline
changes have an effect, regardless of whether they are set as part of a CSS class or on thestyle
prop.Context
Previously,
Editable
components used inline styles to set theirposition
,outline
,white-space
, andword-wrap
CSS properties to some chosen default values. These properties could be overridden by setting them with thestyle
prop on the component, but attempting to override them by setting theclassName
prop would not work because inline styles take precedence.Additionally, as detailed in #4314, code in the
Leaf
component sets themin-height
property on editors to the height of their placeholder to prevent the placeholder from overflowing the editor bounds. However, because this was done by directly setting an inline style on the editor element, users were unable to set themin-height
of an editor usingclassName
orstyle
props on the editor.I decided to solve the first issue by introducing a global
<style>
element that gets added to the DOM on the firstEditable
mount and removed on the lastEditable
unmount. It contains theposition
,outline
,white-space
, andword-wrap
properties that were previously passed to thestyle
prop of each editor. The CSS rule in this stylesheet uses the:where
pseudoclass to target editors, giving it 0 specificity and thus allowing user stylesheets to override its styles.The second issue required a bit more effort. Fixing the first issue allowed the
min-height
property to be changed by the user using a stylesheet or inline styles, but it still needed to be possible for themin-height
to default to the height of the placeholder element, and it needed to be done without using an inline style. There can be more than one editor on a page, each with its own unique placeholder height, so each editor needs its own defaultmin-height
. In order to have each editor element have a differentmin-height
without giving them inline styles, the editor elements need some sort of unique identifier. To accomplish this, I added anid
field to theEditor
type. When an editor is created, it simply uses a counter of the number ofEditor
instances created as itsid
, then increments a counter.Editor elements expose their identifier through their new
data-slate-editor-id
attribute. When anEditable
component mounts, it will now create a<style>
element that targets only itself using itsdata-slate-editor-id
attribute value.Leaf
components access that<style>
element through aWeakMap
and set themin-height
of the editor on it depending on the placeholder height. Because this stylesheet also uses the:where
pseudoclass, themin-height
can be overridden by a user stylesheet.During testing, I discovered an issue where sometimes the placeholder height that is measured will be inaccurate on initial page load, leading to the set
min-height
being incorrect until the component renders again. This was resolved by havingLeaf
components create aResizeObserver
that updates themin-height
of the editor element whenever the size of the placeholder element changes.Checks
yarn test
.yarn lint
. (Fix errors withyarn fix
.)yarn start
.)yarn changeset add
.)