block-options
block-options copied to clipboard
Indenting not working properly in blocks with multiple RichText fields
First of all, thank you so much for writing this plugin! It saved me after my users noticed all the TinyMCE features missing from Gutenberg, especially indenting :)
Unfortunately, per the title, EditorsKit approach to adding indents doesn't really work if a custom block has multiple RichText fields, because the indent is stored as a single block-level attribute, so it can't distinguish multiple fields.
Repro
here's a barebones block with two text fields:
import {registerBlockType} from '@wordpress/blocks'
import {RichText} from '@wordpress/block-editor'
registerBlockType('repro/test', {
title: 'Test',
category: 'common',
attributes: {
first: { type: 'string', source: 'html', selector: '.first', placeholder: 'First...' },
second: { type: 'string', source: 'html', selector: '.second', placeholder: 'Second...' },
},
edit: ({attributes: {first, second}, setAttributes}) => (
<div>
<RichText value={first} onChange={(value)=>setAttributes({first: value})} />
<RichText value={second} onChange={(value)=>setAttributes({second: value})} />
</div>
),
save: ({attributes: {first, second}}) => (
<div>
<RichText.Content tagName="div" className="first" value={first} />
<RichText.Content tagName="div" className="second" value={second} />
</div>
),
})
After pressing "Indent Increase" once in the first field and once in second field, i'd expect to see something like this on the site:
<div class="wp-block-repro-test">
<div class="first has-ek-indent" style="--ek-indent:20px">
First field
</div>
<div class="second has-ek-indent" style="--ek-indent:20px">
Second field
</div>
</div>
however the actual output has a double indent applied to the whole block instead of two separate single indents:
<div class="wp-block-repro-test has-ek-indent" style="--ek-indent:40px">
<div class="first">
First field
</div>
<div class="second">
Second field
</div>
</div>
From looking at the code, I know that this is happening because EditorsKit stores the indent level as a block attribute, so it can't tell there's two fields present -- it just sees that the indent was increased twice, and then applies that to the whole block.
Question
So my question is, do you think it'd be possible to make indenting a more "well-behaved" @wordpress/rich-text
format, and just mark the text up like most formats do? maybe switch it to just wrap the text in something like this:
<div class="has-ek-indent" data-ek-indent-level=3 data-ek-indent="60px">
...
</div>
and then do .has-ek-indent { padding-left: attr(data-ek-indent); }
on the frontend -- attr()
actually seems to have better browser support than var()
, so compatibility shouldn't be a concern.
I could take a stab at writing a PR if you think this is a good idea :)
i've implemented an indent format working (roughly) as described above over here.
(the interesting part is in apply
, you can safely ignore the GetTransform
stuff – that's there for unrelated reasons and is trivially converted to a normal Edit
)