Make Placeholder component "element-query-like" responsive.#18745
Make Placeholder component "element-query-like" responsive.#18745
Conversation
packages/components/package.json
Outdated
| "mousetrap": "^1.6.2", | ||
| "re-resizable": "^6.0.0", | ||
| "react-dates": "^17.1.1", | ||
| "react-resize-aware": "^3.0.0-beta.7", |
There was a problem hiding this comment.
Relying on a beta probably isn't ideal, but their method of measuring DOM changes is superior to other packages like react-use-dimensions because it will trigger an update even when content changes outside of a render() cycle. Maybe react-use-dimensions is enough for this use case 🤷♂
Edit: With a polyfill, https://www.npmjs.com/package/@rehooks/component-size could work
There was a problem hiding this comment.
Apart from window resizing situations (and we know only devs and designers do that, right? 😂 ) is there any real need to update outside of render? If not, react-use-dimensions seems perfect for what we need. I'd be reluctant to go the component-size route because that polyfill for resize-observer is massive 🙀
There was a problem hiding this comment.
Apart from window resizing situations (and we know only devs and designers do that, right? 😂 ) is there any real need to update outside of render?
The update-on-resize is nice, but definitely something we can live without. Worst case, seems like we could apply a transition: width 0.2s ease; and at least have the resizing happen in a way that looks less jarring than an instant snap. 👍 👍
There was a problem hiding this comment.
Its not just window resizing that might cause the dimensions to change. If the width of another element grows or shrinks it might change dimensions of this element without this component having been re-rendered. The use of the iframe is a neat way of detecting these layout changes (roughly, when the iframe dimensions change it fires the resize event on the iframe window).
Given the multi-column layouts in the above screenshots, I think this case is probably something that we need to account for?
The polyfill is definitely huge! Can't wait for a native implementation that works in all browsers! Maybe we can offer the library author some assistance to get it out of beta.
There was a problem hiding this comment.
I'll reach out to the developer and see how we might be able to help.
Edit: Or we could refactor to use v2
There was a problem hiding this comment.
@jasmussen The author has released a new version for us! Try bumping the version to ^3.0.0.
|
As you can see from the deepest nesting level for the image, even more work is necessary, but this is a good start that improves the situation. Likely for the additional work, it might be worth looking at that in light of the new efforts ongoing in #18667. |
| @@ -1,15 +1,15 @@ | |||
| .components-placeholder { | |||
| position: relative; | |||
There was a problem hiding this comment.
This is required to position and size the resizeListener correctly.
There was a problem hiding this comment.
That comment might good in code.
|
Tried to see if some other web builders use similar placeholders. Wix, Weebly, and Squarespace pre-fill in placeholders with demo content or fake images, instead of opting for showing buttons like we do, so they aren't much help. Does any other CMS use block placeholders like we do? Notion works similarly to us, but has similar responsive problems on the desktop app. Anyone have the mobile app and can check how placeholders work there? |
|
Mailchimp has a block placeholder that is pretty similar to the WordPress interface. Mailchimp uses a single button for replacing an image rather than options for URL, media library, and direct upload. Personally, I think it would work well if the buttons had the same width/max-width and the text was centered on the button. I think this might add some continuity and possibly make them more accessible for mobile users. |
|
LivingDocs uses a square cross which is very classic Desktop Publishing-like, but with no buttons. I think the element query nature, of which this PR is just a very first early attempt, is the key way to improve this, as it allows us to optimize for both large and small contexts. The thing is, the placeholder or "setup state" for the block is, to many blocks, the best UI to show next steps, when there's space. Take the Cover block, it feels like it's using the color swatches in a really nice way, letting you quickly pick a color and get moving! |
|
I like the shift to left-aligned text. It feels slightly cleaner and easier to read to me. At the smallest breakpoint, I wonder if the placeholder could be reduced to just a single button that says "Add image…" or "Add media…" or something like that, with no placeholder title above. Would that reduce accessibility? Also, should there be an attempt to make the full placeholder description available at the smaller breakpoints somehow? Perhaps an info icon that opens a pop-up containing the description? |
It seems like it should be fine. The block name, even if a placeholder, will be announced as such, and when you tab into the "Add..." button it's behavior should be clear. Elements that are |
|
What's missing here? As the conversation continues in #18800, it could make sense to merge this as a first step on the path. |
565ffa8 to
0c2cac0
Compare
|
Rebased and gave it a good squash. |
8b41c29 to
734d155
Compare
|
Thank you @jameslnewell ! I bumped in f26db0c#diff-fcafbf9322186d9a2998fd8c67903791R49. I also gave this a good rebase and a squash to simplify a final review. Let me know if things look as they should! |
78136c4 to
7904999
Compare
7904999 to
e484608
Compare
|
It looks like the test failure is legitimate: It's probably because in the initial version of this PR, the resize-aware was used to simply not output the description node below the 320px breakpoint, but I moved that to be CSS classes with |
|
@jasmussen I'll look at the tests. |
|
I removed the "instructions" hiding unit test because it assumed the hiding was done in JS but it's done in CSS and it's harder to test that way. |
1 similar comment
|
I removed the "instructions" hiding unit test because it assumed the hiding was done in JS but it's done in CSS and it's harder to test that way. |
|
Thank you Riad, I'll merge when the checks pass. Props @jameslnewell. |
| 'components-placeholder', | ||
| ( width >= 320 ? 'is-large' : '' ), | ||
| ( width >= 160 && width < 320 ? 'is-medium' : '' ), | ||
| ( width < 160 ? 'is-small' : '' ), |
There was a problem hiding this comment.
One thing I note here is that in the documentation of react-resize-aware, it mentions how width would be null the first time the component is rendered:
This object contains the
widthandheightproperties, these properties are going to benullbefore the component rendered, and will return a number after the component rendered.
https://www.npmjs.com/package/react-resize-aware#api
The "fun" thing about null is that, in the context of these sorts of comparisons, it's treated the same as zero (related, specification).
So:
let width = null;
console.log( width < 160 );
// trueSo we'll always apply the is-small class on the first render, even if it ends up being that the element will actually occupy a large width.
I guess my question is:
- Must we have at least one of
is-large,is-medium, oris-small, and therefore it would be okay to useis-smallas the default until an accurate value can be determined? - Otherwise, would it be more correct to wait to assign any of these modifier classes until the true width can be determined?
There was a problem hiding this comment.
For context, I think this may be contributing to some intermittent failures in the end-to-end tests, where we're trying to click "Try again" when an embed fails, but the placement of the button might be shifting around because it is rendered after the "instructions" which are hidden while is-small class is applied.
This change updates the margins of the notice UI added to block placeholders using the `withNotices` mixin. The update was necessary after #18745 which made the content of block placeholders left-aligned.
This change updates the margins of the notice UI added to block placeholders using the `withNotices` mixin. The update was necessary after #18745 which made the content of block placeholders left-aligned.





This PR is courtesy of @jameslnewell who created the initial work in master...jameslnewell:element-queries. I added some additional commits but did not have the necessary access to James' repository, so I pushed it to origin instead. Let there be no doubt, props: @jameslnewell.
What this PR does, is make the
<Placeholder />component responsive using a custom form of element queries.Before:
After:
The above two screenshots also show why normal responsiveness is not sufficient. The Placeholder component is UI that needs to adapt to various nesting scenarios and dimensions.
To make that happen, I created 3 classes:
size-lg(size large) to the Placeholder component.size-md(size medium)size-sm(size small)For the time being, this solves a problem with the Placeholder component. However we have many other UI elements that can benefit from responsive improvements, so I would love to hear your thoughts on how we can refactor these utility classes to be perhaps more automated or generic or at the very least easy to apply beyond just this Placeholder component.
Design-wise I leveraged those utility classes to reduce the UI as the component grows smaller, including hiding descriptions and icons when there isn't space. I simply removed the Upload icon — it does not feel like it adds value but in fact adds visual clutter instead. Additionally, I left-aligned the text, Placeholder labels, and buttons. This most literally anchors the content in a way that really helps reduce the visual appearance when more than one placeholder is visible on the page at the same time, which is going to be increasingly likely as templates grow in strength!
Your thoughts are very welcome.