block-options icon indicating copy to clipboard operation
block-options copied to clipboard

Indenting not working properly in blocks with multiple RichText fields

Open lubieowoce opened this issue 4 years ago • 1 comments

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 :)

lubieowoce avatar Apr 19 '20 01:04 lubieowoce

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)

lubieowoce avatar Apr 26 '20 12:04 lubieowoce