- Issue created by @shyam_bhatt
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
@jessebaker reported the same problem ~2 hours later: ✨ Improve UI for empty states - Empty layout Closed: duplicate . Closed that as a duplicate.
Transfered what he wrote and merged it with @shyam_bhatt's write-up 👍
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
- 🇬🇧United Kingdom jessebaker
I believe at this point all that is left is the backend work to render the empty space inside the iFrame - basically taking the work done in
useRenderPreviewEmpty[Slot|Region]Placeholders
and doing it on the server side instead. - 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
BE:Because the placeholder is inserted into the preview iFrame after it has loaded it causes a noticeable layout shift every time the preview re-renders so this needs to be refactored and inserted/rendered on the back end.
What is the concrete before vs after that you're looking for? What markup needs to change? What API response needs to change?
- 🇬🇧United Kingdom jessebaker
When a request to the back end for the preview HTML is made currently the HTML returned contains HTML comments to denote the location of regions and slots. When a slot or the main content "region" is empty, the design calls for an empty space into which users can drop their first component to start making the page. The space is styled to have either a green or purple border. This border is rendered in the overlay. Inside the iFrame we simply need some blank space.
The blank space is created by inserting a div with a height and width. In head, we find the HTML comments and insert the div on the client side. This leads to a "jump" after the page is rendered as the new divs are inserted. If the placeholder div were inserted server side the jump would not happen.
So, when a request returns the preview HTML (e.g. a POST or PATCH to
/xb/api/v0/layout/xb_page/1
I'd like the HTML returned to already have placeholder divs in between the HTML comments.For empty regions:
In the markup an empty region currently looks like
<!-- xb-region-start-content --><!-- xb-region-end-content -->
I would like for it to look like this instead:
<!-- xb-region-start-content --><div class="xb--region-empty-placeholder"></div><!-- xb-region-end-content -->
As soon as there is anything rendered in the region, the
xb--region-empty-placeholder
should not be rendered.For empty slots
In the markup an empty slot currently looks like
<!-- xb-slot-start-d42bf579-4554-48e2-9438-b859e00d29d8/content --> <!-- xb-slot-end-d42bf579-4554-48e2-9438-b859e00d29d8/content -->
I would like for it to look like this instead:
<!-- xb-slot-start-d42bf579-4554-48e2-9438-b859e00d29d8/content --><div class="xb--slot-empty-placeholder"></div><!-- xb-slot-end-d42bf579-4554-48e2-9438-b859e00d29d8/content -->
As soon as there is anything rendered in the slot, the
xb--slot-empty-placeholder
should not be rendered.In addition - the server currently renders the first of a slot's examples from the SDC's yml into the slot. This shouldn't be happening. Currently the front end has to remove this markup.
slots: column_one: title: Column One description: The contents of the first column. examples: - <p>This is column 1 content</p> <--- this should not be rendered in XB
On the front end
Once the backend is inserting those DIVs the front end can then remove
ui/src/hooks/useRenderPreviewEmptySlotPlaceholders.ts
andui/src/hooks/useRenderPreviewEmptyRegionPlaceholder.ts
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
For empty regions: …
👎 This will inevitably trigger 🌱 [meta] Themes improperly check renderable arrays when determining visibility Needs work .
🏓 When does XB render an empty region? Only when it's just had its last component instance removed? Because since ✨ When a global region is empty, don't render HTML comment annotations into it Active we specifically don't render these!
In addition - the server currently renders the first of a slot's examples from the SDC's yml into the slot. This shouldn't be happening. Currently the front end has to remove this markup.
Hah! Should be an easy fix, and easily added test coverage for: in
\Drupal\Tests\experience_builder\Kernel\Plugin\ExperienceBuilder\ComponentSource\SingleDirectoryComponentTest::testGetClientSideInfo()
tests withisPreview: FALSE
. 👍For empty slots […]
- We can do this for SDCs, but then this is effectively blocked on
📌
Only run XbTwigExtension inside XBPreviewRenderer
Active
— otherwise we'll inevitably render
<!-- xb-slot-start-d42bf579-4554-48e2-9438-b859e00d29d8/content --><div class="xb--slot-empty-placeholder"></div><!-- xb-slot-end-d42bf579-4554-48e2-9438-b859e00d29d8/content -->
on the live site, too! 😨 - 🏓 We can't do that for code components … so how do you propose to tackle this for those? 😅 If they don't need this: why not?
- And that last point is generalizable: all future
\Drupal\experience_builder\ComponentSource\ComponentSourceWithSlotsInterface
implementations will need to consistently perform the same.
- We can do this for SDCs, but then this is effectively blocked on
📌
Only run XbTwigExtension inside XBPreviewRenderer
Active
— otherwise we'll inevitably render
- 🇬🇧United Kingdom jessebaker
When does XB render an empty region? Only when it's just had its last component instance removed?
This is a good point - I am specifically talking about the Content "region" when a new page is loaded. Other global regions don't need this.
It currently looks like this:
<!-- xb-region-start-content --> <!-- xb-region-end-content -->
and I'd like to see this instead:
<!-- xb-region-start-content --> <div class="xb--region-empty-placeholder"></div> <!-- xb-region-end-content -->
For empty slots [...]
- Ah, yes. I agree this would be blocked on that. I didn't realise the HTML comments were not already limited to only the XB preview
- Code components: We are already inserting the HTML comments around slots for code components. I think determining if they are empty is tricky. Perhaps inserting the placeholder can be done at a similar time in the process to the suggested solution here ✨ Unwrap astro-islands and astro-slots Active
- It seems that we need bespoke solutions for both SDC and JS components. I don't know if there is a way to generalise this implementation so that the process can happen no matter the ComponentSource.